由于ofx Opencv 里的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;
}
}
}
其原理请移步
这里