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; }