今天是地球日,就選了張相關主題的映像做測試
第一種:RGB color space
第二種:RG color space
第三種:Ycrcb之cr分量+otsu閾值化
還有別的一些模型,效果不太好就不貼了
1.rgb model
// skin region location using rgb limitation<br />void SkinRGB(IplImage* rgb,IplImage* _dst)<br />{<br />assert(rgb->nChannels==3&& _dst->nChannels==3);</p><p>static const int R=2;<br />static const int G=1;<br />static const int B=0;</p><p>IplImage* dst=cvCreateImage(cvGetSize(_dst),8,3);<br />cvZero(dst);</p><p>for (int h=0;h<rgb->height;h++) {<br />unsigned char* prgb=(unsigned char*)rgb->imageData+h*rgb->widthStep;<br />unsigned char* pdst=(unsigned char*)dst->imageData+h*dst->widthStep;<br />for (int w=0;w<rgb->width;w++) {<br />if ((prgb[R]>95 && prgb[G]>40 && prgb[B]>20 &&<br />prgb[R]-prgb[B]>15 && prgb[R]-prgb[G]>15/*&&<br />!(prgb[R]>170&&prgb[G]>170&&prgb[B]>170)*/)||//uniform illumination<br />(prgb[R]>200 && prgb[G]>210 && prgb[B]>170 &&<br />abs(prgb[R]-prgb[B])<=15 && prgb[R]>prgb[B]&& prgb[G]>prgb[B])//lateral illumination<br />) {<br />memcpy(pdst,prgb,3);<br />}<br />prgb+=3;<br />pdst+=3;<br />}<br />}<br />cvCopyImage(dst,_dst);<br />cvReleaseImage(&dst);<br />}<br />
2.rg model
// skin detection in rg space<br />void cvSkinRG(IplImage* rgb,IplImage* gray)<br />{<br />assert(rgb->nChannels==3&&gray->nChannels==1);</p><p>const int R=2;<br />const int G=1;<br />const int B=0;</p><p>double Aup=-1.8423;<br />double Bup=1.5294;<br />double Cup=0.0422;<br />double Adown=-0.7279;<br />double Bdown=0.6066;<br />double Cdown=0.1766;<br />for (int h=0;h<rgb->height;h++) {<br />unsigned char* pGray=(unsigned char*)gray->imageData+h*gray->widthStep;<br />unsigned char* pRGB=(unsigned char* )rgb->imageData+h*rgb->widthStep;<br />for (int w=0;w<rgb->width;w++) {<br />int s=pRGB[R]+pRGB[G]+pRGB[B];<br />double r=(double)pRGB[R]/s;<br />double g=(double)pRGB[G]/s;<br />double Gup=Aup*r*r+Bup*r+Cup;<br />double Gdown=Adown*r*r+Bdown*r+Cdown;<br />double Wr=(r-0.33)*(r-0.33)+(g-0.33)*(g-0.33);<br />if (g<Gup && g>Gdown && Wr>0.004){<br />*pGray=255;<br />}else{<br />*pGray=0;<br />}<br />pGray++;<br />pRGB+=3;<br />}<br />}</p><p>}<br />
3.cr+otsu
// implementation of otsu algorithm<br />// author: onezeros#yahoo.cn<br />// reference: Rafael C. Gonzalez. Digital Image Processing Using MATLAB<br />void cvThresholdOtsu(IplImage* src, IplImage* dst)<br />{<br />int height=src->height;<br />int width=src->width;</p><p>//histogram<br />float histogram[256]={0};<br />for(int i=0;i<height;i++) {<br />unsigned char* p=(unsigned char*)src->imageData+src->widthStep*i;<br />for(int j=0;j<width;j++) {<br />histogram[*p++]++;<br />}<br />}<br />//normalize histogram<br />int size=height*width;<br />for(int i=0;i<256;i++) {<br />histogram[i]=histogram[i]/size;<br />}</p><p>//average pixel value<br />float avgValue=0;<br />for(int i=0;i<256;i++) {<br />avgValue+=i*histogram[i];<br />}</p><p>int threshold;<br />float maxVariance=0;<br />float w=0,u=0;<br />for(int i=0;i<256;i++) {<br />w+=histogram[i];<br />u+=i*histogram[i];</p><p>float t=avgValue*w-u;<br />float variance=t*t/(w*(1-w));<br />if(variance>maxVariance) {<br />maxVariance=variance;<br />threshold=i;<br />}<br />}</p><p>cvThreshold(src,dst,threshold,255,CV_THRESH_BINARY);<br />}</p><p>void cvSkinOtsu(IplImage* src, IplImage* dst)<br />{<br />assert(dst->nChannels==1&& src->nChannels==3);</p><p>IplImage* ycrcb=cvCreateImage(cvGetSize(src),8,3);<br />IplImage* cr=cvCreateImage(cvGetSize(src),8,1);<br />cvCvtColor(src,ycrcb,CV_BGR2YCrCb);<br />cvSplit(ycrcb,0,cr,0,0);</p><p>cvThresholdOtsu(cr,cr);<br />cvCopyImage(cr,dst);<br />cvReleaseImage(&cr);<br />cvReleaseImage(&ycrcb);<br />}
原映像
rgb model
rg model
otsu+cr