본문 바로가기
프로그램 활용/인공지능(AI)

[자료수집] Yolov4 TensorFlow로 다루기(응용 개발법)

by 3604 2022. 7. 17.
728x90

Yolov4 TensorFlow로 다루기(응용 개발법)

출처: https://wiserloner.tistory.com/1187?category=825446
 
2년 전 by Prowd Loner

- 이전에 darknet에서 제공하는 yolov4를 다루어봤는데, 그 후속 글입니다.

저번 글의 경우에는 실제 모델이라기보다는, yolo를 이용한 간편한 영상 분석 프로그램을 사용하는 정도였죠...

 

이번엔 TensorFlow를 이용해서 직접 Yolov4 모델을 다루는 것을 알아봅시다.

이걸 다룰수 있게 되면, 말 그대로 컴퓨터가 시각 정보를 처리하는 인공지능을 달게되는 것으로, 딥러닝을 모르는 일반적인 프로그래머도 비교적 쉽게 객체 탐지 기능을 자신의 프로그램에 탑재할수 있게 될 것입니다.

(모듈 방식으로 엔진을 제작해서, 인터페이스에 맞게 개발하는 방식)

 

 

다시한번 YOLO로 뭘 만들수 있는지에 대한 예시. 

 

 

- 이 기술이 뭐가 좋냐면,

1. 모델을 보다 가시적으로 다룰수 있고 자유롭게 커스텀 가능.

아시다시피 텐서플로우를 이용해서 레이어단위로 인공신경망 모델을 다룸으로써 커스텀이 가능합니다.

만약 이를 개선해서 직접 더 좋은 모델로 fix해보고자 한다면 필요한 기술이죠.

2. 프로그래밍적으로 이용.

텐서플로를 라이브러리처럼 사용하여,

분석 결과와 같은 것들을 가져와서 사용하도록 하는 프로그램 작성시 자유롭습니다.

3. 모바일 개발 가능

TensorFlow Lite와 같은 것으로, 모바일 환경에서 이를 구동할수 있으므로 보다 재밌는 응용이 가능합니다.

 

저의 경우에는 yolo는 그냥 어떠한 객체가 어디에 위치해있는지만 탐지하는 역할로 사용하고, 그것을 이용하여 ROI를 추출한 후, Triplet Loss를 사용한 이미지 비교 모델에 넣어주어 안면인식이나 혹은 이상 상황 감지 등을 해보려고 합니다.

화재, 구역 침입, 모션 인식 등에도 사용이 가능할 것이라고 보네요.(face landmark나 skeleton detector 등은 자료를 찾는 중입니다.)

 

- 공부 출처는 https://www.youtube.com/watch?v=iPwepy-SVCQ입니다.

유튜버 The AI Guy는 yolo 관련해서 매우 유용하고 자세하게,

실제 코드와 개발 영상까지 제공해주는 채널입니다.

강추합니다.

 

- 주요사항

주로 보실 것은, 텐서플로에서 출력되는 출력값과, 전체적인 흐름입니다.

미리 기본적인 이미지 분석 및 동영상 분석용 프로그램 코드는 제공되는데, 이를 보고, 텐서플로 출력값에서 나오는 정보를 이용하여, 분석 프로세스 안에 자신이 원하는 기능을 끼워넣을수가 있습니다.

예를들면, 그냥 객체의 bbox와 클래스만 식별하는게 아니라, 어떤 클래스가 검출되면, 경고표시를 한다거나, 화면내 정보를 통계낸다거나, 특정 클래스의 정보를 다른 모듈에 전달해서 처리하도록 하거나 하는 등의 일이 가능해집니다.

 

- 준비사항.

https://github.com/theAIGuysCode/tensorflow-yolov4-tflite

에서 코드를 clone해줍니다.(이 코드가 핵심으로, 이번엔 응용법만 간단히 정리하고, 코드리뷰는 하지 않습니다.)

 

당연히 텐서플로이기에 파이썬 개발환경을 준비해주시고,

IDE는 Visual Studio Code를 사용할 것입니다.

 

(현재 노트북이 말썽이라 실습 환경이 못됩니다.

코드 작성 및 리뷰만 하고 실제 실행 결과는 못 보여드립니다;; 추후 포멧 후 실행할 예정.)

 

0 준비

