版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhongqianli/article/details/85703305
原理
在RGB颜色空间下满足:
R>95
AND G>40 B>20
AND MAX(R,G,B)-MIN(R,G,B)>15
AND ABS(R-G)>15
AND R>G
AND R>B
即可认为是皮肤颜色。
实现
#include <opencv2/core/core.hpp>
//#define SKIN_DETECTION_DEBUG
#ifdef SKIN_DETECTION_DEBUG
#include <string>
#include <stdio.h>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#endif
int max(int a, int b, int c)
{
int max = a;
if(b > max)
max = b;
if(c > max)
max = c;
return max;
}
int min(int a, int b, int c)
{
int min = a;
if(b < min)
min = b;
if(c < min)
min = c;
return min;
}
/**
* @brief skin_detection : exclude gray image
* @param image
* @param skin_ratio
*/
void skin_detection(const cv::Mat &image, double &skin_ratio)
{
int rows = image.rows;
int cols = image.cols;
int skin_pix_num = 0;
#ifdef SKIN_DETECTION_DEBUG
cv::Mat result = image.clone();
#endif
for(int row = 0; row < rows; ++row)
{
for(int col = 0; col < cols; ++col)
{
int B = image.ptr<cv::Vec3b>(row)[col][0];
int G = image.ptr<cv::Vec3b>(row)[col][1];
int R = image.ptr<cv::Vec3b>(row)[col][2];
if(R > 95 && G > 40 && B > 20
&& R > G && R > B
&& std::abs(R - G) > 15
&& max(R, G, B) - min(R, G, B) > 15)
{
skin_pix_num++;
#ifdef SKIN_DETECTION_DEBUG
result.ptr<cv::Vec3b>(row)[col][0] = 0;
result.ptr<cv::Vec3b>(row)[col][1] = 0;
result.ptr<cv::Vec3b>(row)[col][2] = 255;
#endif
}
}
}
skin_ratio = skin_pix_num * 1.0 / (rows * cols);
#ifdef SKIN_DETECTION_DEBUG
char buffer[256];
sprintf(buffer, "%5.5f", skin_ratio);
std::string text = buffer;
cv::putText(result, text, cv::Point(25, 25), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0,255,0), 1);
cv::imshow("result", result);
#endif
}