본문 바로가기

Computer Vision by OpenCV

OpenCV 피부색 영역만 추출하기

반응형
SMALL


이미지에서 사람 피부영역만 골라서 표시하기


사람의 피부색은 HLS영상의 기준으로 볼 때 다음과 같은 조건을 만족한다.

Saturation의 값은 0.2보다 크거나 같고,

Hue값은 28도보다 작거나 같고, 또는 330도 보다 크거나 같으며,

Luminance를 Saturation값으로 나눈 값이 0.5와 3.0 사이에 있어야 한다.


이것은 2007년에 Kakumanu라는 사람이 Pattern Recognition 논문지에 "A survey of skin-color modeling and detection methods"라는 제목으로 실은 논문에 나오는 내용이다.


아래와 같은 이미지에서 피부색은 그대로 두고, 나머지 영역은 모두 검게 바꾼다고 하자.

결과는 아래와 같다. 흑인, 백인, 황인에 상관없이 얼굴영역이 많이 검출되었다. 물론 피부인데도 불구하고 제대로 검출되지 못한 부분도 있고, 피부가 아님에도 피부로 오검출된 부분도 있다.

또 다른 이미지를 가지고 실험한 결과이다. 여기서는 각기 다른 인종의 여성 3명을 대상으로 한다. 

결과는 아래와 같이 대부분의 피부 영역이 올바르게 검출되었지만, 일부 머리카락도 피부로 오검출되었다.


위의 피부검출실험에 사용된 소스코드는 아래와 같다.

입력받은 이미지를 HLS영상으로 바꾸어, H, L, S의 값을 이용하였다.

 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
57
58
59
60
61
#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main(int argc, char** argv)
{

	if (argc != 2)
	{
		cout << " Provide image name to read" << endl;
		return -1;
	}

	Mat inputImg;
	Mat hlsImg;
	Mat skinImg;

	inputImg = imread(argv[1], CV_LOAD_IMAGE_COLOR);
	//resize(inputImg, inputImg, Size(), 0.4, 0.4, CV_INTER_AREA);
	skinImg = inputImg.clone();

	cvtColor(inputImg, hlsImg, CV_BGR2HLS);
	vector<Mat> hls_images(3);
	split(hlsImg, hls_images);

	for (int row = 0; row < hlsImg.rows; row++)
	{
		for (int col = 0; col < hlsImg.cols; col++)
		{
			uchar H = hlsImg.at<Vec3b>(row, col)[0];
			uchar L = hlsImg.at<Vec3b>(row, col)[1];
			uchar S = hlsImg.at<Vec3b>(row, col)[2];

			double LS_ratio = ((double)L) / ((double)S);
			bool skin_pixel = (S >= 50) && (LS_ratio > 0.5) && (LS_ratio < 3.0) && ((H <= 14) || (H >= 165));

			if (skin_pixel == false)
			{
				skinImg.at<Vec3b>(row, col)[0] = 0;
				skinImg.at<Vec3b>(row, col)[1] = 0;
				skinImg.at<Vec3b>(row, col)[2] = 0;
			}
		}
	}

	namedWindow("Original", CV_WINDOW_AUTOSIZE);
	namedWindow("SkinDetected", CV_WINDOW_AUTOSIZE);


	moveWindow("Original", 100, 100);
	moveWindow("SkinDetected", 120, 120);


	imshow("Original", inputImg);
	imshow("SkinDetected", skinImg);

	waitKey(0);
	return 0;
}



반응형
LIST