cmd를 열고,

위의 깃허브 클론한 위치로 이동합니다.

그리고 그곳의 yml 파일을 이용해 아나콘다 환경을 설정할 것입니다.(아나콘다 설치 환경일때.)

 

conda env create -f conda-cpu.yml

conda activate yolov4-cpu

 

위와 같이 명령어를 실행시키면, yaml 파일에 설정된 설정환경이 아나콘다에 적용되고, 

yolov4-cpu가 실행됩니다.

 

만약 gpu 환경으로 하고 싶다면, 위에서 -cpu를 -gpu로 변경만 해주면 됩니다.

 

만일 pip로 설치하고 싶다면,

pip install -r requirements.txt

를 하시거나, 혹은

pip install -r requirements-gpu.txt

를 하시면 됩니다.

 

이제 공식 제공되는 yolov4의 훈련된 가중치를 다운로드 합시다.

https://drive.google.com/file/d/1cewMfusmPjYWbrnuJRuKhPMwRe_b9PaT/view에서 받으실수 있습니다.

 

이 weights 파일을, 아까 clone한 프로젝트 폴더 내의 data 폴더에 이동시킵니다.

만일 커스텀 트레이닝한 가중치 파일을 사용하고 싶다면,

https://wiserloner.tistory.com/1181에서 했던 방식으로 간편하게 학습을 진행한 후, 그 weights 파일을 사용하는 것이 더 편할 것입니다.

 

1. 텐서플로로 이식

python save_model.py --weights ./data/yolov4.weights --output ./checkpoints/yolov4-416 --input_size 416 --model yolov4 

위와 같이 아주 쉽게 추출이 가능합니다.

인자값에 따라서 아주 쉽게 텐서플로 모델을 만들수 있으며, weights는 위에서 준비한 것을 사용하고, output으로 해당 경로에 출력파일이 저장될 것입니다.

input size나, 사용하는 yolo 모델을 작성해주고 실행시키면, 텐서플로 모델 파일이 출력되니, 이를 이용하면 됩니다.

 

실제 실행시키면 yolov4를 해석하며, tensorflow 레이어로 이를 작성하게 됩니다.(이에대한 코드 리뷰도 할까 했는데 그냥 관둡니다. 관심있으시면 한번 해석해보세요.)

마지막으로 summary가 출력되며, checkpoints/yolov4-416 폴더 내에 관련 파일들이 저장될 것입니다.

 

참고로, 커스텀 한 것 역시 동일한 방식으로 하시면 됩니다.

weights에 해당 가중치 파일을 넣어주고, 변경할 것이 있다면 변경하면 됩니다.

 

# Convert darknet weights to tensorflow
## yolov4
python save_model.py --weights ./data/yolov4.weights --output ./checkpoints/yolov4-416 --input_size 416 --model yolov4 

# yolov4-tiny
python save_model.py --weights ./data/yolov4-tiny.weights --output ./checkpoints/yolov4-tiny-416 --input_size 416 --model yolov4 --tiny

# custom yolov4
python save_model.py --weights ./data/custom.weights --output ./checkpoints/custom-416 --input_size 416 --model yolov4 

 

2. 이미지 분석

# Run yolov4 tensorflow model
python detect.py --weights ./checkpoints/yolov4-416 --size 416 --model yolov4 --images ./data/images/kite.jpg

# Run yolov4-tiny tensorflow model
python detect.py --weights ./checkpoints/yolov4-tiny-416 --size 416 --model yolov4 --images ./data/images/kite.jpg --tiny

# Run custom yolov4 tensorflow model
python detect.py --weights ./checkpoints/custom-416 --size 416 --model yolov4 --images ./data/images/car.jpg

이미지에 대한 객체 탐지의 경우는, 제공되는 detect.py를 이용하면 됩니다.

그냥 이대로만 사용하니 뭔가 그냥 darknet yolo를 사용하는것 같죠?

detect.py 코드를 보시면 됩니다.

그 안에, tf 모델을 통해 출력된 결과 데이터를 가지고 처리를 하는 코드가 존재합니다.

추후 간략히 코드를 살펴볼텐데,

일단 위에서 save한 모델을 이용해서, tf로 yolo 모델을 돌려서 처리하는 모든 프로세스가 코드로 제공된 것이라 보면 됩니다.

