生活随笔
收集整理的這篇文章主要介紹了
opencv 肤色
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
先貼代碼
[cpp] view plain
copy void?cvSkinSegment(IplImage*?img,?IplImage*?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);?? ????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++;?? ????}?? ????cvReleaseImage(&imgY);?? ????cvReleaseImage(&imgCr);?? ????cvReleaseImage(&imgCb);?? ????cvReleaseImage(&imgYCrCb);?? }??
主要原理就是通過在Cb Cr空間上找到一個可以擬合常規膚色分布的橢圓形,然后把在橢圓形區域內的像素點標記為膚色
圖1.1 橢圓模板示例
以上插圖來源于《一種基于KL變換的橢圓模型膚色檢測方法?》,具體參數參考的那篇文獻時間久遠找不到了
?
以下是代碼運行后的效果圖
圖1.2 運行效果1
?
圖1.3 運行效果2
?
從上面兩圖可以看出,在光線條件比較理想的情況下,膚色檢測的效果還是不錯的(1.2就比1.3效果好),但是對于一些似膚色區域(比如圖1.3后面的木質門),還是會被誤檢,但這是膚色檢測無法解決的問題。
?
關于效果圖里面一些類似噪點的部分,可以通過膨脹腐蝕模糊再二值化的方法取得比較圓潤的膚色圖(就是可以做mask的)
[c-sharp]?view plain
?copy cvErode(pSkin,?pSkin,?NULL,?1);??????? cvDilate(pSkin,?pSkin,?NULL,?1);?? cvSmooth(pSkin,?pSkin,?CV_GAUSSIAN,?21,?0,?0);?? cvThreshold(pSkin,?pSkin,130,?255,?CV_THRESH_BINARY);??
?
當然有時候效果也不是特別好,這個要靠自己調參數的。
?
總體而言,與OpenCV2.0的adapativeskindetector.cpp相比的話,效果要好(其實我改進的代碼就是參照里面CvAdaptiveSkinDetector類里的process函數的),當然也有可能是因為我的膚色檢測是根據我所處環境的光照條件和攝像頭特性調節的緣故。
?
最后,小小地對代碼作一個說明。
其實代碼很簡單,就是把Y Cb Cr三個通道分開,然后用指針分別對這三個通道的每一個像素進行處理。
需要作修改的就是if(y<100) (*pMask)=(value<700) ? 255:0;?else (*pMask)=(value<850)? 255:0; 這條做閾值判斷的命令
由于光照和攝像頭性能的不同,這里的閾值需要根據自己的攝像頭調節出最合適的效果才可以
?
另外的話,對于質量不是很好的WebCam 建議在輸入圖像上加一個小點的高斯模糊以去除噪點
?
以上算法還曾經作為我的大作業在Matlab和Xilinx FPGA上實現,具體可以參考我的答辯PPT:Skin Segmentation on FPGA
總結
以上是生活随笔為你收集整理的opencv 肤色的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。