무효 클릭 IP 추적 중...
머신러닝,딥러닝/opencv

[파이썬 opencv] 오픈 cv에서 detection model 실행하는 방법

꼬예 2022. 10. 21.

영상을 편집하는데 opencv 만한 tool이 없죠.

영상 편집과 object detection를 동시에 할 순 없을까요?

오픈 cv에서는 이미 만들어진 detection모델들을 로드하여 사용할 수 있습니다.

 

 

이 글을 읽기 전 선수 지식 포스팅

 

1) detection 모델 load

어떤 프레임워크로 만들어진 모델이냐에 따라 사용방법은 조금씩 다른데요.

 

opencv에서 사용되는 다양한 프레임워크
인프런 권철민 딥 러닝 컴퓨터 비전 완벽 가이드 화면 참조

 

기본적으로 첫 번째 인자에는 가중치 모델 파일 경로, 두 번째 인자에는 환경 파일(config파일)의 경로를 넣는 형태로 만들어집니다.

 

환경 파일은 모델을 어떻게 사용할지에 대한 가이드가 담겨 있는 파일입니다.

 

가중치 파일과 환경 파일은 어디에서 다운 받을 수 있을까요?

 

 

 

 

 

텐서플로우를 기준으로 설명드리겠습니다.

 

해당 링크에 접속하시고 스크롤을 조금 내리시면 모델별 weights와 config파일을 다운로드할 수 있는 표가 있습니다.

 

opencv에서 사용가능한 detection 모델

 

여러분이 원하는 파일을 다운로드하시면 됩니다.

 

파일 저장경로를 readNetFromTensorflow 함수 인자로 각각 넣어줍니다.

파일경로를 입력하여 모델 초기화

 

2) 이미지 load

detection 모델에 이미지를 넣는 방법에 대해 알아보겠습니다.

초기화한 모델 객체 cv_net에는 setInput()이라는 메서드가 있는데요.

함수의 인자로 이미지를 넣어주면 됩니다.

 

특이한 점은 blobFromImage함수로 감싼 형태로 넣어주었다는 건데요.

 

blobFromImage 함수는 이미지의 크기나 색감 등을 조정하는 전처리 함수입니다.

 

blobFromImage 함수로 이미지를 깜산형태

 

추가적으로 아래와 같이 이미지 사이즈를 변경할 수 있다는 점도 참고 바랍니다.

 

이미지 사이즈 고정 방법

 

swapRB기능을 굳이 왜 쓰는지 이해가 안 가시는 분들 위해 추가 설명을 하겠습니다.

 

opencv 를 이용하여 이미지를 읽어 결과를 출력해봅니다.

 

cvtColor미적용

 

output:

 

bgr 이미지 output

 

output을 보면 색감이 이상한걸 알 수 있죠. opencv로 이미지를 읽으면 기본적으로 컬러를 bgr형태로 바꾸기 때문인데요.

출력 전 rgb형태로 변경해주는 작업을 필요로 합니다.

 

방법은 아래와 같습니다.

 

cvtColor 함수 적용

 

output:

 

rgb이미지 output

 

이러한 작업은 매번 하기 귀찮기 때문에 swapRB 인자에 True를 넣는 형태로 간단히 구현한 것입니다.

(cv2.dnn.blobFromImage함수에 대해 더 자세히 알고 싶은 분은 해당 글을 참고 바랍니다.)

 

3) 바운딩 박스 그리기

 

forward() 함수를 실행하면 output으로  4차원 행렬이 나옵니다.

 

forward()함수 실행

 

output:

 

4차원 행렬 output

 

우리가 원하는 건 빨간색 사각형 부분입니다.

 

인덱싱을 통해 해당 부분만 읽어오도록 세팅을 해볼겁니다.

 

cv_out을 인덱싱하고 for 문을 돌리면 7개의 원소로 구성된 배열을 뽑아낼 수 있습니다.

 

7개의 배열 추출

 

배열의 첫 번째 인덱스는 class id를 의미하고, 두 번째 인덱스는 confidence score를 의미하는데요.

 

배열 구성요소

 

나머지 4개의 값은 바운딩 박스 좌표입니다.

좌상단 x, y좌표, 우하단 x, y좌표로 구성되어있습니다.

(바운딩 박스 그리는 것이 익숙하지 않은 분은 이 글을 읽고 와주시기 바랍니다.)

 

뽑은 값들은 인덱싱을 통해 더 세부적으로 값을 추출해줘야 합니다.

id값은 int형이어야 하니까 int로 타입을 변경해줍니다.

 

인덱싱 및 타입변경

 

확신도가 높은 바운딩 박스만 그리기 위해 스코어가 0.5 이상인 것만 뽑겠다고 설정합니다.

(조건을 걸지 않으면 많은 바운딩 박스가 그려집니다. 그렇다면 그림을 그리는 의미가 없어질 테니까요.)

인덱싱을 통해 각각의 좌표값들을 할당해줍니다.

 

각좌표값 추출

 

끝인 것 같아 보이지만 파이썬 opencv에서 반환해준 좌표값은  값을 0~1 사이 값으로 스케일링한 값입니다.

 

다시 실제 이미지 크기로 원복 한 상태에서 크기를 산정해야 합니다.

 

해당 이미지의 크기를 구한 후 

 

원본이미지 크기 추출

 

그 크기만큼 해당 좌표에 곱해줘야 합니다.

 

원본크기로 복원

 

원본 이미지 자체에 바운딩박스를 그리면 원본 이미지가 훼손이 됩니다. 복사본을 생성하여 사용하는 걸 추천드립니다.

 

복사이미지 생성

 

rectangle을 그려줍니다.

 

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함수의 인자로 넣어줍니다.

 

putText함수실행

 

output:

 

최종결과

  • 트위터 공유하기
  • 페이스북 공유하기
  • 카카오톡 공유하기
이 컨텐츠가 마음에 드셨다면 커피 한잔(후원) ☕

댓글