void SkinRGB(IplImage* rgb, IplImage* _dst)
{
assert(rgb->nChannels == 3 && _dst->nChannels == 3);
static const int R = 2;
static const int G = 1;
static const int B = 0;
IplImage* dst = cvCreateImage(cvGetSize(_dst), 8, 3);
cvZero(dst);
for (int h = 0; h<rgb->height; h++)
{
unsigned char* prgb = (unsigned char*)rgb->imageData + h*rgb->widthStep;
unsigned char* pdst = (unsigned char*)dst->imageData + h*dst->widthStep;
for (int w = 0; w<rgb->width; 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])//lateral illumination
)
{
memcpy(pdst, prgb, 3);
}
prgb += 3;
pdst += 3;
}
}
cvCopy(dst, _dst);
cvReleaseImage(&dst);
}
// skin detection in rg space
void cvSkinRG(IplImage* rgb, IplImage* gray)
{
assert(rgb->nChannels == 3 && gray->nChannels == 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->height; h++)
{
unsigned char* pGray = (unsigned char*)gray->imageData + h*gray->widthStep;
unsigned char* pRGB = (unsigned char*)rgb->imageData + h*rgb->widthStep;
for (int w = 0; w<rgb->width; 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;
}
pGray++;
pRGB += 3;
}
}
}
// implementation of otsu algorithm
// author: onezeros#yahoo.cn
// reference: Rafael C. Gonzalez. Digital Image Processing Using MATLAB
void cvThresholdOtsu(IplImage* src, IplImage* dst)
{
int height = src->height;
int width = src->width;
//histogram
float histogram[256] = { 0 };
for (int i = 0; i<height; i++)
{
unsigned char* p = (unsigned char*)src->imageData + src->widthStep*i;
for (int j = 0; j<width; j++)
{
histogram[*p++]++;
}
}
//normalize histogram
int size = height*width;
for (int i = 0; i<256; i++)
{
histogram[i] = histogram[i] / size;
}
//average pixel value
float avgValue = 0;
for (int i = 0; i<256; i++)
{
avgValue += i*histogram[i];
}
int threshold;
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;
threshold = i;
}
}
cvThreshold(src, dst, threshold, 255, CV_THRESH_BINARY);
}
void cvSkinOtsu(IplImage* src, IplImage* dst)
{
assert(dst->nChannels == 1 && src->nChannels == 3);
IplImage* ycrcb = cvCreateImage(cvGetSize(src), 8, 3);
IplImage* cr = cvCreateImage(cvGetSize(src), 8, 1);
cvCvtColor(src, ycrcb, CV_BGR2YCrCb);
cvSplit(ycrcb, 0, cr, 0, 0);
cvThresholdOtsu(cr, cr);
cvCopy(cr, dst);
cvReleaseImage(&cr);
cvReleaseImage(&ycrcb);
}
void cvSkinYUV(IplImage* src, IplImage* dst)
{
IplImage* ycrcb = cvCreateImage(cvGetSize(src), 8, 3);
//IplImage* cr=cvCreateImage(cvGetSize(src),8,1);
//IplImage* cb=cvCreateImage(cvGetSize(src),8,1);
cvCvtColor(src, ycrcb, CV_BGR2YCrCb);
//cvSplit(ycrcb,0,cr,cb,0);
static const int Cb = 2;
static const int Cr = 1;
static const int Y = 0;
//IplImage* dst=cvCreateImage(cvGetSize(_dst),8,3);
cvZero(dst);
for (int h = 0; h<src->height; h++)
{
unsigned char* pycrcb = (unsigned char*)ycrcb->imageData + h*ycrcb->widthStep;
unsigned char* psrc = (unsigned char*)src->imageData + h*src->widthStep;
unsigned char* pdst = (unsigned char*)dst->imageData + h*dst->widthStep;
for (int w = 0; w<src->width; w++)
{
if (pycrcb[Cr] >= 133 && pycrcb[Cr] <= 173 && pycrcb[Cb] >= 77 && pycrcb[Cb] <= 127)
{
memcpy(pdst, psrc, 3);
}
pycrcb += 3;
psrc += 3;
pdst += 3;
}
}
//cvCopyImage(dst,_dst);
//cvReleaseImage(&dst);
}
void cvSkinHSV(IplImage* src, IplImage* dst)
{
IplImage* hsv = cvCreateImage(cvGetSize(src), 8, 3);
//IplImage* cr=cvCreateImage(cvGetSize(src),8,1);
//IplImage* cb=cvCreateImage(cvGetSize(src),8,1);
cvCvtColor(src, hsv, CV_BGR2HSV);
//cvSplit(ycrcb,0,cr,cb,0);
static const int V = 2;
static const int S = 1;
static const int H = 0;
//IplImage* dst=cvCreateImage(cvGetSize(_dst),8,3);
cvZero(dst);
for (int h = 0; h<src->height; h++)
{
unsigned char* phsv = (unsigned char*)hsv->imageData + h*hsv->widthStep;
unsigned char* psrc = (unsigned char*)src->imageData + h*src->widthStep;
unsigned char* pdst = (unsigned char*)dst->imageData + h*dst->widthStep;
for (int w = 0; w<src->width; w++)
{
if (phsv[H] >= 7 && phsv[H] <= 29)
{
memcpy(pdst, psrc, 3);
}
phsv += 3;
psrc += 3;
pdst += 3;
}
}
//cvCopyImage(dst,_dst);
//cvReleaseImage(&dst);
}
int main()
{
//IplImage* img = cvLoadImage("C:\C_C++ code\Photo and video\text009.jpg"); //随便放一张jpg图片在D盘或另行设置目录
//IplImage* dstRGB = cvCreateImage(cvGetSize(img), 8, 3);
//IplImage* dstRG = cvCreateImage(cvGetSize(img), 8, 1);
//IplImage* dst_YUV = cvCreateImage(cvGetSize(img), 8, 3);
//IplImage* dst_HSV = cvCreateImage(cvGetSize(img), 8, 3);
cvNamedWindow("inputimage", CV_WINDOW_AUTOSIZE);
cvShowImage("inputimage", img);
cvWaitKey(0);
SkinRGB(img, dstRGB);
cvNamedWindow("SkinRGB", CV_WINDOW_AUTOSIZE);
cvShowImage("SkinRGB", dstRGB);
cvWaitKey(0);
cvSkinRG(img, dstRG);
cvNamedWindow("cvSkinRG", CV_WINDOW_AUTOSIZE);
cvShowImage("cvSkinRG", dstRG);
cvWaitKey(0);
cvSkinOtsu(img, dst_crotsu);
cvNamedWindow("cvSkinOtsu", CV_WINDOW_AUTOSIZE);
cvShowImage("cvSkinOtsu", dst_crotsu);
cvWaitKey(0);
cvSkinYUV(img, dst_YUV);
cvNamedWindow("cvSkinYUV", CV_WINDOW_AUTOSIZE);
cvShowImage("cvSkinYUV", dst_YUV);
cvWaitKey(0);
cvSkinHSV(img, dst_HSV);
cvNamedWindow("cvSkinHSV", CV_WINDOW_AUTOSIZE);
cvShowImage("cvSkinHSV", dst_HSV);
cvWaitKey(0);
IplImage *src;
//VideoCapture video("C:\C_C++ EX8 code\Video\MyVideo.wmv");
VideoCapture video(0);
if (!video.isOpened())
{
return -1;
}
cv::Mat img, dstimg;
cv::Rect rect(170, 40, 240, 400);
video >> img;
src = &(IplImage(img));
IplImage* dst_crotsu = cvCreateImage(cvGetSize(src), 8, 1);
while (1)
{
video >> img;
src = &(IplImage(img));
cvSkinOtsu(src, dst_crotsu);
cvNamedWindow("cvSkinOtsu", CV_WINDOW_AUTOSIZE);
Mat output = cvarrToMat(dst_crotsu);
cv::erode(output, output, cv::Mat());
cv::erode(output, output, cv::Mat());
cv::erode(output, output, cv::Mat());
cv::erode(output, output, cv::Mat());
cv::dilate(output, output, cv::Mat());
imshow("cvSkinOtsu", output);
if (cv::waitKey(40) > 0)
{
break;
}
}
cvWaitKey(0);
return 0;
}