๐Ÿ’ป ํ”„๋กœ์ ํŠธ/๐Ÿงธ TOY-PROJECTS

[DeepLook] 3. ์ „์ฒ˜๋ฆฌ (haar-cascade ์•Œ๊ณ ๋ฆฌ์ฆ˜)

์žฅ์˜์ค€ 2023. 6. 20. 22:22

์ง€๋‚œ๋ฒˆ์— ํฌ๋กค๋งํ•œ ์ด๋ฏธ์ง€๋“ค์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์ „์ฒ˜๋ฆฌ ์ž‘์—…์„ ์ง„ํ–‰ํ–ˆ๋‹ค.

๋ชจ๋ธ์— ํ•™์Šต์‹œํ‚ค๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ธ๋ฌผ์˜ ์‚ฌ์ง„ ์ค‘ ์–ผ๊ตด๋งŒ 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ํ•˜๋Š” ์ „์ฒ˜๋ฆฌ ๊ณผ์ •์„ ๊ฑฐ์ณค๋‹ค.

๋Œ“๊ธ€์ˆ˜0