피부색을 인식하자!

이론



이 부분의 내용은 이 논문 에서 정리해 번역되고 있습니다.

색 공간



색 공간은 색 정보를 3개 또는 4개의 다른 색성분으로 나타내는 수학 모델입니다. 피부 탐지에는 다양한 색 공간을 사용할 수 있습니다. 이들은 RGB 기반 색 공간(RGB, 정규화된 RGB), 색조 기반 색 공간(HSI, HSV 및 HSL), 휘도 기반 색 공간(YCBCr, YIQ 및 YUV)입니다.

RGB(Red-Green-Blue: 빨강-녹색-파랑)



RGB 색 공간은 널리 사용되며 일반적으로 디지털 이미지를 저장하고 표현하기 위한 기본 색 공간입니다. 원색인 빨강, 초록, 파랑의 3개의 컴퍼넌트로 구성되어 있습니다. 세 가지 기본 색상을 혼합하여 모든 색상을 얻을 수 있습니다.

이것은 빨강, 녹색 및 파랑 값의 선형 조인에 의해 색이 얻어지는 추가 색 공간입니다.
3개의 채널은 표면에 닿는 빛의 양에 따라 상관된다.



HSV(Hue Saturation Value: 색조 채도-명도)



색조(H)가 0에서 1.0까지 변경되면 해당 색상이 빨간색에서 노란색, 녹색, 청록색, 파란색, 마젠타를 거쳐 빨간색으로 돌아갑니다. 채도(S)가 0에서 1.0까지 변경되면 해당 색상(색조)이 불포화(회색 음영)에서 완전히 포화(흰색 성분 없음)까지 변경됩니다. 값(V) 또는 밝기가 0에서 1.0까지 변경되면 해당 색상이 점점 밝아집니다.



YCbCr(Luminance, Chrominance)



YCbCr은 인코딩된 비선형 RGB 신호입니다. 색상은 RGB 값의 가중 합으로 구성된 휘도(비선형 RGB에서 계산된 휘도)로 표시됩니다.
이 형식에서 휘도 정보는 단일 성분(Y)으로 저장되고 색차 정보는 두 가지 색차 성분(Cb 및 Cr)으로 저장됩니다. 이 표현을 사용하면 중복 색상 정보를 쉽게 제거할 수 있으므로 JPEG, MPEG1, MPEG2, MPEG4와 같은 이미지 및 비디오 압축 표준에 사용됩니다.



인간의 피부색



저자가 제안한 피부 검출 알고리즘







이상의 알고리즘에 대해서 몇가지 아직 모르고, 구현도 어려울 것 같기 때문에, 이 보다 간단한 방법을 사용해 보겠습니다
htps : // 기주 b. 코 m / 치레 F-메 h ぢ / S 킨데 c 치온
    HSV: 0<=H<=17 and 15<=S<=170 and 0<=V<=255
            and
    YCrCb: 0<=Y<=255 and 135<=Cr<=180 and 85<=Cb<=135

구현



목적




이상의 이미지에서 피부색으로 손가락 끝을 인식하는 것입니다.

환경


Windows 10
OpenCV 3.4.2
Python 3.7.9

코드



HSV 필터


img=cv2.imread("a.jpg")
img_YCrCb = cv2.cvtColor(img, cv2.COLOR_BGR2YCrCb)
HSV_mask = cv2.inRange(img_HSV, (0, 15, 0), (17,170,255)) 
HSV_mask = cv2.morphologyEx(HSV_mask, cv2.MORPH_OPEN, np.ones((3,3), np.uint8))
cv2.imshow("HSV.jpg", HSV_mask)

HSV 필터 결과


YCrCb 필터


img=cv2.imread("a.jpg")
img_YCrCb = cv2.cvtColor(img, cv2.COLOR_BGR2YCrCb)
YCrCb_mask = cv2.inRange(img_YCrCb, (0, 135, 85), (255,180,135)) 
YCrCb_mask = cv2.morphologyEx(YCrCb_mask, cv2.MORPH_OPEN, np.ones((3,3), np.uint8))
cv2.imshow("YCbCr.jpg",YCrCb_mask)

YCrCb 필터 결과


보이는 것처럼 YCrCb 필터 쪽은 자주 피부의 색을 마늘 수 있습니다.

OpenCV 윤곽(링크)



def apply_contours(contour_img):
    ret, thresh = cv2.threshold(contour_img, 127, 255, 0)
    contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)[-2:]
    # 一番大きい輪郭を選ぶ
    cnt = max(contours, key = cv2.contourArea)
    # 輪郭の中最上の点を選ぶ
    topmost = tuple(cnt[cnt[:,:,1].argmin()][0])    
    contour_img = cv2.drawContours(img, [cnt], 0, (0,255,0), 3)
    contour_img = cv2.circle(contour_img , topmost, radius=5, color=(0, 0, 255), thickness=-1)
    return contour_img

윤곽 및 YCrCb 필터 결과:


마지막 코드


import cv2
import numpy as np


img=cv2.imread("WIN_20201203_01_38_27_Pro.jpg")

img_YCrCb = cv2.cvtColor(img, cv2.COLOR_BGR2YCrCb)
YCrCb_mask = cv2.inRange(img_YCrCb, (0, 135, 85), (255,180,135)) 
YCrCb_mask = cv2.morphologyEx(YCrCb_mask, cv2.MORPH_OPEN, np.ones((3,3), np.uint8))


def apply_contours(contour_img):
    ret, thresh = cv2.threshold(contour_img, 127, 255, 0)
    contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)[-2:]
    # 一番大きい輪郭を選ぶ
    cnt = max(contours, key = cv2.contourArea)
    # 輪郭の中最上の点を選ぶ
    topmost = tuple(cnt[cnt[:,:,1].argmin()][0])    
    contour_img = cv2.drawContours(img, [cnt], 0, (0,255,0), 3)
    contour_img = cv2.circle(contour_img , topmost, radius=8, color=(0, 0, 255), thickness=-1)
    return contour_img

YCrCb_result = apply_contours(YCrCb_mask)

#show results
# cv2.imshow("Show image",YCrCb_result)
cv2.imwrite("YCbCr_result.jpg",YCrCb_result)
cv2.waitKey(0)
cv2.destroyAllWindows() 

Happy coding!

좋은 웹페이지 즐겨찾기