만약 원하신다면 이 detect.py 코드를 다른 프로젝트에 import하셔서 사용하셔도 되고, 이를 기반으로, 중간에 정보가 처리되는 구간에 자신의 커스텀 알고리즘을 작성해서 정보를 이용하셔도 됩니다.

 

3. 동영상 분석.

# Run yolov4 on video
python detect_video.py --weights ./checkpoints/yolov4-416 --size 416 --model yolov4 --video ./data/video/video.mp4 --output ./detections/results.avi

# Run custom yolov4 model on video
python detect_video.py --weights ./checkpoints/custom-416 --size 416 --model yolov4 --video ./data/video/cars.mp4 --output ./detections/results.avi

# Run yolov4 on webcam
python detect_video.py --weights ./checkpoints/yolov4-416 --size 416 --model yolov4 --video 0 --output ./detections/results.avi

이미지 분석과 사용법이 동일합니다.

 

- 간단 코드분석.

(save_model.py)

말 그대로 yolo의 모델을 해석해 tf 모델로 저장하는 역할을 합니다.

utils와 같은 것은 직접 확인해보세요.

설정값에 따라 yolo 모델의 내부 구조 파라미터를 반환하는 역할을 합니다.

 

나머지는 실제 텐서플로를 작성할 때처럼, 레이어 하나하나를 설정하며 작성합니다.

가장 처음인 

  input_layer = tf.keras.layers.Input([FLAGS.input_size, FLAGS.input_size, 3])

에서 입력층 레이어를 만든 것에서,

feature_maps = YOLO(input_layer, NUM_CLASS, FLAGS.model, FLAGS.tiny)

으로, 입력층을 받아서 코드 제작자가 커스텀한 YOLO를 마치 계층처럼 쌓아올리고,

여기서 받아온 레이어들을 다시 순회하며,

바운딩 박스의 좌표를 회귀하는 출력층과, 그곳의 클래스를 분류하는 출력층을 묶어서 반환하도록 합니다.

pred = tf.concat([boxes, pred_conf], axis=-1)

이 둘을 위와 같이 하나로 묶어서 최종적으로

 model = tf.keras.Model(input_layer, pred)

이렇게 텐서플로 모델을 작성하면, yolo를 텐서플로 모델로 만든 것이 됩니다.

여기서 응용하시려면 그냥 이를통해 입력값을 넣어주시고 해도 문제는 없습니다.

물론, 텐서플로 2.0을 아신다는 가정 하에...

여기까진 일단 구조를 만든 것이고,

미리 학습시킨 가중치를 사용하려면,

utils.load_weights(model, FLAGS.weights, FLAGS.model, FLAGS.tiny)
  model.summary()
  model.save(FLAGS.output)

이처럼 load_weights를 하고, 마지막에는 model.save까지 해주시면, 인자값으로 정한 output 경로에 해당 모델 정보가 저장될 것입니다.

 

참고로 너무 간략히 설명했죠?

이건 코드가 너무 좋은데, 깔끔하게 설명하기 어려워서 따로 정리할 것입니다.

저는 이 코드를 일단 제 깃허브에 fork해두고, 앞으로 개발 템플릿으로 삼을 생각이고, 일단 분석한 이후, 다른 개발의 초석으로 삼을 예정입니다.

(최근들어 본 가장 깔끔한 코드라서 즐겁네요.)

 

(detect.py)

객체 탐지 모델에 필요한 내용이 들어있는 코드입니다.

이것은 이미지를 분석하는 코드네요.

위에서 모델을 만들었으니 이를 응용해서 사용하는 코드입니다.

프로세스의 흐름에 주의하며, 그냥 객체 탐지용으로 사용하려면 그냥 yolo를 그대로 사용하는게 좋을텐데, 굳이 이렇게 코드로 다루는 이유는 말 안해도 알겠죠?

중간중간 중요한 부분을 찝을테니 해당 부분을 커스텀하면 원하는 객체 탐지 프로그램을 만들수 있을 것입니다.

 

개발자 입장에선 다른건 볼것 없이,

