แ„‚ ๐Ÿ˜„ [11 ์ผ์ฐจ] : EXPLORATION 03. ์นด๋ฉ”๋ผ ์Šคํ‹ฐ์ปค ์•ฑ์„ ๋งŒ๋“ค์–ด ๋ณด์ž

๋ฐฑ๊ฑดยท2022๋…„ 1์›” 21์ผ
0

layout: single

title: ์นด๋ฉ”๋ผ ์Šคํ‹ฐ์ปค ์•ฑ์„ ๋งŒ๋“ค์–ด ๋ณด์ž

์นด๋ฉ”๋ผ ์Šคํ‹ฐ์ปค ์•ฑ์„ ๋งŒ๋“ค์–ด ๋ณด์ž

  • ํ• ๊ฒƒ : ๋™์˜์ƒ ์ฒ˜๋ฆฌ, ๊ฒ€์ถœ, ํ‚คํฌ์ธํŠธ ์ถ”์ •, ์ถ”์ , ์นด๋ฉ”๋ผ ์›๊ทผ

๋ชฉํ‘œ


  • ์–ผ๊ตด์ธ์‹ ์นด๋ฉ”๋ผ ํ๋ฆ„์˜ ์ดํ•ด
  • blib ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์‚ฌ์šฉ
  • ์ด๋ฏธ์ง€ ๋ฐฐ์—ด์˜ ์ธ๋ฑ์‹ฑ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ


์ค€๋น„๋ฌผ


  • png ํŒŒ์ผ์„ ์‚ฌ์šฉ(๋ฐฐ๊ฒฝ์ด ์—†๋Š” ๊ฒƒ)

์‚ฌ์ง„ ์ค€๋น„ํ•˜๊ธฐ

  • ๋ˆˆ, ์ฝ”, ์ž… ๋“ฑ์˜ ์–ผ๊ตด ๊ฐ๊ฐ์˜ ์œ„์น˜๋ฅผ ์ •ํ™•ํžˆ ์•„๋Š” ๊ฒƒ์ด ์ค‘์š”
    -> ์ด ์œ„์น˜๋ฅผ ์ฐพ์•„๋‚ด๋Š” ๊ธฐ์ˆ ์„ landmark ๋˜๋Š” ์กฐ์ •(alignment) ๋ผ๊ณ  ํ•จ
  • face landmark ๋ฐ์ดํ„ฐ์…‹์€ ๋ˆˆ, ์ฝ”, ์ž…๊ณผ ํ„ฑ์„ ํฌํ•จ
  • ๋จธ๋ฆฌ์˜ ์œ„์น˜๋Š” ๋–จ์–ด์ ธ ์žˆ๋Š” ์ •๋„๋กœ

์ค€๋น„ ์„ธ๋ถ€


  • ์–ผ๊ตด์ด ํฌํ•จ๋œ ์‚ฌ์ง„
  • ์‚ฌ์ง„์œผ๋กœ๋ถ€ํ„ฐ ์–ผ๊ตด์˜์—ญ face landmark ๋ฅผ ์ฐพ์Œ
  • landmark๋ฅผ ์ฐพ๊ธฐ ์œ„ํ•ด ์–ผ๊ตด์˜ bounding box๋ฅผ ์ฐพ์Œ
  • ์ฐพ์•„์ง„ ์˜์—ญ์— ์Šคํ‹ฐ์ปค ๋„ฃ๊ธฐ

์–ผ๊ตด์ด ํฌํ•จ๋œ ์‚ฌ์ง„

  • ํŒŒ์ผ๋ช… image.png
    -ํด๋”๊ตฌ์กฐ
    aiffel
    โ”œโ”€โ”€ camera_sticker
    โ””โ”€โ”€ models
    โ””โ”€โ”€ images
    โ”œโ”€โ”€ king.png
    โ”œโ”€โ”€ hero.png
    โ””โ”€โ”€ image.png

ํŒŒ์ผ ๋””๋ ‰ํ† ๋ฆฌ ์ƒ์„ฑ
$ mkdir -p ~/aiffel/camera_sticker/models$

