您的位置:首页 > 运维架构

openFrameworks使用ofxOpencv进行肤色检测

2014-02-27 14:56 405 查看
由于ofxOpencv里的ofxCVColorImage是RGB格式的,没想到调用getCvImage()函数得到的IplImage居然也是RGB格式,结果害得我一开始肤色检测的结果十分诡异。。。作者也够懒的,这么简单居然也不做个转换!

这个就是调换RB通道的代码:

void testApp::cvRGB_or_BGR(IplImage* src_image, IplImage* dst_image)
{
	if (src_image != NULL && dst_image != NULL)
	{
		uchar* src_data=(uchar *)src_image->imageData;
		uchar* dst_data=(uchar *)dst_image->imageData;

		int step = src_image->widthStep/sizeof(uchar);
		int channels = src_image->nChannels;
		//uchar *b,*g,*r;

		for(int i=0;i<src_image->height;i++)
		{
			for(int j=0;j<src_image->width;j++)
			{
				dst_data[i*step+j*channels + 2] = src_data[i*step+j*channels + 0];	// b
				dst_data[i*step+j*channels + 1] = src_data[i*step+j*channels + 1];	// g
				dst_data[i*step+j*channels] = src_data[i*step+j*channels + 2];		// r
			}
		}
	}

	//cvShowImage("RGB", dst_image);	// debug
}


以下是在网上找到的opencv基于c的肤色检测代码:

void testApp::cvSkinSegment(IplImage* img, IplImage* mask)	// mask是单通道的
{
	CvSize imageSize = cvSize(img->width, img->height);
	IplImage *imgY = cvCreateImage(imageSize, IPL_DEPTH_8U, 1);
	IplImage *imgCr = cvCreateImage(imageSize, IPL_DEPTH_8U, 1);
	IplImage *imgCb = cvCreateImage(imageSize, IPL_DEPTH_8U, 1);

	IplImage *imgYCrCb = cvCreateImage(imageSize, img->depth, img->nChannels);
	cvCvtColor(img,imgYCrCb,CV_BGR2YCrCb);
	//cvShowImage("img", img);			// debug
	//cvShowImage("YCrCb", imgYCrCb);	// debug

	cvSplit(imgYCrCb, imgY, imgCr, imgCb, 0);
	int y, cr, cb, l, x1, y1, value;
	unsigned char *pY, *pCr, *pCb, *pMask;

	pY = (unsigned char *)imgY->imageData;
	pCr = (unsigned char *)imgCr->imageData;
	pCb = (unsigned char *)imgCb->imageData;
	pMask = (unsigned char *)mask->imageData;
	cvSetZero(mask);

	l = img->height * img->width;

	for (int i = 0; i < l; i++)
	{
		y  = *pY;
		cr = *pCr;
		cb = *pCb;
		cb -= 109;
		cr -= 152
			;
		x1 = (819*cr-614*cb)/32 + 51;
		y1 = (819*cr+614*cb)/32 + 77;
		x1 = x1*41/1024;
		y1 = y1*73/1024;
		value = x1*x1+y1*y1;

		if(y<100)	
			(*pMask)=(value<700) ? 255:0;
		else		
			(*pMask)=(value<850)? 255:0;

		pY++;
		pCr++;
		pCb++;
		pMask++;
	}
	
	//cvShowImage("mask", mask);	// debug

	cvReleaseImage(&imgY);
	cvReleaseImage(&imgCr);
	cvReleaseImage(&imgCb);
	cvReleaseImage(&imgYCrCb);

	//return mask;
}


我移植的基于c++的肤色检测代码:

void testApp::cvSkinSegment(cv::Mat img, cv::Mat mask)	// mask是单通道的
{
	cv::Size imageSize = img.size();
	cv::Mat imgY, imgCr, imgCb;
	cv::Mat imgYCrCb = cv::Mat(imageSize, CV_8UC3);
	vector<cv::Mat> imgVec;

	cvtColor(img,imgYCrCb,CV_BGR2YCrCb);
	
	split(imgYCrCb, imgVec);
	imgY = imgVec[0];
	imgCr = imgVec[1];
	imgCb = imgVec[2];

	int y, cr, cb, x1, y1, value;
	uchar *pY, *pCr, *pCb, *pMask;

	mask.zeros(mask.size(), mask.type());
	
	int nRows = img.rows;
	int nCols = img.cols;

	for (int i = 0; i < nRows; i++)
	{
		pY = imgY.ptr<uchar>(i);
		pCr = imgCr.ptr<uchar>(i);
		pCb = imgCb.ptr<uchar>(i);
		pMask = mask.ptr<uchar>(i);

		for (int j = 0; j<nCols; j++)
		{
			y  = pY[j];
			cr = pCr[j];
			cb = pCb[j];
			cb -= 109;
			cr -= 152;

			x1 = (819*cr - 614*cb)/32 + 51;
			y1 = (819*cr + 614*cb)/32 + 77;
			x1 = x1 * 41/1024;
			y1 = y1 * 73/1024;
			value = x1*x1 + y1*y1;

			if(y<100)	
				(pMask[j])=(value<700) ? 255:0;
			else		
				(pMask[j])=(value<850)? 255:0;
		}
		
	}
	
}


其原理请移步这里
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: