💡개요
개인적으로 머신러닝을 접해보고 싶어서 미니 프로젝트를 개발하기로 하였습니다. 처음으로 인공지능을 배우는 것이니 재미가 있는 내용을 학습하고 싶어 OpenCV를 선택했습니다. 배운 내용들은 틈틈히 블로그에 작성해서 정리해볼 예정입니다.
💡OpenCV를 이용한 Face Detection 구현하기
▶️ 사용 라이브러리
import cv2
import numpy as np
from tkinter import *
from PIL import Image
from PIL import ImageTk
from tkinter import filedialog
import cv2로 OpenCV 라이브러리를 넣어줍니다.
또한, PIL(Pillow)를 사용하여 이미지 분석과 처리를 쉽게 할 수 있습니다.
▶️ 변수 선언
model_name='./Data/res10_300x300_ssd_iter_140000.caffemodel'
prototext_name='./Data/deploy.prototxt.txt'
min_confidence = 0.3
file_name = "./Data/image/marathon_01.jpg"
title_name = 'dnn Deep Learnig object detection'
frame_width = 300
frame_height = 300
- model_name : Face Detection에 caffe 모델을 사용할 것이기 때문에 caffe가 학습된 모델 파일을 model_name 변수에 선언해줍니다.
- prototext_name : 학습이 완료된 모델에 임의의 입력을 다루기 위해 사용합니다.
- min_confidence : 최소 신뢰도로 0.3일 경우 30% 신뢰도를 의미합니다.
▶️ selectFile() 함수
def selectFile():
file_name = filedialog.askopenfilename(initialdir = "./image",title = "Select file",filetypes = (("jpeg files","*.jpg"),("all files","*.*")))
print('File name : ', file_name)
read_image = cv2.imread(file_name)
image = cv2.cvtColor(read_image, cv2.COLOR_BGR2RGB)
image = Image.fromarray(image)
imgtk = ImageTk.PhotoImage(image=image)
(height, width) = read_image.shape[:2]
detectAndDisplay(read_image, width, height)
- file_name : File Select 버튼을 눌렀을 때 어느 경로로 이동할 것이며, 파일의 타입을 지정해줍니다.
- read_image : cv2.imread() 함수를 이용하여 이미지 파일을 읽습니다.
- image : cv2.cvtColor()함수를 이용하여 BGR 이미지를 RGB이미지로 변환합니다. 이 작업을 수행하는 이유는 OpenCV에 적용할 때 BGR 순서로 저장되어서 추가적으로 RGB로 변환하는 과정이 필요하기 때문입니다. 또한, Image.fraomarray() 함수를 통해 OpenCV 이미지를 PIL 이미지로 변환해줍니다.
- imgtk : ImageTk.PhotoImage(image=변수명)을 통해 PIL이미지를 Tk의 포토 이미지로 변환합니다.
▶️ detectAndDisplay() 함수
detectAndDisplay() 함수는 코드 길이가 길어 3단계로 나누어서 설명합니다.
1단계 blob변환
def detectAndDisplay(frame, w,h):
model=cv2.dnn.readNetFromCaffe(prototext_name, model_name)
blob=cv2.dnn.blobFromImage(cv2.resize(frame,(300,300)), 1.0,(300,300),(104.0, 177.0,123.0))
model.setInput(blob)
detections=model.forward()
min_confidence=float(sizeSpin.get())
- model : dnn중 Caffe가 간단하고 자주 사용하여 cv2.dnn.readNetFromCaffe를 이용합니다.
- blob : blob객체로 만들어줍니다. cv2.dnn.blobFromImage를 이용하며
- cv2.resize(frame,(300,300)) : 이미지 input 파라미터로, frame을 300pixels(가로) x 300pixels(세로)로 resize 합니다.
- 1.0 : scale factor
- (300,300) : size
- (104.0, 177.0, 123.0) : mean subtraction의 경험적 최적값
- detections : forward() 함수를 이용하여 모델이 학습 데이터를 입력받도록 해줍니다.
2단계 confidence for문
for i in range(0, detections.shape[2]):
confidence = detections[0, 0, i, 2]
if confidence > min_confidence:
box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
(startX, startY, endX, endY) = box.astype("int")
print(confidence, startX, startY, endX, endY)
text = "{:.2f}%".format(confidence * 100)
y = startY - 10 if startY - 10 > 10 else startY + 10
cv2.rectangle(frame, (startX, startY), (endX, endY),
(0, 255, 0), 2)
cv2.putText(frame, text, (startX, y),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1)
- for문 범위 : detection.shape[2]로 지정을 하여 최대 박스의 갯수를 지정합니다.
- confidence : detections는 4차 배열로 되어 있어 detections[0,0,i,2]라는 값으로 선언됩니다.
- box : detection[0,0,i,3:7] 라는 루프를 돌때 첫번째i가 0일때 배열 3번부터 7번 이전 즉 6번째 까지 값은 그림의 좌표를 나타냅니다. * np.array([width, height, width, height])를 곱해서 (startX, startY, endX, endY)를 구합니다.
- 3번째 : 전체 폭 중 박스 시작점의 x좌표 상대위치
- 4번째 : 전체 높이 중 박스 시작점의 y좌표 상대위치
- 5번째 : 전체 폭 중 박스 끝점의 x좌표 상대위치
- 6번째 : 전체 높이 중 박스 끝점의 y좌표 상대위치
- text : confidence값에 100을 곱해 확률값을 cv2.putText()함수를 이용하여 이미지 위에 text를 놓습니다.
3단계
image=cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
image=Image.fromarray(image)
imgtk=ImageTk.PhotoImage(image=image)
detection.config(image=imgtk)
detection.image=imgtk
▶️ main함수
main=Tk()
main.title(title_name)
main.geometry()
▶️ image 선언
read_image=cv2.imread(file_name)
image=cv2.cvtColor(read_image, cv2.COLOR_BGR2RGB)
image=Image.fromarray(image)
imgtk=ImageTk.PhotoImage(image=image)
(height, width)=read_image.shape[:2]
selectFile() 함수를 참고하면 이해할 수 있습니다.
▶️ label
label=Label(main, text=title_name)
label.config(font=("Courier", 18))
label.grid(row=0,column=0,columnspan=4)
sizeLabel=Label(main, text='Min Confidence : ')
sizeLabel.grid(row=1,column=0)
sizeVal = IntVar(value=min_confidence)
sizeSpin = Spinbox(main, textvariable=sizeVal,from_=0, to=1, increment=0.05, justify=RIGHT)
sizeSpin.grid(row=1, column=1)
Button(main,text="File Select", height=2,command=lambda:selectFile()).grid(row=1, column=2, columnspan=2, sticky=(W, E))
detection=Label(main, image=imgtk)
detection.grid(row=2,column=0,columnspan=4)
detectAndDisplay(read_image, width, height)
main.mainloop()
label관련 코드들을 작성하여 정리해줍니다.
이렇게 코드를 작성하면 dnn을 활용한 Face Detection을 구현 완료하였습니다. 아직 실력이 부족하여 잘못된 설명이 있을 수 있으니 너그러운 마음으로 글을 봐주시면 감사하겠습니다!!
참고사이트
'개발 > 머신러닝' 카테고리의 다른 글
[혼공머신] 4장. 다양한 분류 알고리즘 (1) | 2023.11.22 |
---|---|
딥러닝(OpenCV cnn)을 이용한 Face Recognition 구현하기 (2) | 2023.10.27 |