$ mkdir -p ~/aiffel/camera_sticker/images<br><br>ํŒŒ์ผ๋ณต์‚ฌ<br> <br> ํŒŒ์ผ ๋ณต์‚ฌ ln -s ~/data/* ~/aiffel/camera_sticker/images$

OpenCV ์„ค์น˜

pip install opencv-python
โ†’ opencv-python : OpenCV ๋ฉ”์ธ ๋ชจ๋“ˆ

pip install opencv-contrib-python
โ†’ opencv-contrib-python contrib ๋ชจ๋“ˆ(๋ž˜ํ„ฐ ํŒจํ‚ค์ง€)

cf.
pip install numpy
โ†’ numpy : ๋ฐ์ดํ„ฐ ๋ถ„์„ ํ™˜๊ฒฝ์—์„œ ๋งŽ์ด ์‚ฌ์šฉ๋˜๋Š” ํ–‰๋ ฌ ์—ฐ์‚ฐ์„ ์œ„ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
pip install matplotlib
โ†’ matplotlib : ๋„ํ‘œ, ์ฐจํŠธ, ๊ทธ๋ž˜ํ”„ ๋“ฑ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋งŒ๋“  ๊ทธ๋ž˜ํ”ฝ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

๋ชจ๋“ˆ import

์ผ๋‹จ ๋ชจ๋“ˆ์„ ๋ถˆ๋Ÿฌ์™€์•ผ ์—๋Ÿฌ๊ฐ€ ์•ˆ๋‚˜๋‹ˆ๊นŒ ใ…‹

import os
import cv2
import matplotlib.pyplot as plt
import numpy as np
import dlib

์ค€๋น„ํ•œ ์ด๋ฏธ์ง€ ์ฝ๊ธฐ

my_image_path = './camera_sticker/images/image.png'
img_bgr = cv2.imread(my_image_path)  # OpenCV๋กœ ์ด๋ฏธ์ง€๋ฅผ ๋ถˆ๋Ÿฌ์˜ต๋‹ˆ๋‹ค
img_show = img_bgr.copy()            # ์ถœ๋ ฅ์šฉ ์ด๋ฏธ์ง€๋ฅผ ๋”ฐ๋กœ ๋ณด๊ด€ํ•ฉ๋‹ˆ๋‹ค
plt.imshow(img_bgr)                  # ์ด๋ฏธ์ง€ ์ถœ๋ ฅํ•˜๊ธฐ
plt.show()                           # ์ด๊ฑด ์™œ ์จ์•ผํ• ๊นŒ์š”???

ํ‘ธ๋ฅธ์ƒ‰๊ฐ์ด ๋„๋Š” ๊ฒƒ์€ opencv์˜ ํŠน์ง•
matplotlib, dlib ๋“ฑ์€ RGB์ˆœ์œผ๋กœ ์‚ฌ์šฉํ•˜๋‚˜
opencv๋Š” ์˜ˆ์™ธ์ ์œผ๋กœ BGR๋กœ ๋ฐ”๊พธ์–ด ์‚ฌ์šฉํ•˜์—ฌ
๋ถ‰์€์ƒ‰ โ†’ ํ‘ธ๋ฅธ์ƒ‰, ํ‘ธ๋ฅธ์ƒ‰ โ†’ ๋ถ‰์€์ƒ‰์œผ๋กœ ๋ฐ”๋€Œ์–ด ์ถœ๋ ฅ
๋ณด์ •์ด ํ•„์š”

์ด๋ฏธ์ง€ ๋ณด์ •ํ•˜๊ธฐ

์ฐธ๊ณ  : OpenCV : ์ด๋ฏธ์ง€ ๋‹ค๋ฃจ๊ธฐ

# plt.imshow ์ด์ „์— RGB ์ด๋ฏธ์ง€๋กœ ๋ฐ”๊พธ๋Š” ๊ฒƒ์„ ์žŠ์ง€๋งˆ์„ธ์š”. 
img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)
plt.imshow(img_rgb)
plt.show()

์ฐธ๊ณ .
cv2.imread('img.png', 0) ์—์„œ 0 ์˜ ์˜๋ฏธ

  • ๋ฌธ์„œ์— ๋”ฐ๋ฅด๋ฉด ์ด๋ฏธ์ง€ ์ฝ๊ธฐ์˜ flag๋Š” ๋‹ค์Œ 3๊ฐ€์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ˆœ์„œ๋Œ€๋กœ 1, 0, -1์˜ ๊ฐ’์„ ๊ฐ–์Šต๋‹ˆ๋‹ค.

  • cv2.IMREAD_COLOR : ์ด๋ฏธ์ง€ ํŒŒ์ผ์„ Color๋กœ ์ฝ์–ด๋“ค์ž…๋‹ˆ๋‹ค. ํˆฌ๋ช…ํ•œ ๋ถ€๋ถ„์€ ๋ฌด์‹œ๋˜๋ฉฐ, Default๊ฐ’์ž…๋‹ˆ๋‹ค.

  • cv2.IMREAD_GRAYSCALE : ์ด๋ฏธ์ง€๋ฅผ Grayscale๋กœ ์ฝ์–ด ๋“ค์ž…๋‹ˆ๋‹ค. ์‹ค์ œ ์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ์‹œ ์ค‘๊ฐ„๋‹จ๊ณ„๋กœ ๋งŽ์ด ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

  • cv2.IMREAD_UNCHANGED : ์ด๋ฏธ์ง€ํŒŒ์ผ์„ alpha channel๊นŒ์ง€ ํฌํ•จํ•˜์—ฌ ์ฝ์–ด ๋“ค์ž…๋‹ˆ๋‹ค.

  • cv2.imread('img.png', 0)์ด๋ผ๊ณ  ํ˜ธ์ถœํ–ˆ๋‹ค๋ฉด ์ด๋ฏธ์ง€๋ฅผ Grayscale๋กœ ์ฝ์–ด ๋“ค์ด๊ฒ ๋‹ค๋Š” ๋œป

์–ผ๊ตด ๊ฒ€์ถœ face detection

  • dlib์˜ face detector๋Š” HOG(Histogram of Oriented Gradients)์™€ SVM(Support Vector Machine)์„ ์‚ฌ์šฉ

  • HOG๋Š” ์ด๋ฏธ์ง€์—์„œ ์ƒ‰์ƒ์˜ ๋ณ€ํ™”๋Ÿ‰
    โ†’ ์ด๋ฏธ์ง€๋กœ๋ถ€ํ„ฐ ๋ฌผ์ฒด์˜ ํŠน์ง•์„ ์ž˜ ์žก์•„๋‚ธ๋‹ค.

  • 2000๋…„๋Œ€ ์ดˆ๋ฐ˜ ๋งŽ์ด ์‚ฌ์šฉ(์–ผ๊ตด ์ด›์  ์žก๋Š” ์šฉ๋„)

โ†’ HOG๋ฅผ ์‹œ๊ฐํ™”ํ•œ ์ด๋ฏธ์ง€

SVM ์„ ํ˜• ๋ถ„๋ฅ˜๊ธฐ

  • ๋‹ค์ฐจ์› ๊ณต๊ฐ„์„ ํ•œ ๋ฒกํ„ฐ๋ผ๊ณ  ๋ณธ๋‹ค๋ฉด ์—ฌ๋Ÿฌ ์ด๋ฏธ์ง€๋Š” ์—ฌ๋Ÿฌ ๋ฒกํ„ฐ
  • SVM ์„ ํ˜• ๋ถ„๋ฅ˜๊ธฐ๋Š” ์–ผ๊ตด์ด๋ƒ ์•„๋‹ˆ๋ƒ๋ฅผ ๊ตฌ๋ถ„ํ•˜๊ธฐ ์ข‹์Œ
  • โ†’ ์ด๋ฏธ์ง€๊ฐ€ HOG๋ฅผ ํ†ตํ•ด ๋ฒกํ„ฐ๋กœ ๋งŒ๋“ค์–ด์กŒ์„ ๋•Œ SVM์ด ์ž˜ ์ž‘๋™

  • ์–ผ๊ตด์˜ ์œ„์น˜๋ฅผ ์ฐพ๋Š” ๋ฐฉ๋ฒ•

    • sliding window ๋ฅผ ์‚ฌ์šฉ
      • ์ž‘์€์˜์—ญ(window)๋ฅผ ์ด๋™ํ•ด๊ฐ€๋ฉฐ ํ™•์ธํ•˜๋Š” ๋ฐฉ๋ฒ•
      • ํฐ ์ด๋ฏธ์ง€์˜ ์ž‘์€ ์˜์—ญ์„ ์ž˜๋ผ ์–ผ๊ตด์ด ์žˆ๋Š”์ง€ ํ•™์ธํ•˜๊ณ  ์˜†์œผ๋กœ ์ด๋™ํ•˜์—ฌ ํ™•์ธ
      • ์ด๋ฏธ์ง€๊ฐ€ ํด์ˆ˜๋ก ์˜ค๋ž˜๊ฑธ๋ฆผ
      • โ†’ ์ด๊ฑธ ํ•ด์†Œํ•˜๊ธฐ ์œ„ํ•ด ๋”ฅ๋Ÿฌ๋‹์ด ํ•„์š”ํ•จ.

    dlib๋ฅผ ํ™œ์˜ hog detector๋ฅผ ์„ ์–ธ.

# detector๋ฅผ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค
import dlib
detector_hog = dlib.get_frontal_face_detector()
print("๐ŸŒซ๐Ÿ›ธ")
๐ŸŒซ๐Ÿ›ธ

์–ผ๊ตด์˜ bounding box ์ฐพ๊ธฐ

detector_hog๋ฅผ ์ด์šฉ ์–ผ๊ตด์˜ bounding box ์ถ”์ถœ

img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)
dlib_rects = detector_hog(img_rgb, 1)   # (image, num of image pyramid)
print("๐ŸŒซ๐Ÿ›ธ")
๐ŸŒซ๐Ÿ›ธ

dlib์€ rgb ์ด๋ฏธ์ง€๋ฅผ ์ž…๋ ฅ์œผ๋กœ ๋ฐ›๊ธฐ ๋•Œ๋ฌธ์—
cvtColor() ๋ฅผ ์ด์šฉํ•ด์„œ
opencv ์˜ bgr ์ด๋ฏธ์ง€๋ฅผ rgb๋กœ ๋ณ€ํ™˜

  • detector_hog์˜ ๋‘ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” ์ด๋ฏธ์ง€ ํ”ผ๋ผ๋ฏธ๋“œ์˜ ์ˆ˜
    • ์ด๋ฏธ์ง€ํ”ผ๋ผ๋ฏธ๋“œ : ์ด๋ฏธ์ง€๋ฅผ upsampling ๋ฐฉ๋ฒ•์„ ํ†ตํ•ด ํฌ๊ธฐ๋ฅผ ํ‚ค์šฐ๋Š” ๊ฒƒ
      • upsampling
        • ๊ฐ„๋‹จํ•˜๊ฒŒ ๋ฐ์ดํ„ฐ์˜ ํฌ๊ธฐ๋ฅผ ํ‚ค์šฐ๋Š” ๊ฒƒ
        • ์ผ๋ฐ˜์ ์œผ๋กœ CNN์˜ ๋ ˆ์ด์–ด๋ฅผ ํ†ต๊ณผํ•˜๋ฉด์„œ ์ด๋ฏธ์ง€์˜ ํฌ๊ธฐ๋ฅผ ์ค„์ด๋Š” ๊ฒƒ
          -> down sampling
        • down sampling์˜ ๋ฐ˜๋Œ€ ๊ฐœ๋…์ด upsampling
    • ์ด๋ฏธ์ง€ ํ”ผ๋ผ๋ฏธ๋“œ์—์„œ ์–ผ๊ตด์„ ๊ฒ€์ถœํ•˜๋ฉด ์ž‘๊ฒŒ ์ตค์˜๋œ ์–ผ๊ตด์„ ํฌ๊ฒŒ ๋ณผ ์ˆ˜ ์žˆ์Œ
    • โ†’ ๋” ์ •ํ™•ํ•œ ๊ฒ€์ถœ์ด ๊ฐ€๋Šฅ
    • ์ฐธ๊ณ  : Image Pyramids
<# ์ฐพ๋Š” ์–ผ๊ตด์„ ํ™”๋ฉด์— ์ถœ๋ ฅ
# ์ฐพ์€ ์–ผ๊ตด ์˜์—ญ ๋ฐ•์Šค ๋ฆฌ์ŠคํŠธ
# ์—ฌ๋Ÿฌ ์–ผ๊ตด์ด ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค
print(dlib_rects)   

for dlib_rect in dlib_rects:
    l = dlib_rect.left()
    t = dlib_rect.top()
    r = dlib_rect.right()
    b = dlib_rect.bottom()

    cv2.rectangle(img_show, (l,t), (r,b), (0,255,0), 2, lineType=cv2.LINE_AA)

img_show_rgb =  cv2.cvtColor(img_show, cv2.COLOR_BGR2RGB)
plt.imshow(img_show_rgb)
plt.show()
rectangles[[(485, 1252) (1635, 2403)]]

  • dlib detector ๋Š”

    • dlib.rectangles ํƒ€์ž…์˜ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜
  • dlib.rectangles ๋Š”

    • dlib.rectangle ๊ฐ์ฒด์˜ ๋ฐฐ์—ด ํ˜•ํƒœ
  • dlib.rectangle๊ฐ์ฒด๋Š”

    • left(), top(), right(), bottom(), height(), width() ๋“ฑ์˜ ํ•จ์ˆ˜๋ฅผ ํฌํ•จ

์ฐธ๊ณ  : dlib.rectangles

  • ๋…น์ƒ‰ ๋ฐ•์Šค๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ์ถœ๋ ฅ๋˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์Œ
  • face detection์ด ์ •์ƒ์ ์œผ๋กœ ์ง„ํ–‰๋˜๊ณ  ์žˆ๋Š”์ง€ ์ฒดํฌํ•ด ๋ณธ ํ›„ ์ง„ํ–‰ํ•  ๊ฒƒ.

์–ผ๊ตด์˜ face landmark ์ฐพ๊ธฐ

  • ์ด๋ชฉ๊ตฌ๋น„์˜ ์œ„์น˜๋ฅผ ์•„๋Š” ๊ฒƒ์ด ์ค‘์š”
  • ์ด๋ชฉ๊ตฌ๋น„์˜ ์œ„์น˜๋ฅผ ์ถ”๋ก ํ•˜๋Š” ๊ฒƒ์„ face landmark localization ๊ธฐ์ˆ 


  • face landmark
    • detection ์˜ ๊ฒฐ๊ณผ๋ฌผ์ธ bounding box ๋กœ ์ž˜๋ผ๋‚ธ(crop) ์–ผ๊ตด ์ด๋ฏธ์ง€๋ฅผ ์ด์šฉ

Object keypoint estimation ์•Œ๊ณ ๋ฆฌ์ฆ˜

  • Face landmark์™€ ๊ฐ™์ด ๊ฐ์ฒด ๋‚ด๋ถ€์˜ ์ ์„ ์ฐพ๋Š” ๊ธฐ์ˆ 
  1. top-down : bounding box๋ฅผ ์ฐพ๊ณ  box ๋‚ด๋ถ€์˜ keypoint๋ฅผ ์˜ˆ์ธก
  2. bottom-up : ์ด๋ฏธ์ง€ ์ „์ฒด์˜ keypoint๋ฅผ ๋จผ์ € ์ฐพ๊ณ  point ๊ด€๊ณ„๋ฅผ ์ด์šฉํ•ด ๊ตฐ์ง‘ํ™” ํ•ด์„œ box ์ƒ์„ฑ
  • ์šฐ๋ฆฌ๊ฐ€ ํ• ๊ฒƒ์€ 1๋ฒˆ ๋ฐฉ๋ฒ•

Dlib landmark localization

  • Dlib์€ ibug 300-W ๋ฐ์ดํ„ฐ์…‹์œผ๋กœ ํ•™์Šตํ•œ pretrained model ์ œ๊ณต
  • ํ•™์Šต ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ regression tree์˜ ์•™์ƒ๋ธ” ๋ชจ๋ธ์„ ์‚ฌ์šฉ

์ด ์ ์˜ ๊ฐœ์ˆ˜๋Š” ๋ฐ์ดํ„ฐ์…‹๊ณผ ๋…ผ๋ฌธ๋งˆ๋‹ค ๋‹ค๋ฆ„

์ฐธ๊ณ : AFLW dataset

  • Dibl์˜ ์ œ๊ณต๋˜๋Š” ๋ชจ๋ธ ์‚ฌ์šฉ
    โ†’ ๋จผ์ € ์•„๋ž˜์˜ ๋‚ด์šฉ์„ ๋‹ค์šด๋กœ๋“œ

wget http://dlib.net/files/shape_predictor_68_face_landmarks.dat.bz2
mv shape_predictor_68_face_landmarks.dat.bz2 ~/aiffel/camera_sticker/models
cd ~/aiffel/camera_sticker && bzip2 -d ./models/shape_predictor_68_face_landmarks.dat.bz2

์ €์žฅํ•œ landmark ๋ชจ๋ธ์„ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ.

import os, dlib
model_path = os.getenv('HOME')+'/aiffel/camera_sticker/models/shape_predictor_68_face_landmarks.dat'
landmark_predictor = dlib.shape_predictor(model_path)
print("๋ถˆ๋Ÿฌ์˜ค๊ธฐ ์™„๋ฃŒ")
๋ถˆ๋Ÿฌ์˜ค๊ธฐ ์™„๋ฃŒ

landmark_predictor ๋Š” RGB ์ด๋ฏธ์ง€์™€ dlib.rectangle์„ ์ž…๋ ฅ ๋ฐ›์•„ dlib.full_object_detection ๋ฅผ ๋ฐ˜ํ™˜

list_landmarks = []

# ์–ผ๊ตด ์˜์—ญ ๋ฐ•์Šค ๋งˆ๋‹ค face landmark๋ฅผ ์ฐพ์•„๋ƒ…๋‹ˆ๋‹ค
for dlib_rect in dlib_rects:
    points = landmark_predictor(img_rgb, dlib_rect)
    # face landmark ์ขŒํ‘œ๋ฅผ ์ €์žฅํ•ด๋‘ก๋‹ˆ๋‹ค
    list_points = list(map(lambda p: (p.x, p.y), points.parts()))
    list_landmarks.append(list_points)

print(len(list_landmarks[0]))
68

points ๋Š” dlib.full_object_detection ์˜ ๊ฐ์ฒด์ด๊ธฐ ๋•Œ๋ฌธ์— parts() ํ•จ์ˆ˜๋กœ ๊ฐœ๋ณ„ ์œ„์น˜์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์กฐ๊ธˆ ๋” ์ง๊ด€์ ์ธ (x, y) ํ˜•ํƒœ๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋„๋ก ๋ณ€ํ™˜ํ•ด ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ list_points ๋Š” tuple (x, y) 68๊ฐœ๋กœ ์ด๋ฃจ์–ด์ง„ ๋ฆฌ์ŠคํŠธ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. ์ด๋ฏธ์ง€์—์„œ ์ฐพ์•„์ง„ ์–ผ๊ตด ๊ฐœ์ˆ˜๋งˆ๋‹ค ๋ฐ˜๋ณตํ•˜๋ฉด list_landmark์— 68๊ฐœ์˜ ๋žœ๋“œ๋งˆํฌ๊ฐ€ ์–ผ๊ตด ๊ฐœ์ˆ˜๋งŒํผ ์ €์žฅ

for landmark in list_landmarks:
    for point in landmark:
        cv2.circle(img_show, point, 10, (0, 255, 255), -1)

img_show_rgb = cv2.cvtColor(img_show, cv2.COLOR_BGR2RGB)
plt.imshow(img_show_rgb)
plt.show()

์Šคํ‹ฐ์ปค ๋ถ™์ด๊ธฐ

๋žœ๋“œ๋งˆํฌ๋ฅผ ๊ธฐ์ค€์œผ๋กœ '๋ˆˆ์น ์œ„ ์–ผ๊ตด ์ค‘์•™' ์— ์Šคํ‹ฐ์ปค๋ฅผ ์”Œ์šฐ๋ฉด ๋  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๊ตฌํ˜„ ๋ฐฉ๋ฒ•์€ ์—ฌ๋Ÿฌ ๊ฐ€์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์œ„ ๊ทธ๋ฆผ์ฒ˜๋Ÿผ ์ฝ” ์ค‘์‹ฌ์„ ๊ธฐ์ค€์œผ๋กœ ๋†’์ด x ์ด์ƒ์— ๊ทธ๋ ค๋„ ๋˜๊ณ  ๋ˆˆ์น ์œ„ n ํ”ฝ์…€ ์œ„์— ์Šคํ‹ฐ์ปค๋ฅผ ๊ตฌํ˜„

์ค‘์š”ํ•œ ๊ฒƒ์€ ์–ผ๊ตด ์œ„์น˜, ์นด๋ฉ”๋ผ์˜ ๊ฑฐ๋ฆฌ์— ๋”ฐ๋ผ ํ”ฝ์…€ x ๊ฐ€ ๋‹ค๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ๋น„์œจ๋กœ ๊ณ„์‚ฐ์„ ํ•ด์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ณ„์‚ฐํ•  ์ˆ˜์น˜๋Š” ๋‘ ๊ฐ€์ง€

for dlib_rect, landmark in zip(dlib_rects, list_landmarks):
    print (landmark[30]) # ์ฝ”์˜ index๋Š” 30 ์ž…๋‹ˆ๋‹ค
    x = landmark[30][0]
    y = landmark[30][1] - dlib_rect.height()//2
    w = h = dlib_rect.width()
    print ('(x,y) : (%d,%d)'%(x,y))
    print ('(w,h) : (%d,%d)'%(w,h))
(984, 1899)
(x,y) : (984,1323)
(w,h) : (1151,1151)

์ค€๋น„ํ•ด๋‘” ์Šคํ‹ฐ์ปค ์ด๋ฏธ์ง€๋ฅผ ์ฝ์–ด์„œ ์ ์šฉ.

sticker_path = './camera_sticker/images/king.png'
img_sticker = cv2.imread(sticker_path) # ์Šคํ‹ฐ์ปค ์ด๋ฏธ์ง€๋ฅผ ๋ถˆ๋Ÿฌ์˜ต๋‹ˆ๋‹ค
img_sticker = cv2.resize(img_sticker, (w,h))
print (img_sticker.shape)
(1151, 1151, 3)

์™•๊ด€ ์ด๋ฏธ์ง€๋ฅผ ์ฝ๊ณ  ์œ—๋‹จ๊ณ„์—์„œ ๊ณ„์‚ฐํ•œ ํฌ๊ธฐ๋กœ resize

์›๋ณธ ์ด๋ฏธ์ง€์— ์Šคํ‹ฐ์ปค ์ด๋ฏธ์ง€๋ฅผ ์ถ”๊ฐ€ํ•˜์‹œ ์œ„ํ•ด์„œ x,y์ขŒํ‘œ ์กฐ์ •
์ด๋ฏธ์ง€ ์‹œ์ž‘์ ์€ top-left ์ขŒํ‘œ

refined_x = x - w // 2
refined_y = y - h
print ('(x,y) : (%d,%d)'%(refined_x, refined_y))
(x,y) : (409,172)
# ๊ฒฐ๊ณผ๊ฐ’์ด ์Œ์ˆ˜๊ฐ€ ๊ณ„์‚ฐ
# ์Šคํ‹ฐ์ปค์˜ ์‹œ์ž‘์ ์ด ์–ผ๊ตด ์‚ฌ์ง„์˜ ์˜์—ญ์„ ๋ฒ—์–ด๋‚˜๋ฉด ์Œ์ˆ˜๋กœ ํ‘œํ˜„
# opencv ๋ฐ์ดํ„ฐ๋Š” numpy ndarray ํ˜•ํƒœ์˜ ๋ฐ์ดํ„ฐ ์‚ฌ์šฉ
# ndarray๋Š” ์Œ์ˆ˜ ์ธ๋ฑ์Šค ์ ‘๊ทผ ๋ถˆ๊ฐ€
# ์›๋ณธ ์ด๋ฏธ์ง€์˜ ๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚œ ์Šคํ‹ฐ์ปค ๋ถ€๋ถ„์„ ์ œ๊ฑฐ ํ•„์š”

์Šคํ‹ฐ์ปค์˜ ์‹œ์ž‘์  + ์Šคํ‹ฐ์ปค ์‚ฌ์ง„์˜ ํฌ๊ธฐ๊ฐ€ ์›๋ณธ ์ด๋ฏธ์ง€์˜ ํฌ๊ธฐ๋ณด๋‹ค ํฐ ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค. ์Šคํ‹ฐ์ปค ์‚ฌ์ง„์˜ ์˜ค๋ฅธ์ชฝ์ด๋‚˜ ์•„๋ž˜์ชฝ์œผ๋กœ ๋„˜์–ด๊ฐ€๋Š” ๊ฒฝ์šฐ์ฃ . ์ด ๊ฒฝ์šฐ๋Š” ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌํ• ๊นŒ.

if refined_x < 0: 
    img_sticker = img_sticker[:, -refined_x:]
    refined_x = 0
if refined_y < 0:
    img_sticker = img_sticker[-refined_y:, :]
    refined_y = 0

print ('(x,y) : (%d,%d)'%(refined_x, refined_y))
(x,y) : (409,172)

-y ํฌ๊ธฐ๋งŒํผ ์Šคํ‹ฐ์ปค๋ฅผ cropํ•˜๊ณ  top์˜ x,y ์ขŒํ‘œ๋ฅผ ๊ฐ๊ฐ์˜ ๊ฒฝ์šฐ์— ๋งž์ถฐ ์›๋ณธ ์ด๋ฏธ์ง€์˜ ๊ฒฝ๊ณ„๊ฐ’์œผ๋กœ ์ˆ˜์ •

# ์›๋ณธ ์ด๋ฏธ์ง€์— ์Šคํ‹ฐ์ปค ์ ์šฉ
# ๊ธธ์–ด์„œ ๋ณต์žกํ•ด ๋ณด์ด์ง€๋งŒ img_show[from:to] ํ˜•์‹์ž…๋‹ˆ๋‹ค
sticker_area = img_show[refined_y:refined_y+img_sticker.shape[0], refined_x:refined_x+img_sticker.shape[1]]
img_show[refined_y:refined_y+img_sticker.shape[0], refined_x:refined_x+img_sticker.shape[1]] = \
    np.where(img_sticker==0,sticker_area,img_sticker).astype(np.uint8)
print("์Š~")
์Š~

sticker_area๋Š” ์›๋ณธ์ด๋ฏธ์ง€์—์„œ ์Šคํ‹ฐ์ปค๋ฅผ ์ ์šฉํ•  ์œ„์น˜๋ฅผ cropํ•œ ์ด๋ฏธ์ง€ ์ž…๋‹ˆ๋‹ค. ์˜ˆ์ œ์—์„œ๋Š” (344,0) ๋ถ€ํ„ฐ (344+187, 0+89) ๋ฒ”์œ„์˜ ์ด๋ฏธ์ง€๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

์Šคํ‹ฐ์ปค ์ด๋ฏธ์ง€์—์„œ ์‚ฌ์šฉํ•  ๋ถ€๋ถ„์€ 0 ์ด ์•„๋‹Œ ์ƒ‰์ด ์žˆ๋Š” ๋ถ€๋ถ„์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ np.where๋ฅผ ํ†ตํ•ด img_sticker ๊ฐ€ 0 ์ธ ๋ถ€๋ถ„์€ sticker_area๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  0์ด ์•„๋‹Œ ๋ถ€๋ถ„์„ img_sticker๋ฅผ ์‚ฌ์šฉํ•˜์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค. img_show ์— ๋‹ค์‹œ ์ ์šฉ

# ๊ฒฐ๊ณผ ์ด๋ฏธ์ง€๋ฅผ ์ถœ๋ ฅํ•˜๋ฉด 
plt.imshow(cv2.cvtColor(img_show, cv2.COLOR_BGR2RGB))
plt.show()

bounding box์™€ landmark๋ฅผ ์ œ๊ฑฐํ•˜๊ณ  ์ตœ์ข… ๊ฒฐ๊ณผ๋งŒ ์ถœ๋ ฅํ•ด ๋ด…์‹œ๋‹ค. img_show ๋Œ€์‹ , ์ง€๊ธˆ๊นŒ์ง€ ์•„๊ปด ๋‘์—ˆ๋˜ img_rgb๋ฅผ ํ™œ์šฉ

sticker_area = img_bgr[refined_y:refined_y +img_sticker.shape[0], refined_x:refined_x+img_sticker.shape[1]]
img_bgr[refined_y:refined_y +img_sticker.shape[0], refined_x:refined_x+img_sticker.shape[1]] = \
    np.where(img_sticker==0,sticker_area,img_sticker).astype(np.uint8)
plt.imshow(cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB))
plt.show()

profile
๋งˆ์ผ€ํŒ…์„ ์œ„ํ•œ ์ธ๊ณต์ง€๋Šฅ ์„ค๊ณ„์™€ ์Šคํƒ€ํŠธ์—… Log

0๊ฐœ์˜ ๋Œ“๊ธ€