OpenCV皮肤检测技术对比与总结
opencv做皮膚檢測(cè)的技術(shù)總結(jié)。那首先列一些現(xiàn)在主流的皮膚檢測(cè)的方法都有哪些:
一、基于RGB的皮膚檢測(cè)
根據(jù)RGB顏色模型找出定義好的膚色范圍內(nèi)的像素點(diǎn),范圍外的像素點(diǎn)設(shè)為黑色。
查閱資料后可以知道,前人做了大量研究,膚色在RGB模型下的范圍基本滿足以下約束:
在均勻光照下應(yīng)滿足以下判別式:
R>95 AND G>40 B>20 AND MAX(R,G,B)-MIN(R,G,B)>15 AND ABS(R-G)>15 AND R>G AND R>B
在側(cè)光拍攝環(huán)境下:
R>220 AND G>210 AND B>170 AND ABS(R-G)<=15 AND R>B AND G>B
既然判別式已經(jīng)確定了,所以按照判別式寫程序就很簡(jiǎn)單了。
/*基于RGB范圍的皮膚檢測(cè)*/ Mat RGB_detect(Mat& img) {/*R>95 AND G>40 B>20 AND MAX(R,G,B)-MIN(R,G,B)>15 AND ABS(R-G)>15 AND R>G AND R>BORR>220 AND G>210 AND B>170 AND ABS(R-G)<=15 AND R>B AND G>B*/Mat detect = img.clone();detect.setTo(0);if (img.empty() || img.channels() != 3){return detect;}for (int i = 0; i < img.rows; i++){for (int j = 0; j < img.cols; j++){uchar *p_detect = detect.ptr<uchar>(i, j);uchar *p_img = img.ptr<uchar>(i, j);if ((p_img[2] > 95 && p_img[1]>40 && p_img[0] > 20 &&(MAX(p_img[0], MAX(p_img[1], p_img[2])) - MIN(p_img[0], MIN(p_img[1], p_img[2])) > 15) &&abs(p_img[2] - p_img[1]) > 15 && p_img[2] > p_img[1] && p_img[1] > p_img[0]) ||(p_img[2] > 200 && p_img[1] > 210 && p_img[0] > 170 && abs(p_img[2] - p_img[1]) <= 15 &&p_img[2] > p_img[0] && p_img[1] > p_img[0])){p_detect[0] = p_img[0];p_detect[1] = p_img[1];p_detect[2] = p_img[2];}}}return detect; }檢測(cè)效果如下:
從檢測(cè)結(jié)果可以看出,皮膚的檢測(cè)效果并不好,首先皮膚檢測(cè)的完整性并不高,一些稍微光線不好的區(qū)域也沒法檢測(cè)出皮膚來(lái)。第二,這種基于RBG范圍來(lái)判定皮膚的算法太受光線的影響了,魯棒性確實(shí)不好。
二、基于橢圓皮膚模型的皮膚檢測(cè)
經(jīng)過(guò)前人學(xué)者大量的皮膚統(tǒng)計(jì)信息可以知道,如果將皮膚信息映射到Y(jié)CrCb空間,則在CrCb二維空間中這些皮膚像素點(diǎn)近似成一個(gè)橢圓分布。因此如果我們得到了一個(gè)CrCb的橢圓,下次來(lái)一個(gè)坐標(biāo)(Cr, Cb)我們只需判斷它是否在橢圓內(nèi)(包括邊界),如果是,則可以判斷其為皮膚,否則就是非皮膚像素點(diǎn)。
/*基于橢圓皮膚模型的皮膚檢測(cè)*/ Mat ellipse_detect(Mat& src) {Mat img = src.clone();Mat skinCrCbHist = Mat::zeros(Size(256, 256), CV_8UC1);//利用opencv自帶的橢圓生成函數(shù)先生成一個(gè)膚色橢圓模型ellipse(skinCrCbHist, Point(113, 155.6), Size(23.4, 15.2), 43.0, 0.0, 360.0, Scalar(255, 255, 255), -1);Mat ycrcb_image;Mat output_mask = Mat::zeros(img.size(), CV_8UC1);cvtColor(img, ycrcb_image, CV_BGR2YCrCb); //首先轉(zhuǎn)換成到Y(jié)CrCb空間for (int i = 0; i < img.cols; i++) //利用橢圓皮膚模型進(jìn)行皮膚檢測(cè)for (int j = 0; j < img.rows; j++){Vec3b ycrcb = ycrcb_image.at<Vec3b>(j, i);if (skinCrCbHist.at<uchar>(ycrcb[1], ycrcb[2]) > 0) //如果該落在皮膚模型橢圓區(qū)域內(nèi),該點(diǎn)就是皮膚像素點(diǎn)output_mask.at<uchar>(j, i) = 255;}Mat detect;img.copyTo(detect,output_mask); //返回膚色圖return detect; }?檢測(cè)效果:
這種基于膚色橢圓模型的算法的皮膚檢測(cè)較上面算法在效果上有著較大的提升,基本上改檢測(cè)的皮膚都檢測(cè)到了,對(duì)光線的抗干擾能力也是比較強(qiáng)的,檢測(cè)出來(lái)的圖像都比較干凈,背景雜質(zhì)較少。
三、YCrCb顏色空間Cr分量+Otsu法閾值分割
這里先簡(jiǎn)單介紹YCrCb顏色空間。
YCrCb即YUV,其中“Y”表示明亮度(Luminance或Luma),也就是灰階值;而“U”和“V” 表示的則是色度(Chrominance或Chroma),作用是描述影像色彩及飽和度,用于指定像素的顏色。“亮度”是透過(guò)RGB輸入信號(hào)來(lái)建立的,方法是將RGB信號(hào)的特定部分疊加到一起。“色度”則定義了顏色的兩個(gè)方面─色調(diào)與飽和度,分別用Cr和Cb來(lái)表示。其中,Cr反映了RGB輸入信號(hào)紅色部分與RGB信號(hào)亮度值之間的差異。而Cb反映的是RGB輸入信號(hào)藍(lán)色部分與RGB信號(hào)亮度值之間的差異。
該方法的原理也很簡(jiǎn)單:
a.將RGB圖像轉(zhuǎn)換到Y(jié)CrCb顏色空間,提取Cr分量圖像
b.對(duì)Cr做自二值化閾值分割處理(Otsu法)
/*YCrCb顏色空間Cr分量+Otsu法*/ Mat YCrCb_Otsu_detect(Mat& src) {Mat ycrcb_image;cvtColor(src, ycrcb_image, CV_BGR2YCrCb); //首先轉(zhuǎn)換成到Y(jié)CrCb空間Mat detect;vector<Mat> channels;split(ycrcb_image, channels);Mat output_mask = channels[1];threshold(output_mask, output_mask, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);src.copyTo(detect, output_mask);return detect; }?檢測(cè)效果:
四、基于YCrCb顏色空間Cr,Cb范圍篩選法
這個(gè)方法跟法一其實(shí)大同小異,只是顏色空間不同而已。據(jù)資料顯示,正常黃種人的Cr分量大約在133至173之間,Cb分量大約在77至127之間。大家可以根據(jù)自己項(xiàng)目需求放大或縮小這兩個(gè)分量的范圍,會(huì)有不同的效果。
/*YCrCb顏色空間Cr,Cb范圍篩選法*/ Mat YCrCb_detect(Mat & src) {Mat ycrcb_image;int Cr = 1;int Cb = 2;cvtColor(src, ycrcb_image, CV_BGR2YCrCb); //首先轉(zhuǎn)換成到Y(jié)CrCb空間Mat output_mask = Mat::zeros(src.size(), CV_8UC1);for (int i = 0; i < src.rows; i++){for (int j = 0; j < src.cols; j++){uchar *p_mask = output_mask.ptr<uchar>(i, j);uchar *p_src = ycrcb_image.ptr<uchar>(i, j);if (p_src[Cr] >= 133 && p_src[Cr] <= 173 && p_src[Cb] >= 77 && p_src[Cb] <= 127){p_mask[0] = 255;}}}Mat detect;src.copyTo(detect, output_mask);;return detect; }?檢測(cè)效果:
五、HSV顏色空間H范圍篩選法
同樣地,也是在不同的顏色空間下采取相應(yīng)的顏色范圍將皮膚分割出來(lái)。
/*HSV顏色空間H范圍篩選法*/ Mat HSV_detector(Mat& src) {Mat hsv_image;int h = 0;int s = 1;int v = 2;cvtColor(src, hsv_image, CV_BGR2HSV); //首先轉(zhuǎn)換成到Y(jié)CrCb空間Mat output_mask = Mat::zeros(src.size(), CV_8UC1);for (int i = 0; i < src.rows; i++){for (int j = 0; j < src.cols; j++){uchar *p_mask = output_mask.ptr<uchar>(i, j);uchar *p_src = hsv_image.ptr<uchar>(i, j);if (p_src[h] >= 0 && p_src[h] <= 20 && p_src[s] >=48 && p_src[v] >=50){p_mask[0] = 255;}}}Mat detect;src.copyTo(detect, output_mask);;return detect; }檢測(cè)效果:
?
這篇文章對(duì)各大主流的皮膚檢測(cè)算法做了個(gè)總結(jié)和實(shí)現(xiàn)。其實(shí)說(shuō)白了,每個(gè)算法的思想都是大同小異的,都是根據(jù)總結(jié)出來(lái)的一些經(jīng)驗(yàn),設(shè)定皮膚顏色的范圍,再將其過(guò)濾出來(lái),不同的只是過(guò)濾的過(guò)程在不同的顏色空間下進(jìn)行而已。我們可以根據(jù)自己的應(yīng)用場(chǎng)景,適當(dāng)?shù)匦薷倪@些范圍,以獲得滿意的結(jié)果。可以改善的方向就是,我們可以用合適的濾波器或者形態(tài)學(xué)處理一些噪聲,來(lái)使得提取出來(lái)的皮膚更為干凈。
總結(jié)
以上是生活随笔為你收集整理的OpenCV皮肤检测技术对比与总结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: java h5 桌面应用_用HTML5打
- 下一篇: VS2015+QT5.8 程序打包发布详