在对物体做初步检测时,颜色信息非常有用。如可用来检测皮肤的颜色,检测到的皮肤区域可作为图像中有人存在的标志。在手势识别中经常使用这个方法,用肤色检测来确定手的位置。
在下面的例子中,我们将使用色调和饱和度来识别肤色,定义一个基于数值区间(最小和最大色调,最小和最大饱和度)的函数,把图像中的像素分为皮肤和非皮肤两类:
完整代码如下:
#include <iostream>#include <opencv2/core/core.hpp>#include <opencv2/highgui/highgui.hpp>#include <opencv2/opencv.hpp>using namespace cv;using namespace std;void detectHcolor(const Mat &image, //输入图像 double minHue,double maxHue, //色调(Hue)区间 double minSat,double maxSat, //饱和度(saturation)区间 Mat &mask) //输出掩码{ Mat hsv;//转换到HSV空间 cvtColor(image, hsv, CV_BGR2HSV);//将图像从一个色彩空间转换为另一个色彩空间 std::vector<Mat>channels;//分割3个通道,并存进3个图像 split(hsv, channels);//channels[0]是色调 //channels[1]是饱和度 //channels[2]是亮度 //色调掩码 Mat mask1;//小于maxHue threshold(channels[0], mask1, maxHue, 255, THRESH_BINARY_INV); Mat mask2;//大于minHue threshold(channels[0], mask2, minHue, 255, THRESH_BINARY); Mat hueMask;//色调掩码 if (minHue<maxHue) hueMask=mask1&mask2; else //如果区间穿越0度中轴线 hueMask=mask1|mask2; //饱和度掩码 //小于maxSat threshold(channels[1], mask1, maxSat, 255, THRESH_BINARY_INV); //大于minSat threshold(channels[1], mask2, minSat, 255, THRESH_BINARY); Mat satMask;//饱和度掩码 satMask=mask1&mask2; //组合掩码 mask=hueMask&satMask;}int main( ){ Mat image=imread("/Users/zhangxiaoyu/Desktop/3.png"); if(image.empty()) { cout<<"Error!cannot be read...../n"; return -1; } Mat mask; detectHcolor(image, 160, 10, 25, 166, mask); Mat detected(image.size(),CV_8UC3,Scalar(0,0,0)); image.copyTo(detected,mask); namedWindow("detectedimage"); imshow("detectedimage", detected); waitKey(0); }有关图像掩码:OPENCV中的有些操作可以用来定义掩码。函数或方法通常对图像中所有像素进行操作,通过定义掩码可以限制这些函数或方法的作用范围。掩码是一个8位图像,如果掩码中某个位置的值不为0,在这个位置上的操作就会起作用;如果掩码中某些像素位置的值为0,那么对图像中相应位置的操作将不起作用。
CV_EXPORTS_W double threshold( InputArray src,OutputArray dst,double thresh,double maxval, int type );
参数说明:
src:原始数组 (单通道 , 8-bit of 32-bit 浮点数)。dst:输出数组,必须与 src 的类型一致,或者为 8-bit。threshold:阈值max_value:使用 CV_THRESH_BINARY 和 CV_THRESH_BINARY_INV 的最大值。threshold_type:阈值类型threshold_type=CV_THRESH_BINARY:如果 src(x,y)>threshold ,dst(x,y) = max_value; 否则,dst(x,y)=0;threshold_type=CV_THRESH_BINARY_INV:如果 src(x,y)>threshold,dst(x,y) = 0; 否则,dst(x,y) = max_value.threshold_type=CV_THRESH_TRUNC:如果 src(x,y)>threshold,dst(x,y) = max_value; 否则dst(x,y) = src(x,y).threshold_type=CV_THRESH_TOZERO:如果src(x,y)>threshold,dst(x,y) = src(x,y) ; 否则 dst(x,y) = 0。threshold_type=CV_THRESH_TOZERO_INV:如果 src(x,y)>threshold,dst(x,y) = 0 ; 否则dst(x,y) = src(x,y).测试用原始图像如下所示:检测结果图像如下所示:
显然可见,对皮肤颜色进行可靠准确的检测需要更佳精确的基于大批量皮肤样本的分析。并且对不同的图像进行检测,很难保证都有好的效果。在人物摄影时影响彩色再现的因素很多,如白平衡和光照条件等。使用以上的方法只是做一个初步的检测。
新闻热点
疑难解答