boxes, scores, classes, valid_detections = tf.image.combined_non_max_suppression(
            boxes=tf.reshape(boxes, (tf.shape(boxes)[0], -1, 1, 4)),
            scores=tf.reshape(
                pred_conf, (tf.shape(pred_conf)[0], -1, tf.shape(pred_conf)[-1])),
            max_output_size_per_class=50,
            max_total_size=50,
            iou_threshold=FLAGS.iou,
            score_threshold=FLAGS.score
        )
        pred_bbox = [boxes.numpy(), scores.numpy(), classes.numpy(), valid_detections.numpy()]

이것 뒤에 원하는 알고리즘을 넣으면 됩니다.

 

자, 위에서는 이미지를 가져오고, 모델을 가져오고, 변수를 준비하는 등의 일을 담당했다면, 실질적으로 예측을 실행해 결과를 출력하는 모델의 최종부분이 이곳입니다.

여기서 나온 boxes는, 검출된 바운딩 박스, 그리고 scores는 검출 정확도, classes는 해당하는 클래스, valid_detections는 검출된 유효한 박스의 개수를 의미합니다.

 

이 정보가 객체 탐지로 얻어올수 있는 정보의 모든것이므로, 이를 넘파이 배열로 감싼 pred_bbox를 이용하면 원하는 처리를 할수 있을 것입니다.

 

이에대해 보다 잘 이해하시려면,

utils의 draw_bbox 메소드를 확인하시면, pred_bbox를 어떻게 이용한지를 잘 나타냅니다.

 

detect_video.py 역시 위와 동일한데,

pred_bbox를 잘 이용하면 되는건 마찬가지입니다.

이미지를 중첩한 것과 같은 동영상의 특성상 while문이 true로 무한반복 되며 영상을 읽어나가는데, pred_bbox가 갱신될때마다의 처리를 해주면 됩니다.

 

 

- 마지막으로 응용...

음... 아무래도 위에서는 아무나 다 개발이 가능하다 했는데, 그래도 텐서플로 2는 다룰줄 알아야 조금은 수월하지 않을까 생각합니다.

 

model을 추출해내고, 그것을 실행시켜 bbox와 class, 정확도를 얻어내도록 라이브러리를 만들면, 아마 파이썬 어떤 프로그래밍에도 적용이 가능할 것입니다.

 

유튜브 강사분께선 이를 이용해 간단히 특정 물체 count 프로그램을 만드셨는데, 그런식으로 사용해도 되고, 좀 불법적인 이야기를 하자면, FPS 게임 핵을 만들때, 캐릭터를 탐지하도록 하고, 적군이 판명되면, 현 마우스 에임 위치와 가까운 바운딩 박스를 선별해서, 그 구역에 마우스 포인트가 도달하도록 프로그래밍을 하는 방식으로 개발도 가능하겠네요.

(실제로 만들어본적도 없고 게임핵은 만들 생각 없습니다. 게다가 최신 핵에 대해 기술적으로 호기심은 존재하는데, 실제 이러한 방식이 쓰이는지는 모르겠네요... 일단 사용이야 가능하리라 보는데... ㅎㅎ 보다 자연스러운 움직임을 위해 여러가지 추가하고...)

 

- 어쨌건 이상입니다.

텐서플로보다 토치가 더 편하신 분들이 있을텐데, 아마 찾아보면 있을 것입니다.

전 일단 아직 토치를 사용해야하는 의의를 못느껴서...

개인적으로, 이번 코드가 너무 깔끔한지라 좀 분석이 필요할것 같습니다.

 

분석하여 다른 언어로 옮길수 있다면 옮겨보면 좋겠지만, 아마 전 하지 않을것 같네요. 텐서플로랑 넘파이 등 파이썬 라이브러리가 다른언어로 옮기면 얼마나 노가다가 될지...

그래도 컴퓨터 비전쪽은 C++가 주가 되므로, yolo 구조에 따라 차라리 C++ 텐서플로우로 새로 학습시켜서 사용할수 있게 하는 방법은 찾아볼 예정입니다.

 

그리고 깜빡 잊었는데, 해당 코드에 안드로이드용 코드도 있는 것 같으니 모바일 개발에 관심있으신 분들은 보세요.

어차피 텐서플로로 옮길수 있는 시점에서 그런건 찾아보면 나오게 되어 있습니다.(모바일? OK. 라즈베리 파이? OK.)

 

프로세스 흐름과 원리만 잘 이해한 상태로 여러가지를 만들어볼 것입니다.

728x90