일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- figma
- mongo
- postgresql
- review
- nodejs
- PyTorch
- python
- UI
- frontend
- DM
- ps
- SOLID
- Git
- Three
- sqlite
- CSS
- ts
- Express
- html
- react
- Linux
- GAN
- DB
- CV
- API
- C++
- PRISMA
- ML
- js
- vscode
- Today
- Total
아카이브
[Opencv] opencv 연습 | 1. 인물 사진에서 얼굴 인식하기 본문
다음 블로그의 글을 참고하였습니다.
https://seokii.tistory.com/112
[OpenCV with Python] - 15. 인물 사진 9000장 얼굴 인식 해보고 잘라서 저장해보기
코드 및 이미지 : https://github.com/Seokii/Study_OpenCV GitHub - Seokii/Study_OpenCV: study about OpenCV study about OpenCV. Contribute to Seokii/Study_OpenCV development by creating an account on GitHub. github.com https://seokii.tistory.com/111 [ML
seokii.tistory.com
* * *
Goal.
Opencv와 미리 학습된 모델을 이용해서 사진에서 인물의 얼굴을 표시해보겠습니다.
1. Dataset 준비
데이터셋으로는 KDDI AI Center 에서 제작한 LFW emotion dataset 을 사용했습니다.
아래 github 링크에서 내려받을 수 있습니다.
https://github.com/KDDI-AI-Center/LFW-emotion-dataset
GitHub - KDDI-AI-Center/LFW-emotion-dataset: Datasets released for <<Facial Expression Recognition with the advent of face masks
Datasets released for <<Facial Expression Recognition with the advent of face masks>> - GitHub - KDDI-AI-Center/LFW-emotion-dataset: Datasets released for <<Facial Expression Reco...
github.com
링크로 들어간 뒤 아래 표시한 링크를 누르면 내려받게 됩니다.
압축 해제한 뒤 LFW-emotion-dataset > data > LFW-FER > LFW-FER > train
경로로 들어가면 세 개의 이미지 폴더를 찾을 수 있습니다.
폴더 별로 각각 부정적 / 중립적 / 긍정적 표정인 얼굴의 이미지셋으로 분류되어 있습니다.
지금은 감정별 분류가 필요 없으므로 하나의 폴더로 합쳐서 사용하겠습니다.
2. Pre-trained Model 준비
이번에는 미리 학습된 모델을 사용합니다.
모델은 opencv에서 제공하는 haarcascades 모델을 사용하겠습니다.
아래 github 링크에서 내려받을 수 있습니다.
https://github.com/opencv/opencv/tree/master/data/haarcascades
GitHub - opencv/opencv: Open Source Computer Vision Library
Open Source Computer Vision Library. Contribute to opencv/opencv development by creating an account on GitHub.
github.com
링크로 들어가면 용도별로 여러가지의 xml 파일이 있는데
이중에서 정면 얼굴 인식용인 fontalface_default.xml 파일을 사용합니다.
3. 프로젝트 구성
Opencv-Py라는 이름의 프로젝트를 만들었습니다. 구성은 다음과 같습니다.
datasets
ㄴ LFW : 하나의 폴더로 합쳤던 LFW dataset
models
ㄴ haarcascade_frontalface_default.xml : 학습된 xml 파일 모델
outputs
ㄴ LFW : 출력 이미지를 저장할 곳
FLW.py : 메인 코드
test.py : opencv 작동 테스트용 파일
readme.md : readme 파일
4. FLW.py
위 과정을 토대로 dataset의 이미지 파일들에서 얼굴을 표시하여
새로운 이미지 파일로 저장하는 코드를 작성했습니다.
4.1. import
1
2
|
import cv2
import os
|
cs |
cv2는 opencv 라이브러리입니다.
os는 프로젝트 폴더의 경로들을 다루기 위해 사용합니다.
4.2. make_dataset_name_list( )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
# make_dataset_name_list(path) ==============================
# path (string) : directory of the dataset
# return (list) - list of name without extension
# ===========================================================
def make_dataset_name_list(path):
name_list = os.listdir(path_dir)
print(name_list[0]) # 'Aaron_Eckhart_0001.jpg'
print(len(name_list)) # 9330
name_list_nonex = []
for i in range(len(name_list)):
name_list_nonex.append(name_list[i].replace(".jpg", ""))
print(name_list_nonex[0]) # 'Aaron_Eckhart_0001'
return name_list_nonex
|
cs |
os.listdir(path) : path에 있는 모든 파일들의 이름을 list 형태로 반환합니다.
dataset의 이미지 파일들은 모두 "이름.jpg" 형태의 이름으로 되어 있습니다.
여기서 확장자를 떼고 "이름"의 형태로 바꾼 리스트를 만들어 반환하는 함수입니다.
4.3. find_face( )
1
2
3
4
5
6
7
8
9
|
# find_face(image, model) ===================================
# image (ndarray) : image array
# model (string) : directory of the xml file
# return (ndarray) - [[x, y, w, h], ...]
# ===========================================================
def find_face(image, model):
face_cascade = cv2.CascadeClassifier(model)
image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
return face_cascade.detectMultiScale(image_gray, 1.3, 5)
|
cs |
CascadeClassifier( )는 opencv에서 제공하는 class입니다.
CascadeClassifier( )의 detectMultiScale( ) method를 이용해 이미지에서 얼굴을 찾습니다.
detectMultiScale(image, scaleFactor, minNeighbors) | ||
image | ndarray | 대상 이미지 |
scaleFactor | float | 표시할 사각형의 크기( > 1.0). 증가할 수록 축소됨 |
minNeighbors | int | 근처 위치에도 사각형을 생성했을 대 목표(얼굴)로 인정되는 사각형의 최소 개수. 증가할 수록 목표(얼굴)를 인식하는 기준이 높아짐 |
Return | ndarray | 사각형 정보[x좌표, y좌표, 너비, 높이]에 대한 list |
4.4. save_rect( )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
# save_rect(image, rects, show) =============================
# image (ndarray) : image array
# rects (ndarray) : captured rect arrays [[x, y, w, h], ...]
# show (bool) : if show output image (=False)
# return (None)
# ===========================================================
def save_rect(image, rects, show=False):
for i in range(len(rects)):
x, y, w, h = rects[i]
cv2.rectangle(image, (x, y), (x+w, y+h), (255, 0, 0), 2)
cv2.imwrite(f"outputs/LFW/{name}_{i}.jpg", image)
if show:
cv2.imshow("face_recongnition", image)
cv2.waitKey(0)
cv2.destroyAllWindows()
|
cs |
사각형 위치에 대한 정보를 받아 이미지 위에 표시한 뒤 경로를 지정해 저장합니다.
이미지의 이름을 "이미지 이름_번호.jpg"로 저장하는데, 이는 한 사진에 얼굴이 두 개 이상일 경우를 위해서 입니다.
가령 사람 두 명이 있는 'a'라는 이미지 파일이 있으면 'a_0', 'a_1'로 저장되는 식입니다.
추가로 show 값을 조정하여 실행 후 이미지를 출력할 수 있습니다.
waitKey(time)는 키보드에서 키입력이 있을 때까지 대기하는 함수입니다.
waitKey(time) | ||
time | int | 대기 시간(ms) 0 : 무한 대기 |
Return | str | 입력한 키의 문자와 동일한 아스키 코드 값 |
4.5. 메인 코드
1
2
3
4
5
6
7
8
9
|
path_dir = "datasets/LFW/"
haarcascade = "models/haarcascade_frontalface_default.xml"
image_name_list = make_dataset_name_list(path_dir)
for name in image_name_list[:3]:
face = cv2.imread("datasets/LFW/" + name + ".jpg")
face_rects = find_face(face, haarcascade) #[[x y w h]]
save_rect(face, face_rects, show=True)
|
cs |
경로를 나타내는 문자열은 미리 변수로 저장해둡니다.
FLW dataset에서부터 확장자를 뗀 이름 리스트 image_name_list를 생성합니다.
이후 순서대로 이미지 파일을 불러 와 find_face( )로 사각형을 찾습니다.
마지막으로 save_rect( )로 이미지에 얼굴 영역을 표시하여 저장 및 출력합니다.
파일 개수가 매우 많으니 간단하게 3개 까지만 실행하도록 했습니다.
5. 결과
다음과 같이 올바르게 얼굴이 인식되고 저장되었습니다.
아래는 코드 전문입니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
import cv2
import os
# make_dataset_name_list(path) ==============================
# path (string) : directory of the dataset
# return (list) - list of name without extension
# ===========================================================
def make_dataset_name_list(path):
name_list = os.listdir(path_dir)
print(name_list[0]) # 'Aaron_Eckhart_0001.jpg'
print(len(name_list)) # 9330
name_list_nonex = []
for i in range(len(name_list)):
name_list_nonex.append(name_list[i].replace(".jpg", ""))
print(name_list_nonex[0]) # 'Aaron_Eckhart_0001'
return name_list_nonex
# find_face(image, model) ===================================
# image (ndarray) : image array
# model (string) : directory of the xml file
# return (ndarray) - [[x, y, w, h], ...]
# ===========================================================
def find_face(image, model):
face_cascade = cv2.CascadeClassifier(model)
image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
return face_cascade.detectMultiScale(image_gray, 1.3, 5)
# save_rect(image, rects, show) =============================
# image (ndarray) : image array
# rects (ndarray) : captured rect arrays [[x, y, w, h], ...]
# show (bool) : if show output image (=False)
# return (None)
# ===========================================================
def save_rect(image, rects, show=False):
for i in range(len(rects)):
x, y, w, h = rects[i]
cv2.rectangle(image, (x, y), (x+w, y+h), (255, 0, 0), 2)
cv2.imwrite(f"outputs/LFW/{name}_{i}.jpg", image)
if show:
cv2.imshow("face_recongnition", image)
cv2.waitKey(0)
cv2.destroyAllWindows()
path_dir = "datasets/LFW/"
haarcascade = "models/haarcascade_frontalface_default.xml"
image_name_list = make_dataset_name_list(path_dir)
for name in image_name_list[:3]:
face = cv2.imread("datasets/LFW/" + name + ".jpg")
face_rects = find_face(face, haarcascade) #[[x y w h]]
save_rect(face, face_rects, show=False)
|
cs |
'CS > CV' 카테고리의 다른 글
[Opencv] Opencv 설치하기 (0) | 2023.01.13 |
---|