์ง๋๋ฒ์ ํฌ๋กค๋งํ ์ด๋ฏธ์ง๋ค์ ๊ธฐ๋ฐ์ผ๋ก ์ ์ฒ๋ฆฌ ์์ ์ ์งํํ๋ค.
๋ชจ๋ธ์ ํ์ต์ํค๊ธฐ ์ํด์๋ ์ธ๋ฌผ์ ์ฌ์ง ์ค ์ผ๊ตด๋ง crop ๋ ์ํ๋ฅผ ํ์ต์์ผ์ผ ํ๋๋ฐ, ์ด ๋ถ๋ถ์ ๋ํด ์ฐพ์๋ณด๋ haar cascade classifier ๋ผ๋ ์๊ณ ๋ฆฌ์ฆ์ด ์์๋ค.
1. Haar Cascade Classifier ์๊ณ ๋ฆฌ์ฆ์ด๋?
๊ฐ๋จํ๊ฒ ์์ฝํ์๋ฉด, haar cascade classifier ์๊ณ ๋ฆฌ์ฆ์ ๊ฒ์ถํ ๋์์ด ๋๋ ๋ฌผ์ฒด๊ฐ ์๋ ์ด๋ฏธ์ง (Positive Image)์ ์๋ ์ด๋ฏธ์ง(Negative Image)๋ฅผ ์ต๋ํ ๋ง์ด ํ์ฉํด์ ๋ค๋จ๊ณ ํจ์๋ฅผ ํ๋ จ์ํค๋ ๊ธฐ๊ณํ์ต ๋ฐฉ์์ด๋ค.
ํด๋น ์๊ณ ๋ฆฌ์ฆ์ ์ ์ฌ ํ๋ฅด ํน์ง (haar-like features)๊ณผ ์บ์ค์ผ์ด๋ ๋ถ๋ฅ๊ธฐ (cascade classifier)๋ฅผ ์ฌ์ฉํ๋ค.
1. ์ ์ฌ ํ๋ฅด ํน์ง (haar-like features)
- ์ฌ๊ฐํ ํํ์ ํํฐ ์งํฉ์ ์ฌ์ฉํ๋ค.
- ํฐ์ ์ฌ๊ฐํ ์์ญ ํฝ์ ๊ฐ์ ํฉ์์ ๊ฒ์์ ์ฌ๊ฐํ ์์ญ ํฝ์ ๊ฐ์ ๋บ ๊ฒฐ๊ณผ ๊ฐ์ ์ถ์ถํ์ฌ,
- ์ต์ข ์ ์ผ๋ก ๊ณ์ฐ๋ ๊ฐ์ด ์์์ธ์ง ์์์ธ์ง๋ฅผ ๊ธฐ์ค์ผ๋ก ์ผ๊ตด์ ํน์ง์ด ์๋์ง ํ๋จํ๋ค.
- ๋ํ์ ์ผ๋ก, ์ฌ๋์ ๋์ชฝ์ ๋์น๊ณผ ๋๋์ ๋ฑ์ผ๋ก ์ธํด ์ด๋ก๊ณ , ๊ทธ ์๋ ์ฝง๋ฑ ๋ถ๋ถ์ ๋ฐ๊ฒ ํ์๋๋ ํน์ง๋ค์ด ์ถ์ถ๋๋ค.
2. ์บ์ค์ผ์ด๋ ๋ถ๋ฅ๊ธฐ (cascade classifier)
- ํน์ง์ ๋ชจ์ผ๋ ์์ ์ ada boost ์๊ณ ๋ฆฌ์ฆ์ผ๋ก ์ํ๋๋ฉฐ, ํ๊ท ์ ์ผ๋ก 6000๊ฐ์ ํน์ง์ ์ถ์ถํ๋๋ฐ, ์ด๊ฒ์ ๋ชจ๋ ๋น๊ตํ๊ธฐ์๋ ๋นํจ์จ์ ์ด๋ค.
- non-face์ธ ์์ญ์ ๋น ๋ฅด๊ฒ skip ํ๋๋ก ๋ค๋จ๊ณ (cascade) ๊ฒ์ฌ๋ฅผ ์ํํ๋ค.
- ๋ค๋จ๊ณ ๊ฒ์ฌ๋ ์๋์ฐ์ ๋ํ 6000๊ฐ์ ๋ชจ๋ ํน์ง์ ์ ์ฉํ๋ ๋์ , ๋ถ๋ฅ์์ ๋ค๋ฅธ ๋จ๊ณ๋ก ํน์ง์ ๋ฌถ๊ณ ํ๋์ฉ ํ๋์ฉ ์ ์ฉํ๋ ๊ฒ์ด๋ค.
- ๋ง์ฝ ์๋์ฐ๊ฐ ์ฒซ ๋ฒ์งธ ๋จ๊ณ์์ ์คํจํ๋ฉด ๋ฒ๋ฆฌ๊ณ , ๋๋จธ์ง ํน์ง๋ค์ ๋ ์ด์ ๊ณ ๋ คํ์ง ์๋๋ค.
- ๋ง์ฝ ํต๊ณผ๋๋ฉด ํน์ง์ ๋ ๋ฒ์งธ ๋จ๊ณ๋ฅผ ์ ์ฉํ๊ณ ์ด๋ฅผ ๊ณ์ ๋ฐ๋ณตํ๋ค.
- ๋ชจ๋ ๋จ๊ณ๋ฅผ ํต๊ณผํ ์๋์ฐ๊ฐ ์ต์ข ์ ์ธ ์ผ๊ตด ์์ญ์ด ๋๋ค.
2. ์ฝ๋ ์ ์ฉ
์์์ ์ค๋ช ํ haar-cascade classifier ์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํ์ฌ ์ผ๊ตด ์ฌ์ง์ crop ์ํค๋ ๊ณผ์ ์ ์งํํ๋ค.
๋ ์์ธํ ์ฝ๋๋ ๊นํ๋ธ๋ฅผ ์ฐธ๊ณ ํ๊ธธ ๋ฐ๋๋ค.
์งํ๋๋ ๋จ๊ณ๋ ๋ค์๊ณผ ๊ฐ๋ค:
1. ํ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ค์นํ๊ณ ์ ์ฅ๋ ์ฌ์ง์ cv2 ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํตํด ํ๋ ฌ๋ก ์ฝ์ด์จ๋ค.
# ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ค์น ๋ฐ ๋ถ๋ฌ์ค๊ธฐ
!pip install opencv-python
import numpy as np
import pandas as pd
import cv2
import os
# ์ด๋ฏธ์ง ๋ถ๋ฌ์ค๊ธฐ
# ์ ์ฒด ์ด๋ฏธ์ง ๊ฐ์ ธ์ค๋ ๋ฃจํธ ๋๋ ํ ๋ฆฌ
root_dir = '/Users/jang-youngjoon/dev-projects/deep-look/crawled-image'
# ๊ฐ๊ธฐ์
selected_celeb = 'kky'
path = os.path.join(root_dir, selected_celeb)
file_list = os.listdir(path)
# ํ๋ ฌ๋ก ์ด๋ฏธ์ง ์ฝ์ด๋ค์ด๊ธฐ
for file in file_list:
image_path = os.path.join(path, file)
image = cv2.imread(image_path)
print(image)
๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๊ฐ๋ค. (์ด๋ฏธ์ง๊ฐ ์๋ ์ฌ์ง๊ณผ ๊ฐ์ ํ๋ ฌ๋ก ๋ณํ๋๋ค.)
2. ํ ์คํ
ํ๋์ ์ํ ์ด๋ฏธ์ง๋ฅผ ๊ฐ์ ธ์ ํ๋ ฌ๋ก ์ฝ์ด ๋ค์ด๊ณ , cv2.CascadeClassifier ํจ์ ๋ด์ ๋ฏธ๋ฆฌ ํ์ต๋ xml ํ์ผ์ ๋ถ๋ฌ์ ์ผ๊ตด์ ๊ฒ์ถํ๋ ์๊ณ ๋ฆฌ์ฆ์ ์์ฑํ๋ค. ์ดํ, ์ด๋ฏธ์ง๋ฅผ ํ๋ฐฑ ์ค์ผ์ผ๋ก ๋ณํํ๊ณ , face_cascade.detectMultiScale ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ์ด๋ ์ ๋์ threshold๋ก ๊ฒ์ถํ ์ง ์์๋ณธ๋ค.
# face_cascade ์๊ณ ๋ฆฌ์ฆ์ xml ํ์ผ ์ฝ์
face_cascade = cv2.CascadeClassifier("../haarcascade_frontalface_default.xml")
# ํ๋ฐฑ ์ด๋ฏธ์ง๋ก ๋ณํ
gray = cv2.cvtColor(sample_image, cv2.COLOR_BGR2GRAY)
# ์ผ๊ตด ๊ฒ์ถ
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
for (x, y, w, h) in faces:
cropped_image = image[y : y+h, x : x+w]
resized_image = cv2.resize(cropped_image, (180, 180))
๋ง์ง๋ง for ๋ฃจํ๋ faces ๋ฆฌ์คํธ์ ์๋ ๊ฐ ์ผ๊ตด์ ๋ํด ๋ฐ๋ณตํ๋ค. ๋ฐ๋ณตํ ๋๋ง๋ค (x, y, w, h)๋ผ๋ ๋ณ์๋ก ํ์ฌ ์ผ๊ตด์ ์ขํ์ ํฌ๊ธฐ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ต๋๋ค. x์ y๋ ์ผ๊ตด์ ์ผ์ชฝ ์ ๋ชจ์๋ฆฌ์ ์ขํ์ด๊ณ , w์ h๋ ๊ฐ๊ฐ ์ผ๊ตด์ ๋๋น์ ๋์ด๋ฅผ ๋ํ๋ธ๋ค.
๋ ๋ฒ์งธ ์ค์ cropped_image๋ ์๋ณธ ์ด๋ฏธ์ง์์ ์ผ๊ตด ์์ญ๋ง์ ์๋ผ๋ธ๋ค. ๋ฐฐ์ด ์ฌ๋ผ์ด์ฑ์ ํตํด ์๋ผ๋ด๊ณ , cropped_image๋ผ๋ ๋ณ์์ ์ ์ฅ๋๋ค.
๋ง์ง๋ง ์ค์์๋ ์๋ฆฐ ์ด๋ฏธ์ง๋ฅผ ์ค์ด๋ (๋ฆฌ์ฌ์ด์งํ๋) ์ญํ ์ ์ํํ๋ค.
3. ๋ชจ๋ ํ์ผ์ ์ ์ฉ
์ด์ ์ ์๊ณ ๋ฆฌ์ฆ์ ๋ชจ๋ ํ์ผ์ ์ ์ฉํด๋ดค๋ค. ๋๋ ํ ๋ฆฌ๋ฅผ ๋ถ๋ฌ์ค๊ณ , ๋น์ทํ๊ฒ ์ฝ๋๋ฅผ ์์ฑํ๋ค.
# ์ผ๊ตด๋ง cropํ๋ ์๊ณ ๋ฆฌ์ฆ
def crop_face(image, name):
# face_cascade ๋ชจ๋ธ ์ฌ์ฉ
face_cascade = cv2.CascadeClassifier("../haarcascade_frontalface_default.xml")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
for (x, y, w, h) in faces:
cropped_image = image[y : y+h, x : x+w]
resized_image = cv2.resize(cropped_image, (180, 180))
cv2.imwrite(os.path.join(save_path, name), resized_image)
print(f"{celeb_name_to_en} image cropped & saved" )
for image_name in image_list:
# .DS Store ํ์ผ ํ์ธ
if 'jpg' in image_name:
original_image = cv2.imread(os.path.join(import_path, str(image_name)))
# ๋ฐฑ์ ์ด๋ฏธ์ง ๋ฐฉ์ง ํ ๋ผํ๋๋ฐ ์๋จ,,,
if (type(original_image) != 'NoneType' or original_image != None) :
crop_face(original_image, image_name)
else:
continue
else:
continue
ํฌ๋กค๋ง ์์ ๋ฐฑ์ ์ด๋ฏธ์ง๊ฐ ๊ฒ์ถ๋๊ธฐ๋ ํ๋๋ฐ, ์ด๋ ์ค๋ฅ๊ฐ ๋์ ์ค๊ฐ์ ๋ฉ์ท๋ค. ์ด๋ฅผ ํด๊ฒฐํ๋ ค๊ณ ์กฐ๊ฑด๋ฌธ์ ๋ฌ์์ง๋ง,,์๋งํ๊ฒ ์คํ๋์ง ์์๋ค.. (์ถํ ์์ ์์ )
์ด๋ ๊ฒ haar cascade ์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํ์ฌ ๋ชจ๋ ์ฌ์ง๋ค์ ์ผ๊ตด์ ๊ฒ์ถํ๊ณ , ํด๋น ๋ถ๋ถ๋ง cropํ๋ ์ ์ฒ๋ฆฌ ๊ณผ์ ์ ๊ฑฐ์ณค๋ค.
'๐ป ํ๋ก์ ํธ > ๐งธ TOY-PROJECTS' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[DeepLook] 5. ๋ฐฑ์๋ ์ฐ๊ฒฐ (0) | 2023.06.21 |
---|---|
[DeepLook] 4. ๋ชจ๋ธ ์ ์ ๋ฐ ํ์ต (0) | 2023.06.21 |
[DeepLook] 2. AI ์์ ์ค๊ณ ๊ณผ์ / ํฌ๋กค๋ง (0) | 2023.06.20 |
[DeepLook] 1. ์์ํ๊ฒ ๋ ๊ณ๊ธฐ / ํ๋ก์ ํธ IA (0) | 2023.06.20 |
[ํ ์ดํ๋ก์ ํธ-NETFLIX CLONE] Next.js ๋ฅผ ํ์ฉํ Netflix Clone ํ๋ก์ ํธ (0) | 2023.06.20 |