当前位置:   article > 正文

使用灰度共生矩阵实现指纹分割_灰度共生矩阵 掌纹

灰度共生矩阵 掌纹

     灰度共生矩阵,Gray Level Co-occurrence Matrix,简写为GLCM

     由于纹理是由灰度分布在空间位置上反复出现而形成的,因而在图像空间中相隔某距离的两象素之间会存在一定的灰度关系,即图像中灰度的空间相关特性。灰度共生矩阵就是一种通过研究灰度的空间相关特性来描述纹理的常用方法。

     取图像(N×N)中任意一点 (x,y)及偏离它的另一点 (x+a,y+b),设该点对的灰度值为 (g1,g2)。令点(x,y) 在整个画面上移动,则会得到各种 (g1,g2)值,设灰度值的级数为 k,则(g1,g2) 的组合共有 k 的平方种。对于整个画面,统计出每一种 (g1,g2)值出现的次数,然后排列成一个方阵,再用(g1,g2) 出现的总次数将它们归一化为出现的概率P(g1,g2) ,这样的方阵称为灰度共生矩阵。

  关于灰度共生矩阵的详细描述,请参考我的另一篇博文:http://blog.csdn.net/computerme/article/details/39805257

   本文主要是采用灰度共生矩阵来实现指纹的分割,所谓的指纹分割就是把有指纹的区域从图像中提取出来。下图是的我代码的流程图


