在對物體做初步檢測時,顏色信息非常有用。如可用來檢測皮膚的顏色,檢測到的皮膚區域可作爲圖像中有人存在的標誌。在手勢識別中經常使用這個方法,用膚色檢測來確定手的位置。
在下面的例子中,我們將使用色調和飽和度來識別膚色,定義一個基於數值區間(最小和最大色調,最小和最大飽和度)的函數,把圖像中的像素分爲皮膚和非皮膚兩類:
完整代碼如下:
#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 );
參數說明:
顯然可見,對皮膚顏色進行可靠準確的檢測需要更佳精確的基於大批量皮膚樣本的分析。並且對不同的圖像進行檢測,很難保證都有好的效果。在人物攝影時影響彩色再現的因素很多,如白平衡和光照條件等。使用以上的方法只是做一個初步的檢測。