膚色似然

膚色似然圖像以及圖像二值化的源代碼,轉自http://hi.baidu.com/cinvent_new/blog/item/c9cd2039e088ae2497ddd8d1.html
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <math.h>
  4. #include <cv.h>
  5. #include <highgui.h>
  6. #include<iostream.h>
  7. IplImage secaipingheng(IplImage* seping);//色彩平衡
  8. IplImage fusesiran(IplImage* fusi);//膚色似然
  9. int main(int argc, char *argv[])
  10. {
  11. IplImage* img = 0; // 原圖
  12. IplImage* seping = 0;//色彩平衡
  13. IplImage* ycbcr = 0;//ycbcr
  14. IplImage* fusi = 0;//膚色似然
  15. IplImage* fu = 0;//膚色
  16. img=cvLoadImage("1.jpg",-1);//加載圖像
  17. if(!img)
  18. {
  19. cout<<"圖片不存在"<<endl;
  20. return 0;
  21. }
  22. cvNamedWindow("原圖", 0); 
  23. cvResizeWindow("原圖",200,200);
  24. cvMoveWindow("原圖",400,400);
  25. cvShowImage("原圖", img );
  26. seping=cvCreateImage(cvSize(img->width,img->height),IPL_DEPTH_8U,3);
  27. ycbcr=cvCreateImage(cvSize(img->width,img->height),IPL_DEPTH_8U,3);
  28. fusi=cvCreateImage(cvSize(img->width,img->height),IPL_DEPTH_8U,1);
  29. fu=cvCreateImage(cvSize(img->width,img->height),IPL_DEPTH_8U,3);
  30. *seping=secaipingheng(img);
  31. //cvNamedWindow("色彩平衡", CV_WINDOW_AUTOSIZE); 
  32. //cvShowImage("色彩平衡", seping);
  33. cvSmooth(seping, seping,CV_MEDIAN ,3,0,0,0 );
  34. cvCvtColor(seping, ycbcr, CV_RGB2YCrCb);// rgb->ycrcb
  35. *fusi=fusesiran(ycbcr);
  36. //cvNamedWindow("膚色似然", CV_WINDOW_AUTOSIZE); 
  37. //cvShowImage("膚色似然", fusi);
  38. int height,width,step,channels;
  39. uchar *data;
  40. height = img->height; 
  41. width = img->width; 
  42. step = img->widthStep; 
  43. channels = img->nChannels;
  44. data = (uchar *)img->imageData;
  45. int i,j;
  46. for(i=0;i<height;i++) for(j=0;j<width;j++)
  47. {
  48. if(((fusi->imageData + fusi->widthStep*i))[j]==0)
  49. {
  50.    data[i*step+j*channels+0]=0;
  51.    data[i*step+j*channels+1]=0;
  52.    data[i*step+j*channels+2]=0;
  53. }
  54. }
  55. cvNamedWindow("膚色圖", 0); 
  56. cvResizeWindow("膚色圖",200,200);
  57. cvMoveWindow("膚色圖",615,400);
  58. cvShowImage("膚色圖", img );
  59. //cvSaveImage("haha.jpg", img);//
  60. cvWaitKey(0);
  61. //cvDestroyWindow( "原圖" );//銷燬窗口
  62. //cvReleaseImage( &img ); //釋放圖像
  63. //cvDestroyWindow( "膚色圖" );//銷燬窗口
  64. //cvReleaseImage( &img ); //釋放圖像
  65. //cvDestroyWindow( "色彩平衡" );//銷燬窗口
  66. cvReleaseImage( &seping ); //釋放圖像
  67. //cvDestroyWindow( "膚色似然" );//銷燬窗口
  68. cvReleaseImage( &fusi ); //釋放圖像
  69. return 1;
  70. }
  71. ///////////////////////////////////色彩平衡//////////////////////////////////////////////////////
  72. IplImage secaipingheng( IplImage* seping)
  73. {
  74. IplImage* dst;//色彩平衡
  75. IplImage* gray;//gray圖
  76. dst=cvCreateImage(cvSize(seping->width,seping->height),IPL_DEPTH_8U,3);
  77. gray=cvCreateImage(cvSize(seping->width,seping->height),IPL_DEPTH_8U,1);
  78. int height,width,step,channels;
  79. uchar *data,*data1;
  80. height = seping->height; 
  81. width = seping->width;
  82. step = seping->widthStep; 
  83. channels = seping->nChannels;
  84. data = (uchar *)seping->imageData;
  85. data1 = (uchar *)dst->imageData;
  86. int i,j;
  87. double R,G,B,Gy,aR,aG,aB;
  88. cvZero(dst);
  89. CvMat* MR=cvCreateMat(height,width,CV_64FC1);
  90. CvMat* MG=cvCreateMat(height,width,CV_64FC1);
  91. CvMat* MB=cvCreateMat(height,width,CV_64FC1);
  92. for(i=0;i<height;i++) for(j=0;j<width;j++)
  93. {
  94.    R=data[i*step+j*channels+0];
  95.    G=data[i*step+j*channels+1];
  96.    B=data[i*step+j*channels+2];
  97.    Gy=((gray->imageData + gray->widthStep*i))[j];
  98. cvmSet(MR,i,j,R);
  99. cvmSet(MG,i,j,G);
  100. cvmSet(MB,i,j,B);
  101. ((gray->imageData + gray->widthStep*i))[j]=(R+G+B)/3;
  102. }
  103. CvScalar argR,argG,argB;
  104. double argI;
  105. argR=cvAvg(MR,0);
  106. argG=cvAvg(MG,0);
  107. argB=cvAvg(MB,0);
  108. argI=(argR.val[0]+argG.val[0]+argB.val[0])/3;
  109. aR=argI/argR.val[0];
  110. aG=argI/argG.val[0];
  111. aB=argI/argB.val[0];
  112. for(i=0;i<height;i++) for(j=0;j<width;j++)
  113. {
  114. R=CV_MAT_ELEM(*MR,double,i,j)*aR;
  115. G=CV_MAT_ELEM(*MG,double,i,j)*aG;
  116. B=CV_MAT_ELEM(*MB,double,i,j)*aB;
  117. if(R>255)data1[i*step+j*channels+0]=255;
  118. else data1[i*step+j*channels+0]=R;
  119. if(G>255)data1[i*step+j*channels+1]=255;
  120. else data1[i*step+j*channels+1]=G;
  121. if(B>255)data1[i*step+j*channels+2]=255;
  122. else data1[i*step+j*channels+2]=B;
  123. }
  124. cvNamedWindow("色彩平衡", CV_WINDOW_AUTOSIZE); 
  125. cvShowImage("色彩平衡", dst);
  126. //cvWaitKey(0);
  127. //cvDestroyWindow( "色彩平衡" );//銷燬窗口
  128. //cvReleaseImage( &dst ); //釋放圖像
  129. return *dst;
  130. }
  131. //////////////////////////////////膚色似然////////////////////////////////////////////////
  132. IplImage fusesiran(IplImage* fusi)
  133. {
  134. IplImage* dst;//膚色圖
  135. dst=cvCreateImage(cvSize(fusi->width,fusi->height),IPL_DEPTH_8U,1);
  136. int height,width,step,channels;
  137. uchar *data;
  138. height = fusi->height; 
  139. width = fusi->width; 
  140. step = fusi->widthStep; 
  141. channels = fusi->nChannels;
  142. data = (uchar *)fusi->imageData;
  143. double c[4]={0.0077 ,-0.0041,-0.0041 ,0.0047};
  144. CvMat* max=cvCreateMat(height,width,CV_64FC1);//存儲膚色概率密度矩陣(數組)
  145. CvMat* mat=cvCreateMat(2,2,CV_64FC1);//存儲協方差矩陣(逆)
  146. CvMat* a=cvCreateMat(1,2,CV_64FC1);//{cb,cr}
  147. CvMat* a1=cvCreateMat(2,1,CV_64FC1);//{cb,cr}轉至
  148. CvMat* res=cvCreateMat(1,1,CV_64FC1);
  149. cvInitMatHeader(mat,2,2,CV_64FC1,c);
  150. double res1[1]={0};
  151. cvInitMatHeader(res,1,1,CV_64FC1,res1);
  152. int i,j;
  153. double b,r,cb,cr,u;
  154. //按照上面的公式進行膚色似然度計算
  155. for(i=0;i<height;i++)
  156. for(j=0;j<width;j++)
  157. {
  158. b=data[i*step+j*channels+1];//cb 分量
  159. r=data[i*step+j*channels+2];//cr 分量
  160. cb=b-103.0056;////117.4361
  161. cr=r-140.1309;////156.5599
  162. double p1[2]={cb,cr};
  163. cvInitMatHeader(a,1,2,CV_64FC1,p1);
  164. cvMatMulAdd(a,mat,0,a);
  165. double p2[2]={cb,cr};///////////////////////////////////////
  166. cvInitMatHeader(a1,2,1,CV_64FC1,p2);
  167. cvMatMulAdd(a,a1,0,res);
  168. u=CV_MAT_ELEM(*res,double,0,0);
  169. u=exp(-0.5*u);
  170. cvmSet(max,i,j,u);
  171. }
  172. double max1=0; //初始化最大值
  173. double mm=0;
  174. cvMinMaxLoc(max,NULL,&max1,NULL,NULL);
  175. //膚色似然度
  176. for(i=0;i<height;i++) for(j=0;j<width;j++)
  177. {
  178. mm=CV_MAT_ELEM(*max,double,i,j)/max1;
  179. cvmSet(max,i,j,255*mm);
  180. ((dst->imageData + dst->widthStep*i))[j]=255*mm;
  181. }
  182. //cvNamedWindow("膚色6", CV_WINDOW_AUTOSIZE); 
  183. //cvShowImage("膚色6", dst );
  184. double n[256],p[256];
  185. for(i=0;i<256;i++)
  186. {
  187. n[i]=0;
  188.     p[i]=0;
  189. }
  190. int nn;
  191. for(i=0;i<height;i++) for(j=0;j<width;j++)
  192. {
  193. nn=int(CV_MAT_ELEM(*max,double,i,j));
  194. n[nn]++;
  195. }
  196. for(i=0;i<256;i++)
  197. p[i]=n[i]/(height*width);
  198. double q,w0,w1,u0,u1,ut,Q[]={0,0,0,0,0,0,0,0,0,0};
  199. int flag=0;
  200. for(int m=10;m<=190;m+=20)
  201. {
  202. q=0;w0=0;w1=0;u0=0;u1=0;ut=0;
  203. for(i=0;i<=m;i++)       w0+=p[i];
  204. for(i=m+1;i<=255;i++)   w1+=p[i];
  205. for(i=0;i<=m;i++)       u0+=i*p[i]/w0;
  206. for(i=m+1;i<=255;i++)   u1+=i*p[i]/w1;
  207. for(i=0;i<=255;i++)     ut+=i*p[i];
  208. q=w0*(u0-ut)*(u0-ut)+w1*(u1-ut)*(u1-ut);
  209. if (q<1)q=0;
  210. Q[flag]=q;
  211. flag++;
  212. }
  213. double max2=Q[0];
  214. j=0;
  215. for(i=1;i<=9;i++)
  216. if(max2<Q[i])
  217. {
  218.    max2=Q[i];
  219.    j=i;
  220. }
  221. int yuzhi;
  222. yuzhi=20*j;
  223. IplImage* dst1;//二值
  224. dst1=cvCreateImage(cvSize(fusi->width,fusi->height),IPL_DEPTH_8U,1);
  225. IplImage* dst11;//二值
  226. dst11=cvCreateImage(cvSize(fusi->width,fusi->height),IPL_DEPTH_8U,1);
  227. cvZero(dst11);
  228. cvZero(dst1);
  229. for(i=0;i<height;i++) for(j=0;j<width;j++)
  230. {
  231. nn=int(CV_MAT_ELEM(*max,double,i,j));
  232. if(nn>yuzhi)((dst1->imageData + dst1->widthStep*i))[j]=255;
  233. }
  234.         CvMemStorage* storage = cvCreateMemStorage(0);
  235.         CvSeq* contour = 0;
  236.         cvThreshold( dst1, dst1, 128, 255, CV_THRESH_BINARY );
  237.         cvDilate( dst1, dst1, NULL, 1 );
  238.        cvFindContours( dst1, storage, &contour, sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );
  239.        double contour_area = 0;
  240.   
  241.         for( ; contour != 0; contour = contour->h_next )
  242.         {
  243.             contour_area=100*fabs(cvContourArea( contour, CV_WHOLE_SEQ )); //
  244.       if(contour_area>height*width)//((contour->v_next!=0)&&(contour_area>height*width))//
  245.             cvDrawContours( dst11, contour, CV_RGB(255,255,255), CV_RGB(255,255,255), 0, CV_FILLED, 8 );
  246.   
  247.         }
  248. cvNamedWindow("膚色6", 0); 
  249. cvShowImage("膚色6", dst11 );
  250. //cvWaitKey(0);
  251. //cvDestroyWindow( "膚色6" );//銷燬窗口
  252. //cvReleaseImage( &dst11 ); //釋放圖像
  253. return *dst11;
  254. }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章