【新】opencv肤色检测源码
【摘要】
//第一种:RGB color space // skin region location using rgb limitationvoid ImageSkin::ImageSkinRGB(const Mat& rgb, Mat& _dst){ assert(rgb.channels() == 3 &&am...
-
//第一种:RGB color space
-
// skin region location using rgb limitation
-
void ImageSkin::ImageSkinRGB(const Mat& rgb, Mat& _dst)
-
{
-
assert(rgb.channels() == 3 && _dst.channels() == 3);
-
-
static const int R=2;
-
static const int G=1;
-
static const int B=0;
-
-
Mat dst = Mat(_dst.size(), _dst.type(), 3);
-
dst.setTo(Scalar(0, 0, 0));
-
-
for (int h=0; h<rgb.rows; h++)
-
{
-
for (int w=0; w<rgb.cols; w++)
-
{
-
// 数组的一份拷贝
-
Vec3b prgb = rgb.at<Vec3b>(h, w);
-
Vec3b pdst = dst.at<Vec3b>(h, w);
-
//auto* pdst111 = &dst.at<Vec3b>(h, w);
-
-
if ((prgb[R]>95 && prgb[G]>40 && prgb[B]>20 &&
-
prgb[R]-prgb[B]>15 && prgb[R]-prgb[G]>15) || //uniform illumination
-
(prgb[R]>200 && prgb[G]>210 && prgb[B]>170 &&
-
abs(prgb[R]-prgb[B])<=15 && prgb[R]>prgb[B] && prgb[G]>prgb[B])
-
)
-
{
-
// 赋值切不可用pdst!
-
memcpy(&dst.at<Vec3b>(h, w), &prgb/*rgb.at<Vec3b>(h, w)*/, 3);
-
// 同上
-
//dst.at<Vec3b>(h, w)[R] = rgb.at<Vec3b>(h, w)[R];
-
//dst.at<Vec3b>(h, w)[G] = rgb.at<Vec3b>(h, w)[G];
-
//dst.at<Vec3b>(h, w)[B] = rgb.at<Vec3b>(h, w)[B];
-
}
-
}
-
}
-
dst.copyTo(_dst);
-
dst.release();
-
}
-
-
//第二种:RG color space
-
// skin detection in rg space
-
void ImageSkin::ImageSkinRG(const Mat& rgb, Mat& gray)
-
{
-
assert(rgb.channels() == 3 && gray.channels() == 1);
-
-
const int R=2;
-
const int G=1;
-
const int B=0;
-
-
double Aup=-1.8423;
-
double Bup=1.5294;
-
double Cup=0.0422;
-
double Adown=-0.7279;
-
double Bdown=0.6066;
-
double Cdown=0.1766;
-
-
for (int h=0; h<rgb.rows; h++)
-
{
-
for (int w=0; w<rgb.cols; w++)
-
{
-
auto* pGray = &gray.at<uchar>(h, w);
-
auto pRGB = rgb.at<Vec3b>(h, w);
-
-
int s=pRGB[R]+pRGB[G]+pRGB[B];
-
double r=(double)pRGB[R]/s;
-
double g=(double)pRGB[G]/s;
-
double Gup=Aup*r*r+Bup*r+Cup;
-
double Gdown=Adown*r*r+Bdown*r+Cdown;
-
double Wr=(r-0.33)*(r-0.33)+(g-0.33)*(g-0.33);
-
-
if (g<Gup && g>Gdown && Wr>0.004)
-
{
-
*pGray=255;
-
}
-
else
-
{
-
*pGray=0;
-
}
-
-
}
-
}
-
}
-
//
-
//第三种:otsu阈值化【仅限单通道】
-
// reference: Rafael C. Gonzalez. Digital Image Processing Using MATLAB
-
void ImageSkin::ImageThresholdOtsu(const Mat& src, Mat& dst)
-
{
-
int height=src.rows;
-
int width=src.cols;
-
-
// 统计直方图
-
float histogram[256]= {0};
-
for(int i=0; i<height; i++)
-
{
-
for(int j=0; j<width; j++)
-
{
-
uchar p = src.at<uchar>(i, j);
-
histogram[p]++;
-
}
-
}
-
-
// 直方图归一化
-
int size=height*width;
-
for(int i=0; i<256; i++)
-
{
-
histogram[i]=histogram[i]/size;
-
}
-
-
// 求像素平均值
-
float avgValue=0;
-
for(int i=0; i<256; i++)
-
{
-
avgValue+=i*histogram[i];
-
}
-
-
int tH;
-
float maxVariance=0;
-
float w=0,u=0;
-
for(int i=0; i<256; i++)
-
{
-
w+=histogram[i];
-
u+=i*histogram[i];
-
-
float t=avgValue*w-u;
-
float variance=t*t/(w*(1-w));
-
if(variance>maxVariance)
-
{
-
maxVariance=variance;
-
tH=i;
-
}
-
}
-
-
threshold(src, dst, tH, 255, CV_THRESH_BINARY);
-
}
-
//
-
//第四种:Ycrcb之cr分量+otsu阈值化
-
void ImageSkin::ImageSkinOtsu(const Mat& src, Mat& dst)
-
{
-
assert(dst.channels() == 1 && src.channels() == 3);
-
-
Mat ycrcb = Mat(src.size(), src.type(), 3);
-
Mat yCRcb[3];
-
-
cvtColor(src, ycrcb, CV_BGR2YCrCb);
-
split(ycrcb, yCRcb);
-
-
ImageThresholdOtsu(yCRcb[1], yCRcb[1]);
-
yCRcb[1].copyTo(dst);
-
-
yCRcb[1].release();
-
ycrcb.release();
-
}
-
//
-
//第五种:YCrCb中133<=Cr<=173 77<=Cb<=127
-
void ImageSkin::ImageSkinYUV(const Mat& src, Mat& dst)
-
{
-
Mat ycrcb = Mat(src.size(), src.type(), 3);
-
cvtColor(src, ycrcb, CV_BGR2YUV); // CV_BGR2YCrCb
-
-
static const int Cb=2;
-
static const int Cr=1;
-
static const int Y=0;
-
-
dst.setTo(Scalar(0, 0, 0));
-
-
for (int h=0; h<src.rows; h++)
-
{
-
for (int w=0; w<src.cols; w++)
-
{
-
const Vec3b* pycrcb = &ycrcb.at<Vec3b>(h, w);
-
const Vec3b* psrc = &src.at<Vec3b>(h, w);
-
//const uchar* pdst = &dst.at<uchar>(h, w);
-
-
if ((*pycrcb)[Cr]>=133 && (*pycrcb)[Cr]<=173 && (*pycrcb)[Cb]>=77 && (*pycrcb)[Cb]<=127)
-
{
-
memcpy(&dst.at<Vec3b>(h, w), psrc, 3);
-
}
-
}
-
}
-
-
}
测试代码:
-
int _tmain(int argc, _TCHAR* argv[])
-
{
-
Mat img = imread("..\\test.png", 1);
-
Mat dstRGB = Mat(img.size(), CV_8UC3);
-
Mat dstRG = Mat(img.size(), CV_8UC1);
-
Mat dst_crotsu = Mat(img.size(), CV_8UC1);
-
Mat dst_YUV = Mat(img.size(), CV_8UC3);
-
-
namedWindow("Original WIN", CV_WINDOW_AUTOSIZE);
-
imshow("Original WIN", img);
-
waitKey(0);
-
-
ImageSkin ImgS;
-
ImgS.ImageSkinRGB(img, dstRGB);
-
namedWindow("ImageSkinRGB WIN", CV_WINDOW_AUTOSIZE);
-
imshow("ImageSkinRGB WIN", dstRGB);
-
imwrite("..//ImageSkinRGB.jpg", dstRGB);
-
waitKey(0);
-
-
ImgS.ImageSkinRG(img, dstRG);
-
namedWindow("ImageSkinRG WIN", CV_WINDOW_AUTOSIZE);
-
imshow("ImageSkinRG WIN", dstRG);
-
imwrite("..//ImageSkinRG.jpg", dstRG);
-
waitKey(0);
-
-
ImgS.ImageSkinOtsu(img, dst_crotsu);
-
namedWindow("ImageSkinOtsu WIN", CV_WINDOW_AUTOSIZE);
-
imshow("ImageSkinOtsu WIN", dst_crotsu);
-
imwrite("..//ImageSkinOtsu.jpg", dst_crotsu);
-
waitKey(0);
-
-
ImgS.ImageSkinYUV(img, dst_YUV);
-
namedWindow("ImageSkinYUV WIN", CV_WINDOW_AUTOSIZE);
-
imshow("ImageSkinYUV WIN", dst_YUV);
-
imwrite("..//ImageSkinYUV.jpg", dst_YUV);
-
waitKey(0);
-
-
return 0;
-
}
结果显示如图:
本文代码参考了这位大牛的博客点击打开链接,我将它们修改为C++风格,便于自己和其他也习惯C++风格的朋友使用
文章来源: panda1234lee.blog.csdn.net,作者:panda1234lee,版权归原作者所有,如需转载,请联系作者。
原文链接:panda1234lee.blog.csdn.net/article/details/26730905
【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)