源代码如下

  1. #include <iostream>
  2. #include "highgui.h"
  3. #include "cv.h"
  4. #define GLCM_DIS 2 //灰度共生矩阵的统计距离
  5. #define GLCM_CLASS 8 //计算灰度共生矩阵的图像灰度值等级化
  6. #define GLCM_ANGLE_HORIZATION 0 //水平
  7. #define GLCM_ANGLE_VERTICAL 1 //垂直
  8. #define GLCM_ANGLE_DIGONAL_45 2 //45度对角
  9. #define GLCM_ANGLE_DIGONAL_135 3 //135度对角
  10. int threshold = 15;
  11. #pragma region calGLCM
  12. int GetMax(CvMat* bWavelet,int& max_value,int& min_value)
  13. {
  14. int i,j;
  15. int width,height;
  16. int max = 0;
  17. int min = 0;
  18. width = bWavelet->width;
  19. height = bWavelet->height;
  20. for (i = 0;i<height;i++ )
  21. {
  22. for(j = 0;j<width;j++)
  23. {
  24. if (CV_MAT_ELEM(*bWavelet,float,i,j)> max)
  25. max = CV_MAT_ELEM(*bWavelet,float,i,j);
  26. if(CV_MAT_ELEM(*bWavelet,float,i,j) < min)
  27. min = CV_MAT_ELEM(*bWavelet,float,i,j);
  28. }
  29. }
  30. max_value = max;
  31. min_value = min;
  32. return 1;
  33. }
  34. int calGLCM(CvMat* bWavelet,int angleDirection,double* featureVector)
  35. {
  36. int i,j;
  37. int width,height;
  38. int min,max;
  39. if(NULL == bWavelet)
  40. return 1;
  41. width = bWavelet->width;
  42. height = bWavelet->height;
  43. int * glcm = new int[GLCM_CLASS * GLCM_CLASS];
  44. int * histImage = new int[width * height];
  45. if(NULL == glcm || NULL == histImage)
  46. return 2;
  47. //灰度等级化---分GLCM_CLASS个等级
  48. //uchar *data =(uchar*) bWavelet->imageData;
  49. //GetMax(bWavelet,max,min);
  50. //printf("max = %d,min = %d ",max,min);
  51. //system("pause");
  52. int relative_value = 0;
  53. for(i = 0;i < height;i++){
  54. for(j = 0;j < width;j++){
  55. histImage[i * width + j] = (int)(CV_MAT_ELEM(*bWavelet,float,i,j) * GLCM_CLASS / 256);
  56. //relative_value = CV_MAT_ELEM(*bWavelet,float,i,j) - min;
  57. //histImage[i * width + j] = (int)(relative_value * GLCM_CLASS / (max-min+1));
  58. //printf("%d ",histImage[i * width + j]);
  59. }
  60. }
  61. //初始化共生矩阵
  62. for (i = 0;i < GLCM_CLASS;i++)
  63. for (j = 0;j < GLCM_CLASS;j++)
  64. glcm[i * GLCM_CLASS + j] = 0;
  65. //计算灰度共生矩阵
  66. int w,k,l;
  67. //水平方向
  68. if(angleDirection == GLCM_ANGLE_HORIZATION)
  69. {
  70. for (i = 0;i < height;i++)
  71. {
  72. for (j = 0;j < width;j++)
  73. {
  74. l = histImage[i * width + j];
  75. if(j + GLCM_DIS >= 0 && j + GLCM_DIS < width)
  76. {
  77. k = histImage[i * width + j + GLCM_DIS];
  78. glcm[l * GLCM_CLASS + k]++;
  79. }
  80. if(j - GLCM_DIS >= 0 && j - GLCM_DIS < width)
  81. {
  82. k = histImage[i * width + j - GLCM_DIS];
  83. glcm[l * GLCM_CLASS + k]++;
  84. }
  85. }
  86. }
  87. }
  88. //垂直方向
  89. else if(angleDirection == GLCM_ANGLE_VERTICAL)
  90. {
  91. for (i = 0;i < height;i++)
  92. {
  93. for (j = 0;j < width;j++)
  94. {
  95. l = histImage[i * width + j];
  96. if(i + GLCM_DIS >= 0 && i + GLCM_DIS < height)
  97. {
  98. k = histImage[(i + GLCM_DIS) * width + j];
  99. glcm[l * GLCM_CLASS + k]++;
  100. }
  101. if(i - GLCM_DIS >= 0 && i - GLCM_DIS < height)
  102. {
  103. k = histImage[(i - GLCM_DIS) * width + j];
  104. glcm[l * GLCM_CLASS + k]++;
  105. }
  106. }
  107. }
  108. }
  109. //135度对角方向
  110. else if(angleDirection == GLCM_ANGLE_DIGONAL_135)
  111. {
  112. for (i = 0;i < height;i++)
  113. {
  114. for (j = 0;j < width;j++)
  115. {
  116. l = histImage[i * width + j];
  117. if(j + GLCM_DIS >= 0 && j + GLCM_DIS < width && i + GLCM_DIS >= 0 && i + GLCM_DIS < height)
  118. {
  119. k = histImage[(i + GLCM_DIS) * width + j + GLCM_DIS];
  120. glcm[l * GLCM_CLASS + k]++;
  121. }
  122. if(j - GLCM_DIS >= 0 && j - GLCM_DIS < width && i - GLCM_DIS >= 0 && i - GLCM_DIS < height)
  123. {
  124. k = histImage[(i - GLCM_DIS) * width + j - GLCM_DIS];
  125. glcm[l * GLCM_CLASS + k]++;
  126. }
  127. }
  128. }
  129. }
  130. //45度对角方向
  131. else if(angleDirection == GLCM_ANGLE_DIGONAL_45)
  132. {
  133. for (i = 0;i < height;i++)
  134. {
  135. for (j = 0;j < width;j++)
  136. {
  137. l = histImage[i * width + j];
  138. if(j + GLCM_DIS >= 0 && j + GLCM_DIS < width && i - GLCM_DIS >= 0 && i - GLCM_DIS < height)
  139. {
  140. k = histImage[(i - GLCM_DIS) * width + j + GLCM_DIS];
  141. glcm[l * GLCM_CLASS + k]++;
  142. }
  143. if(j - GLCM_DIS >= 0 && j - GLCM_DIS < width && i + GLCM_DIS >= 0 && i + GLCM_DIS < height)
  144. {
  145. k = histImage[(i + GLCM_DIS) * width + j - GLCM_DIS];
  146. glcm[l * GLCM_CLASS + k]++;
  147. }
  148. }
  149. }
  150. }
  151. //计算特征值
  152. double entropy = 0,energy = 0,contrast = 0,homogenity = 0;
  153. for (i = 0;i < GLCM_CLASS;i++)
  154. {
  155. for (j = 0;j < GLCM_CLASS;j++)
  156. {
  157. //熵
  158. if(glcm[i * GLCM_CLASS + j] > 0)
  159. entropy -= glcm[i * GLCM_CLASS + j] * log10(double(glcm[i * GLCM_CLASS + j]));
  160. //能量
  161. energy += glcm[i * GLCM_CLASS + j] * glcm[i * GLCM_CLASS + j];
  162. //对比度
  163. contrast += (i - j) * (i - j) * glcm[i * GLCM_CLASS + j];
  164. //一致性
  165. homogenity += 1.0 / (1 + (i - j) * (i - j)) * glcm[i * GLCM_CLASS + j];
  166. }
  167. }
  168. //返回特征值
  169. i = 0;
  170. featureVector[i++] = entropy;
  171. featureVector[i++] = energy;
  172. featureVector[i++] = contrast;
  173. featureVector[i++] = homogenity;
  174. delete[] glcm;
  175. delete[] histImage;
  176. return 0;
  177. }
  178. #pragma endregion calcGLCM
  179. double calc_variance(double a[4])
  180. {
  181. double sum;
  182. double mean;
  183. double variance;
  184. sum = a[0]+a[1]+a[2]+a[3];
  185. mean = sum/4.0;
  186. variance = (a[0]-mean)*(a[0]-mean) + (a[1]-mean)*(a[1]-mean) + (a[2]-mean)*(a[2]-mean)+(a[3]-mean)*(a[3]-mean);
  187. variance = variance/4.0;
  188. return sqrt(variance);
  189. }
  190. void main()
  191. {
  192. clock_t start,finish;
  193. int WIDTH,HEIGHT;
  194. threshold = 8.5;
  195. IplImage* src_img = cvLoadImage("8.bmp",0); //load the picture
  196. WIDTH = src_img->width;
  197. HEIGHT = src_img->height;
  198. int step = src_img->widthStep; //the width of each row
  199. printf("width: %d step: %d depth: %d channels: %d",WIDTH,step,src_img->depth,src_img->nChannels);
  200. IplImage* msk_img = cvCreateImage(cvSize(WIDTH,HEIGHT),8,1);
  201. cvZero(msk_img);
  202. IplImage* dst_img = cvCreateImage(cvSize(WIDTH,HEIGHT),8,1);
  203. cvZero(dst_img);
  204. cvNot(dst_img,dst_img);
  205. start = clock();
  206. //cvSmooth(src_img,src_img,CV_GAUSSIAN);
  207. //cvSmooth(src_img,src_img,CV_MEDIAN,2);
  208. float sum;
  209. cvNamedWindow("src");
  210. cvShowImage("src",src_img);
  211. CvMat* cwindow = cvCreateMat(5,4,CV_32FC1); //store the temperate 3*3 matrix
  212. //CvMat* cwindow = cvCreateMat(5,5,CV_32FC1); //store the temperate 3*3 matrix
  213. double features[10];
  214. double entropy[4] = {0};
  215. double energy[4] = {0};
  216. double contrast[4] = {0};
  217. double homogenity[4] = {0};
  218. double variance;
  219. uchar* gray_ptr = NULL;
  220. uchar* msk_ptr = NULL;
  221. gray_ptr = (uchar*) (src_img->imageData);
  222. msk_ptr = (uchar*) (msk_img->imageData);
  223. int x,y;
  224. for(y = 2; y<src_img->height-2; y = y+2)
  225. {
  226. for ( x = 2; x<src_img->width-2; x = x+2)
  227. {
  228. /*CV_MAT_ELEM(*cwindow,float,0,0) = gray_ptr[(y-2)*step+(x-2)];
  229. CV_MAT_ELEM(*cwindow,float,0,1) = gray_ptr[(y-2)*step+x-1];
  230. CV_MAT_ELEM(*cwindow,float,0,2) = gray_ptr[(y-2)*step+x];
  231. CV_MAT_ELEM(*cwindow,float,0,3) = gray_ptr[(y-2)*step+(x+1)];
  232. CV_MAT_ELEM(*cwindow,float,0,4) = gray_ptr[(y-2)*step+(x+2)];
  233. CV_MAT_ELEM(*cwindow,float,1,0) = gray_ptr[(y-1)*step+(x-2)];
  234. CV_MAT_ELEM(*cwindow,float,1,1) = gray_ptr[(y-1)*step+x-1];
  235. CV_MAT_ELEM(*cwindow,float,1,2) = gray_ptr[(y-1)*step+ x];
  236. CV_MAT_ELEM(*cwindow,float,1,3) = gray_ptr[(y-1)*step+(x+1)];
  237. CV_MAT_ELEM(*cwindow,float,1,4) = gray_ptr[(y-1)*step+x+2];
  238. CV_MAT_ELEM(*cwindow,float,2,0) = gray_ptr[y*step+(x-2)];
  239. CV_MAT_ELEM(*cwindow,float,2,1) = gray_ptr[y*step+(x-1)];
  240. CV_MAT_ELEM(*cwindow,float,2,2) = gray_ptr[y*step+x];
  241. CV_MAT_ELEM(*cwindow,float,2,3) = gray_ptr[y*step+(x+1)];
  242. CV_MAT_ELEM(*cwindow,float,2,4) = gray_ptr[y*step+(x+2)];
  243. CV_MAT_ELEM(*cwindow,float,3,0) = gray_ptr[(y+1)*step+(x-2)];
  244. CV_MAT_ELEM(*cwindow,float,3,1) = gray_ptr[(y+1)*step+x-1];
  245. CV_MAT_ELEM(*cwindow,float,3,2) = gray_ptr[(y+1)*step+x];
  246. CV_MAT_ELEM(*cwindow,float,3,3) = gray_ptr[(y+1)*step+(x+1)];
  247. CV_MAT_ELEM(*cwindow,float,3,4) = gray_ptr[(y+1)*step+(x+2)];
  248. CV_MAT_ELEM(*cwindow,float,4,0) = gray_ptr[(y+2)*step+(x-2)];
  249. CV_MAT_ELEM(*cwindow,float,4,1) = gray_ptr[(y+2)*step+x-1];
  250. CV_MAT_ELEM(*cwindow,float,4,2) = gray_ptr[(y+2)*step+x];
  251. CV_MAT_ELEM(*cwindow,float,4,3) = gray_ptr[(y+2)*step+(x+1)];
  252. CV_MAT_ELEM(*cwindow,float,4,4) = gray_ptr[(y+2)*step+x+2];*/
  253. CV_MAT_ELEM(*cwindow,float,0,0) = gray_ptr[(y-2)*step+(x-2)];
  254. CV_MAT_ELEM(*cwindow,float,0,1) = gray_ptr[(y-2)*step+x-1];
  255. CV_MAT_ELEM(*cwindow,float,0,2) = gray_ptr[(y-2)*step+x];
  256. CV_MAT_ELEM(*cwindow,float,0,3) = gray_ptr[(y-2)*step+(x+1)];
  257. //CV_MAT_ELEM(*cwindow,float,0,4) = gray_ptr[(y-2)*step+(x+2)];
  258. CV_MAT_ELEM(*cwindow,float,1,0) = gray_ptr[(y-1)*step+(x-2)];
  259. CV_MAT_ELEM(*cwindow,float,1,1) = gray_ptr[(y-1)*step+x-1];
  260. CV_MAT_ELEM(*cwindow,float,1,2) = gray_ptr[(y-1)*step+ x];
  261. CV_MAT_ELEM(*cwindow,float,1,3) = gray_ptr[(y-1)*step+(x+1)];
  262. //CV_MAT_ELEM(*cwindow,float,1,4) = gray_ptr[(y-1)*step+x+2];
  263. CV_MAT_ELEM(*cwindow,float,2,0) = gray_ptr[y*step+(x-2)];
  264. CV_MAT_ELEM(*cwindow,float,2,1) = gray_ptr[y*step+(x-1)];
  265. CV_MAT_ELEM(*cwindow,float,2,2) = gray_ptr[y*step+x];
  266. CV_MAT_ELEM(*cwindow,float,2,3) = gray_ptr[y*step+(x+1)];
  267. //CV_MAT_ELEM(*cwindow,float,2,4) = gray_ptr[y*step+(x+2)];
  268. CV_MAT_ELEM(*cwindow,float,3,0) = gray_ptr[(y+1)*step+(x-2)];
  269. CV_MAT_ELEM(*cwindow,float,3,1) = gray_ptr[(y+1)*step+x-1];
  270. CV_MAT_ELEM(*cwindow,float,3,2) = gray_ptr[(y+1)*step+x];
  271. CV_MAT_ELEM(*cwindow,float,3,3) = gray_ptr[(y+1)*step+(x+1)];
  272. //CV_MAT_ELEM(*cwindow,float,3,4) = gray_ptr[(y+1)*step+(x+2)];
  273. CV_MAT_ELEM(*cwindow,float,4,0) = gray_ptr[(y+2)*step+(x-2)];
  274. CV_MAT_ELEM(*cwindow,float,4,1) = gray_ptr[(y+2)*step+x-1];
  275. CV_MAT_ELEM(*cwindow,float,4,2) = gray_ptr[(y+2)*step+x];
  276. CV_MAT_ELEM(*cwindow,float,4,3) = gray_ptr[(y+2)*step+(x+1)];
  277. //CV_MAT_ELEM(*cwindow,float,4,4) = gray_ptr[(y+2)*step+x+2];
  278. calGLCM(cwindow,0,features);
  279. contrast[0] = features[2];
  280. //entropy[0] = features[0];
  281. //energy[0] = features[1];
  282. //homogenity[0] = features[3];
  283. calGLCM(cwindow,1,features);
  284. contrast[1] = features[2];
  285. //entropy[1] = features[0];
  286. //energy[1] = features[1];
  287. //homogenity[1] = features[3];
  288. calGLCM(cwindow,2,features);
  289. contrast[2] = features[2];
  290. //entropy[2] = features[0];
  291. //energy[2] = features[1];
  292. //homogenity[2] = features[3];
  293. calGLCM(cwindow,3,features);
  294. contrast[3] = features[2];
  295. variance = calc_variance(contrast);
  296. //printf("%f\n",contrast[3]);
  297. //entropy[3] = features[0];
  298. //energy[3] = features[1];
  299. //homogenity[3] = features[3];
  300. //if (variance >30)
  301. // dst_ptr[y*step+x] = 0;
  302. //else dst_ptr[y*step+x] = 255;
  303. if (variance >threshold)
  304. {
  305. msk_ptr[(y-2)*step+(x-2)] = 255;
  306. msk_ptr[(y-2)*step+x-1] = 255;
  307. msk_ptr[(y-2)*step+x]=255;
  308. msk_ptr[(y-2)*step+(x+1)]= 255;
  309. //dst_ptr[(y-2)*step+(x+2)]= 255;
  310. msk_ptr[(y-1)*step+(x-2)]= 255;
  311. msk_ptr[(y-1)*step+x-1]= 255;
  312. msk_ptr[(y-1)*step+ x]= 255;
  313. msk_ptr[(y-1)*step+(x+1)]= 255;
  314. //dst_ptr[(y-1)*step+x+2]= 255;
  315. msk_ptr[y*step+(x-2)]= 255;
  316. msk_ptr[y*step+(x-1)]= 255;
  317. msk_ptr[y*step+x]= 255;
  318. msk_ptr[y*step+(x+1)]= 255;
  319. //dst_ptr[y*step+(x+2)]= 255;
  320. msk_ptr[(y+1)*step+(x-2)]= 255;
  321. msk_ptr[(y+1)*step+x-1]= 255;
  322. msk_ptr[(y+1)*step+x]= 0;
  323. msk_ptr[(y+1)*step+(x+1)]= 255;
  324. //dst_ptr[(y+1)*step+(x+2)]= 255;
  325. msk_ptr[(y+2)*step+(x-2)]= 255;
  326. msk_ptr[(y+2)*step+x-1]= 255;
  327. msk_ptr[(y+2)*step+x]= 255;
  328. msk_ptr[(y+2)*step+(x+1)]= 255;
  329. //dst_ptr[(y+2)*step+x+2]= 255;
  330. //dst_ptr[(y+2)*step+x+2]= 0;
  331. }
  332. //dst_ptr[y*step+x] = 0;
  333. else
  334. {
  335. msk_ptr[(y-2)*step+(x-2)] = 0;
  336. msk_ptr[(y-2)*step+x-1] = 0;
  337. msk_ptr[(y-2)*step+x]=0;
  338. msk_ptr[(y-2)*step+(x+1)]= 0;
  339. //dst_ptr[(y-2)*step+(x+2)]= 0;
  340. msk_ptr[(y-1)*step+(x-2)]= 0;
  341. msk_ptr[(y-1)*step+x-1]= 0;
  342. msk_ptr[(y-1)*step+ x]= 0;
  343. msk_ptr[(y-1)*step+(x+1)]= 0;
  344. //dst_ptr[(y-1)*step+x+2]= 0;
  345. msk_ptr[y*step+(x-2)]= 0;
  346. msk_ptr[y*step+(x-1)]= 0;
  347. msk_ptr[y*step+x]= 0;
  348. msk_ptr[y*step+(x+1)]= 0;
  349. //dst_ptr[y*step+(x+2)]= 0;
  350. msk_ptr[(y+1)*step+(x-2)]= 0;
  351. msk_ptr[(y+1)*step+x-1]= 0;
  352. msk_ptr[(y+1)*step+x]= 0;
  353. msk_ptr[(y+1)*step+(x+1)]= 0;
  354. //dst_ptr[(y+1)*step+(x+2)]= 0;
  355. msk_ptr[(y+2)*step+(x-2)]= 0;
  356. msk_ptr[(y+2)*step+x-1]= 0;
  357. msk_ptr[(y+2)*step+x]= 0;
  358. msk_ptr[(y+2)*step+(x+1)]= 0;
  359. }
  360. }
  361. }
  362. cvNamedWindow("mask_before");
  363. cvShowImage("mask_before",msk_img);
  364. cvSmooth(msk_img,msk_img,CV_MEDIAN,19);
  365. cvMorphologyEx( msk_img, msk_img, NULL, NULL, CV_MOP_OPEN, 3 );
  366. // 开运算先腐蚀在膨胀,腐蚀可以清除噪点,膨胀可以修复裂缝
  367. cvMorphologyEx( msk_img, msk_img, NULL, NULL, CV_MOP_CLOSE, 3 );
  368. // 闭运算先膨胀后腐蚀,之所以在开运算之后,因为噪点膨胀后再腐蚀,是不可能去除的
  369. cvNamedWindow("mask");
  370. cvShowImage("mask",msk_img);
  371. cvCopy(src_img,dst_img,msk_img);
  372. cvNamedWindow("dst",CV_WINDOW_AUTOSIZE);
  373. cvShowImage("dst",dst_img);
  374. finish = clock();
  375. printf(" 计算时间%.2fms \n", (double) (finish - start));
  376. cvWaitKey(0);
  377. }

最后的运行如果如下:




测试图片及源代码下载:http://download.csdn.net/detail/computerme/8056957

本文系原创,转载请注明转载自:http://blog.csdn.net/computerme/article/details/40269357

Reference:

灰度共生矩阵在指纹图像分割中的应用.  李慧娜,郭超峰,平源,2012

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/346727
推荐阅读
相关标签
  

闽ICP备14008679号