灰度共生矩阵
灰度直方图是对整张图像所有像素点的灰度值进行统计的结果。
灰度共生矩阵是对图像上保持某种距离的两像素点的灰度状况进行统计的结果。
取图像 (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)这样的方阵称为灰度共生矩阵。距离差分值(a,b) 取不同的数值组合,可以得到不同情况下的联合概率矩阵。(a,b) 取值要根据纹理周期分布的特性来选择,对于较细的纹理,选取(1,0)、(1,1)、(2,0)等小的差分值。
当 a=1,b=0时,像素对是水平的,即0度扫描;
当 a=0,b=1 时,像素对是垂直的,即90度扫描;
当 a=1,b=1时,像素对是右对角线的,即45度扫描;
当 a=-1,b=1时,像素对是左对角线,即135度扫描。
1 #include "cbir.h" 2 3 #define GLCM_DISTEN 3 //偏离距离 4 #define GLCM_CLASS 8 //灰度降级 5 6 /* 7 功能: 8 求图像4个方向的灰度共生矩阵,并计算4个特征值,保存于featherVector[] 9 参数: 10 Grey_Image:灰度图像 11 angleDirection:方向 12 featherVector:保存特征值 13 */ 14 15 int calGLCM(Mat Grey_Image, int angleDirection, double* featureVector) 16 { 17 int i, j; 18 int width, height; 19 20 width = Grey_Image.cols; 21 height = Grey_Image.rows; 22 23 int * glcm = new int[GLCM_CLASS * GLCM_CLASS];//灰度共生矩 8 * 8 一维数组 24 int * histImage = new int[width * height];//降级后的图像 300 * 200 一维数组 25 26 if (NULL == glcm || NULL == histImage) 27 return 2; 28 29 //降低图像灰度等级,把图像256个灰度级按顺序分为8个区间 30 uchar *data = (uchar*)Grey_Image.data; 31 for (i = 0; i < height; i++) { 32 for (j = 0; j < width; j++) { 33 histImage[i * width + j] = (int)(data[width * i + j] * GLCM_CLASS / 256);// 除32取整 = 降级后的灰度 34 } 35 } 36 37 //初始化共生矩阵 38 for (i = 0; i < GLCM_CLASS; i++) 39 for (j = 0; j < GLCM_CLASS; j++) 40 glcm[i * GLCM_CLASS + j] = 0;// 8 x 8 置零 41 42 //计算灰度共生矩阵 43 int k, l; 44 45 // 0°水平 46 if (angleDirection == 0) 47 { 48 // 遍历降级后的图像 300 * 200 49 for (i = 0; i < height; i++) 50 { 51 for (j = 0; j < width; j++) 52 { 53 l = histImage[i * width + j];//取图像点(i,j)像素值 54 55 if (j + GLCM_DISTEN < width) 56 { 57 k = histImage[i * width + j + GLCM_DISTEN];//取图像点(i,j+d)像素值 58 glcm[l * GLCM_CLASS + k]++;// 将灰度共生矩中(value(i,j),value(i,j+d))值加1 59 } 60 } 61 } 62 } 63 64 // 90°垂直 65 else if (angleDirection == 90) 66 { 67 for (i = 0; i < height; i++) 68 { 69 for (j = 0; j < width; j++) 70 { 71 l = histImage[i * width + j];//取图像点(i,j)像素值 72 73 if (i + GLCM_DISTEN < height) 74 { 75 k = histImage[(i + GLCM_DISTEN) * width + j];//取图像点(i+d,j)像素值 76 glcm[l * GLCM_CLASS + k]++;// 将灰度共生矩中(value(i,j),value(i+d,j))值加1 77 } 78 } 79 } 80 } 81 82 // 45° 83 else if (angleDirection == 45) 84 { 85 for (i = 0; i < height; i++) 86 { 87 for (j = 0; j < width; j++) 88 { 89 l = histImage[i * width + j];//取图像点(i,j)像素值 90 91 if (j + GLCM_DISTEN < width && i + GLCM_DISTEN < height) 92 { 93 k = histImage[(i + GLCM_DISTEN) * width + j + GLCM_DISTEN];//取图像点(i+d,j+d)像素值 94 glcm[l * GLCM_CLASS + k]++;// 将灰度共生矩中(value(i,j),value(i+d,j+d))值加1 95 } 96 } 97 } 98 } 99 100 // 135° 101 else if (angleDirection == 135) 102 { 103 for (i = 0; i < height; i++) 104 { 105 for (j = 0; j < width; j++) 106 { 107 l = histImage[i * width + j];//取图像点(i,j)像素值 108 109 if (j - GLCM_DISTEN >= 0 && i - GLCM_DISTEN >= 0) 110 { 111 k = histImage[(i - GLCM_DISTEN) * width + j - GLCM_DISTEN];//取图像点(i+d,j-d)像素值 112 glcm[l * GLCM_CLASS + k]++;// 将灰度共生矩中(value(i,j),value(i+d,j-d))值加1 113 } 114 } 115 } 116 } 117 118 //计算特征值 119 double entropy = 0, energy = 0, contrast = 0, homogenity = 0; 120 121 for (i = 0; i < GLCM_CLASS; i++) 122 { 123 for (j = 0; j < GLCM_CLASS; j++) 124 { 125 //熵 126 if (glcm[i * GLCM_CLASS + j] > 0) 127 entropy -= glcm[i * GLCM_CLASS + j] * log10(double(glcm[i * GLCM_CLASS + j])); 128 129 //能量 130 energy += glcm[i * GLCM_CLASS + j] * glcm[i * GLCM_CLASS + j]; 131 132 //对比度 133 contrast += (i - j) * (i - j) * glcm[i * GLCM_CLASS + j]; 134 135 //一致性 136 homogenity += 1.0 / (1 + (i - j) * (i - j)) * glcm[i * GLCM_CLASS + j]; 137 } 138 } 139 140 //返回特征值 141 i = 0; 142 featureVector[i++] = entropy; 143 featureVector[i++] = energy; 144 featureVector[i++] = contrast; 145 featureVector[i++] = homogenity; 146 147 delete[] glcm; 148 delete[] histImage; 149 150 return 0; 151 } 152 153 154 /* 155 功能: 156 纹理特征:灰度共生矩 157 参数: 158 src:传入图像 159 */ 160 161 double AveDev[8];// 保存 8 个特征值 162 163 double getEigenValueByHDGSJ(Mat src) 164 { 165 Mat dst = rgb2grey(src);//RNG -> GRAY 166 imshow("1", dst); 167 waitKey(1000); 168 169 // 垂直 0° 170 double GLCM_0[4] = { 0 }; 171 calGLCM(dst, 0, GLCM_0); 172 cout << setprecision(20) << " 0°熵:" << GLCM_0[0] << endl; 173 cout << setprecision(20) << " 0°能量:" << GLCM_0[1] << endl; 174 cout << setprecision(20) << " 0°对比度:" << GLCM_0[2] << endl; 175 cout << setprecision(20) << " 0°一致性:" << GLCM_0[3] << endl; 176 177 double Average0 = 0.25 * (GLCM_0[0] + GLCM_0[1] + GLCM_0[2] + GLCM_0[3]); 178 cout << setprecision(20) << " 0°均值:" << Average0 << endl; 179 180 double temp0 = 1; 181 for (int i = 0; i < 4; i++) 182 { 183 temp0 += GLCM_0[i] * GLCM_0[i]; 184 } 185 double StaDev0 = sqrt(0.25 * temp0); 186 cout << setprecision(20) << " 0°标准差:" << StaDev0 << endl; 187 188 cout << endl; 189 190 // 水平 90° 191 double GLCM_90[4] = { 0 }; 192 calGLCM(dst, 90, GLCM_90); 193 cout << setprecision(20) << " 90°熵:" << GLCM_90[0] << endl; 194 cout << setprecision(20) << " 90°能量:" << GLCM_90[1] << endl; 195 cout << setprecision(20) << " 90°对比度:" << GLCM_90[2] << endl; 196 cout << setprecision(20) << " 90°一致性:" << GLCM_90[3] << endl; 197 198 double Average90 = 0.25 * (GLCM_90[0] + GLCM_90[1] + GLCM_90[2] + GLCM_90[3]); 199 cout << setprecision(20) << " 90°均值:" << Average90 << endl; 200 201 double temp90 = 1; 202 for (int i = 0; i < 4; i++) 203 { 204 temp90 += GLCM_90[i] * GLCM_90[i]; 205 } 206 double StaDev90 = sqrt(0.25 * temp90); 207 cout << setprecision(20) << " 90°标准差:" << StaDev90 << endl; 208 209 cout << endl; 210 211 // 45° 212 double GLCM_45[4] = { 0 }; 213 calGLCM(dst, 45, GLCM_45); 214 cout << setprecision(20) << " 45°熵:" << GLCM_45[0] << endl; 215 cout << setprecision(20) << " 45°能量:" << GLCM_45[1] << endl; 216 cout << setprecision(20) << " 45°对比度:" << GLCM_45[2] << endl; 217 cout << setprecision(20) << " 45°一致性:" << GLCM_45[3] << endl; 218 219 double Average45 = 0.25 * (GLCM_45[0] + GLCM_45[1] + GLCM_45[2] + GLCM_45[3]); 220 cout << setprecision(20) << " 45°均值:" << Average45 << endl; 221 222 double temp45 = 1; 223 for (int i = 0; i < 4; i++) 224 { 225 temp45 += GLCM_45[i] * GLCM_45[i]; 226 } 227 double StaDev45 = sqrt(0.25 * temp45); 228 cout << setprecision(20) << " 45°标准差:" << StaDev45 << endl; 229 230 cout << endl; 231 232 // 135° 233 double GLCM_135[4] = { 0 }; 234 calGLCM(dst, 135, GLCM_135); 235 cout << setprecision(20) << " 135°熵:" << GLCM_135[0] << endl; 236 cout << setprecision(20) << " 135°能量:" << GLCM_135[1] << endl; 237 cout << setprecision(20) << " 135°对比度:" << GLCM_135[2] << endl; 238 cout << setprecision(20) << " 135°一致性:" << GLCM_135[3] << endl; 239 240 double Average135 = 0.25 * (GLCM_135[0] + GLCM_135[1] + GLCM_135[2] + GLCM_135[3]); 241 cout << setprecision(20) << " 135°均值:" << Average135 << endl; 242 243 double temp135 = 1; 244 for (int i = 0; i < 4; i++) 245 { 246 temp135 += GLCM_135[i] * GLCM_135[i]; 247 } 248 double StaDev135 = sqrt(0.25 * temp135); 249 cout << setprecision(20) << " 135°标准差:" << StaDev135 << endl; 250 251 cout << endl; 252 253 AveDev[0] = Average0; 254 AveDev[1] = Average90; 255 AveDev[2] = Average45; 256 AveDev[3] = Average135; 257 AveDev[4] = StaDev0; 258 AveDev[5] = StaDev90; 259 AveDev[6] = StaDev45; 260 AveDev[7] = StaDev135; 261 262 return 0; 263 264 }