영상을 편집하는데 opencv 만한 tool이 없죠.
영상 편집과 object detection를 동시에 할 순 없을까요?
오픈 cv에서는 이미 만들어진 detection모델들을 로드하여 사용할 수 있습니다.
이 글을 읽기 전 선수 지식 포스팅
1) detection 모델 load
어떤 프레임워크로 만들어진 모델이냐에 따라 사용방법은 조금씩 다른데요.
기본적으로 첫 번째 인자에는 가중치 모델 파일 경로, 두 번째 인자에는 환경 파일(config파일)의 경로를 넣는 형태로 만들어집니다.
환경 파일은 모델을 어떻게 사용할지에 대한 가이드가 담겨 있는 파일입니다.
가중치 파일과 환경 파일은 어디에서 다운 받을 수 있을까요?
텐서플로우를 기준으로 설명드리겠습니다.
해당 링크에 접속하시고 스크롤을 조금 내리시면 모델별 weights와 config파일을 다운로드할 수 있는 표가 있습니다.
여러분이 원하는 파일을 다운로드하시면 됩니다.
파일 저장경로를 readNetFromTensorflow 함수 인자로 각각 넣어줍니다.
2) 이미지 load
detection 모델에 이미지를 넣는 방법에 대해 알아보겠습니다.
초기화한 모델 객체 cv_net에는 setInput()이라는 메서드가 있는데요.
함수의 인자로 이미지를 넣어주면 됩니다.
특이한 점은 blobFromImage함수로 감싼 형태로 넣어주었다는 건데요.
blobFromImage 함수는 이미지의 크기나 색감 등을 조정하는 전처리 함수입니다.
추가적으로 아래와 같이 이미지 사이즈를 변경할 수 있다는 점도 참고 바랍니다.
swapRB기능을 굳이 왜 쓰는지 이해가 안 가시는 분들 위해 추가 설명을 하겠습니다.
opencv 를 이용하여 이미지를 읽어 결과를 출력해봅니다.
output:
output을 보면 색감이 이상한걸 알 수 있죠. opencv로 이미지를 읽으면 기본적으로 컬러를 bgr형태로 바꾸기 때문인데요.
출력 전 rgb형태로 변경해주는 작업을 필요로 합니다.
방법은 아래와 같습니다.
output:
이러한 작업은 매번 하기 귀찮기 때문에 swapRB 인자에 True를 넣는 형태로 간단히 구현한 것입니다.
(cv2.dnn.blobFromImage함수에 대해 더 자세히 알고 싶은 분은 해당 글을 참고 바랍니다.)
3) 바운딩 박스 그리기
forward() 함수를 실행하면 output으로 4차원 행렬이 나옵니다.
output:
우리가 원하는 건 빨간색 사각형 부분입니다.
인덱싱을 통해 해당 부분만 읽어오도록 세팅을 해볼겁니다.
cv_out을 인덱싱하고 for 문을 돌리면 7개의 원소로 구성된 배열을 뽑아낼 수 있습니다.
배열의 첫 번째 인덱스는 class id를 의미하고, 두 번째 인덱스는 confidence score를 의미하는데요.
나머지 4개의 값은 바운딩 박스 좌표입니다.
좌상단 x, y좌표, 우하단 x, y좌표로 구성되어있습니다.
(바운딩 박스 그리는 것이 익숙하지 않은 분은 이 글을 읽고 와주시기 바랍니다.)
뽑은 값들은 인덱싱을 통해 더 세부적으로 값을 추출해줘야 합니다.
id값은 int형이어야 하니까 int로 타입을 변경해줍니다.
확신도가 높은 바운딩 박스만 그리기 위해 스코어가 0.5 이상인 것만 뽑겠다고 설정합니다.
(조건을 걸지 않으면 많은 바운딩 박스가 그려집니다. 그렇다면 그림을 그리는 의미가 없어질 테니까요.)
인덱싱을 통해 각각의 좌표값들을 할당해줍니다.
끝인 것 같아 보이지만 파이썬 opencv에서 반환해준 좌표값은 값을 0~1 사이 값으로 스케일링한 값입니다.
다시 실제 이미지 크기로 원복 한 상태에서 크기를 산정해야 합니다.
해당 이미지의 크기를 구한 후
그 크기만큼 해당 좌표에 곱해줘야 합니다.
원본 이미지 자체에 바운딩박스를 그리면 원본 이미지가 훼손이 됩니다. 복사본을 생성하여 사용하는 걸 추천드립니다.
rectangle을 그려줍니다.
output:
아쉬운 점은 해당 객체가 어떤 라벨인지를 알 수 없다는 점인데요.
putText를 통하여 글자를 써줍니다.
(putText사용법이 낯선 분은 이 글을 참조하시기 바랍니다.)
현재 우리가 가지고 있는 정보는 class Id 밖에 없기 없습니다.
class id와 라벨 값이 매핑된 딕셔너리를 미리 준비합니다.
labels_to_names_0 = {0:'person',1:'bicycle',2:'car',3:'motorcycle',4:'airplane',5:'bus',6:'train',7:'truck',8:'boat',9:'traffic light',
10:'fire hydrant',11:'street sign',12:'stop sign',13:'parking meter',14:'bench',15:'bird',16:'cat',17:'dog',18:'horse',19:'sheep',
20:'cow',21:'elephant',22:'bear',23:'zebra',24:'giraffe',25:'hat',26:'backpack',27:'umbrella',28:'shoe',29:'eye glasses',
30:'handbag',31:'tie',32:'suitcase',33:'frisbee',34:'skis',35:'snowboard',36:'sports ball',37:'kite',38:'baseball bat',39:'baseball glove',
40:'skateboard',41:'surfboard',42:'tennis racket',43:'bottle',44:'plate',45:'wine glass',46:'cup',47:'fork',48:'knife',49:'spoon',
50:'bowl',51:'banana',52:'apple',53:'sandwich',54:'orange',55:'broccoli',56:'carrot',57:'hot dog',58:'pizza',59:'donut',
60:'cake',61:'chair',62:'couch',63:'potted plant',64:'bed',65:'mirror',66:'dining table',67:'window',68:'desk',69:'toilet',
70:'door',71:'tv',72:'laptop',73:'mouse',74:'remote',75:'keyboard',76:'cell phone',77:'microwave',78:'oven',79:'toaster',
80:'sink',81:'refrigerator',82:'blender',83:'book',84:'clock',85:'vase',86:'scissors',87:'teddy bear',88:'hair drier',89:'toothbrush',
90:'hair brush'}
class_id를 통해 각각의 라벨 값과 score를 caption변수에 담고, caption을 putText함수의 인자로 넣어줍니다.
output:
'머신러닝,딥러닝 > opencv' 카테고리의 다른 글
[파이썬 opencv] 오픈cv 를 통해 비디오(영상) 출력하는 방법 (0) | 2022.12.02 |
---|---|
[파이썬 opencv] 오픈 cv에서 yolov3 사용하는 방법 (2) | 2022.10.26 |
[오픈 cv] 트랙바란? 트랙바 사용방법(for opencv 초보자) (0) | 2022.09.14 |
[파이썬 opencv] 두 이미지 합치는 방법(with 크기 다른 이미지) (0) | 2022.09.13 |
[opencv] 그림 그리기 | 글자 쓰는 법 (+ 한글 사용 방법) (0) | 2022.09.06 |
댓글