├── lib └── libglcm.so ├── image ├── miska.jpg ├── Satellite.jpg └── Test_Result.png ├── CMakeLists.txt ├── README - 中文.md ├── README.md └── src ├── main.cpp ├── glcm.h └── glcm.cpp /lib/libglcm.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upcAutoLang/GLCM-OpenCV/HEAD/lib/libglcm.so -------------------------------------------------------------------------------- /image/miska.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upcAutoLang/GLCM-OpenCV/HEAD/image/miska.jpg -------------------------------------------------------------------------------- /image/Satellite.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upcAutoLang/GLCM-OpenCV/HEAD/image/Satellite.jpg -------------------------------------------------------------------------------- /image/Test_Result.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upcAutoLang/GLCM-OpenCV/HEAD/image/Test_Result.png -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED(VERSION 2.8) 2 | PROJECT(GLCM) 3 | 4 | SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) 5 | SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib) 6 | 7 | FIND_PACKAGE(OpenCV REQUIRED) 8 | LINK_DIRECTORIES(${PROJECT_BINARY_DIR}/lib) 9 | 10 | INCLUDE_DIRECTORIES(./) 11 | INCLUDE_DIRECTORIES(./src) 12 | 13 | SET(LIB_GLCM_SOURCE 14 | ./src/glcm.h 15 | ./src/glcm.cpp) 16 | ADD_LIBRARY(glcm SHARED ${LIB_GLCM_SOURCE}) 17 | TARGET_LINK_LIBRARIES(glcm 18 | ${OpenCV_LIBS}) 19 | 20 | SET(LIB_GLCM glcm) 21 | ADD_EXECUTABLE(GLCM_test ./src/main.cpp) 22 | TARGET_LINK_LIBRARIES(GLCM_test 23 | ${LIB_GLCM}) 24 | -------------------------------------------------------------------------------- /README - 中文.md: -------------------------------------------------------------------------------- 1 | 该仓库中内容是笔者研究灰度共生矩阵(GLCM)后,根据其原理调用了OpenCV库写出的C++代码。 2 | 3 | # 一、原理解释 4 | 对GLCM的研究,笔者写了博客。地址如下: 5 | http://blog.csdn.net/ajianyingxiaoqinghan/article/details/71552744 6 | 7 | # 二、文件说明 8 | 9 | - src:源代码所在路径 10 | - glcm.h:GLCM算法头文件源码 11 | - glcm.cpp:GLCM算法实现源码 12 | - main.cpp:测试GLCM源码 13 | - lib:动态链接库生成路径 14 | - image: 程序测试所用图像存储路径 15 | - CMakeLists.txt:该工程CMake文件 16 | 17 | # 三、工程生成教程 18 | ## 1. 笔者的工作环境: 19 | 20 | - 操作系统:Ubuntu 14.04 LTS 21 | - OpenCV版本: 2.4.9 22 | - 编译条件: 23 | - 已编译且安装OpenCV 24 | - 已安装CMake 25 | 26 | 关于Ubuntu 14.04下OpenCV的安装,笔者写的教程如下: 27 | CSDN:http://blog.csdn.net/ajianyingxiaoqinghan/article/details/62424132 28 | GitHub:https://github.com/upcAutoLang/Blog/issues/1 29 | 30 | ## 2. CMake该项目 31 | 进入终端,进入GLCM_OpenCV路径,输入以下指令: 32 | ```bash 33 | cmake ./ 34 | make 35 | ``` 36 | 即可编译该工程。 37 | 生成文件路径:/GLCM_OpenCV/bin 38 | 生成库文件路径:/GLCM_OpenCV/lib 39 | 40 | # 四、测试效果 41 | 用/GLCM_OpenCV/image/miska.jpg做测试,结果如下: 42 | ![](./image/Test_Result.png) 43 | 44 | Debug版本下,测试程序中计算出的该算法效率输出如下: 45 | ```cpp 46 | Time of Magnitude Gray Image: 1.38906ms 47 | Time of Calculate Texture Features of the whole Image: 4126.57ms 48 | ``` 49 | Release版本下,测试程序中计算出的该算法效率输出如下: 50 | ```cpp 51 | Time of Magnitude Gray Image: 0.452412ms 52 | Time of Calculate Texture Features of the whole Image: 1291.15ms 53 | 54 | ``` 55 | 56 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This repository is the C++ Source Code of GLCM, which is based on OpenCV libraries after I learn about the theory of GLCM (Gray-level Co-occurrence Matrix). 2 | 3 | # GLCM's Theory 4 | I wrote a blog about GLCM's theory. And here is the web address: 5 | http://blog.csdn.net/ajianyingxiaoqinghan/article/details/71552744 6 | 7 | # Files Introduction 8 | 9 | - src - Source Codes' Path 10 | - glcm.h - GLCM algorithm's head file source code 11 | - glcm.cpp - GLCM algorithm's C++ source code 12 | - main.cpp - GLCM algorithm's test program's source code 13 | - lib - the Generating Path of Dynamic-Link Library 14 | - image - the Path of Images for Algorithm Test Program 15 | - CMakeLists.txt - CMake File of this Project 16 | 17 | # Tutorial for Generating this Project 18 | ## 1. My Working Environment 19 | 20 | - Operating System: Ubuntu 14.04 LTS 21 | - OpenCV Version: 2.4.9 22 | - Conditions before your cmake command: 23 | - have already done OpenCV's make & make install 24 | - have already done CMake's make & make install 25 | 26 | Besides, I also wrote the tutorial blog of how to install OpenCV 2.4.9 in Ubuntu 14.04. Here are the websites: 27 | CSDN:http://blog.csdn.net/ajianyingxiaoqinghan/article/details/62424132 28 | GitHub:https://github.com/upcAutoLang/Blog/issues/1 29 | 30 | ## 2. CMake this Project 31 | Open a terminal and enter in the path of folder named *GLCM_OpenCV*, then input commands like below: 32 | ```bash 33 | cmake ./ 34 | make 35 | ``` 36 | Then you will build this project. 37 | 38 | The path of binary files - /GLCM_OpenCV/build/bin 39 | The path of library files - /GLCM_OpenCV/build/lib 40 | 41 | # Test Results 42 | I run the algorithm test program by using image whose path is */GLCM_OpenCV/image/miska.jpg*, and the result is like below: 43 | ![](./image/Test_Result.png) 44 | 45 | the result of **Debug Version**: 46 | ```cpp 47 | Time of Magnitude Gray Image: 1.38906ms 48 | Time of Calculate Texture Features of the whole Image: 4126.57ms 49 | ``` 50 | the result of **Release Version**: 51 | ```cpp 52 | Time of Magnitude Gray Image: 0.452412ms 53 | Time of Calculate Texture Features of the whole Image: 1291.15ms 54 | ``` 55 | 56 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | /*================================================================= 2 | * Calculate GLCM(Gray-level Co-occurrence Matrix) By OpenCV. 3 | * 4 | * Copyright (C) 2017 Chandler Geng. All rights reserved. 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public License as published 8 | * by the Free Software Foundation; either version 2 of the License, or (at 9 | * your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, but 12 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 13 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 14 | * more details. 15 | * 16 | * You should have received a copy of the GNU General Public License along 17 | * with this program; if not, write to the Free Software Foundation, Inc., 59 18 | * Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | =================================================================== 20 | */ 21 | 22 | /*================================================= 23 | * Version: 24 | * v1.0: 完成了单个GLCM的计算; 25 | * v1.1: 完成了矩阵归一化、图像纹理特征计算的功能; 26 | * v1.2: 完成了矩阵边界部分的计算; 27 | * v1.3: 完成了获取单一通道、灰度图量化为4/8/16等级的功能; 28 | * v1.4: 完成了整幅图像纹理特征的计算; 29 | * v1.5: 完成了对纹理特征图像的调整功能,并显示; 30 | * v1.7: 添加了计算整幅图像的特征值函数; 31 | =================================================== 32 | */ 33 | 34 | #include "glcm.h" 35 | 36 | // 示例程序 37 | // Example Program 38 | int main() 39 | { 40 | char key; 41 | Mat img; 42 | GLCM glcm; 43 | TextureEValues EValues; 44 | 45 | // 程序运行时间统计变量 46 | // the Time Statistical Variable of Program Running Time 47 | double time; 48 | double start; 49 | 50 | // 纹理特征值矩阵 51 | // the Matrixs of Texture Features 52 | Mat imgEnergy, imgContrast, imgHomogenity, imgEntropy; 53 | 54 | // 读取图像 55 | // Read a Image 56 | img = imread("/home/grq/miska.jpg"); 57 | 58 | Mat dstChannel; 59 | glcm.getOneChannel(img, dstChannel, CHANNEL_B); 60 | 61 | // 灰度量化,并统计运算时间 62 | // Magnitude Gray Image, and calculate program running time 63 | start = static_cast(getTickCount()); 64 | glcm.GrayMagnitude(dstChannel, dstChannel, GRAY_8); 65 | time = ((double)getTickCount() - start) / getTickFrequency() * 1000; 66 | cout << "Time of Magnitude Gray Image: " << time << "ms" <(getTickCount()); 71 | glcm.CalcuTextureImages(dstChannel, imgEnergy, imgContrast, imgHomogenity, imgEntropy, 5, GRAY_8, true); 72 | time = ((double)getTickCount() - start) / getTickFrequency() * 1000; 73 | cout << "Time of Generate the whole Image's Calculate Texture Features Image: " << time << "ms" << endl<(getTickCount()); 76 | glcm.CalcuTextureEValue(dstChannel, EValues, 5, GRAY_8); 77 | time = ((double)getTickCount() - start) / getTickFrequency() * 1000; 78 | cout << "Time of Calculate Texture Features of the whole Image: " << time << "ms" << endl< 27 | 28 | using namespace cv; 29 | using namespace std; 30 | 31 | // 灰度等级 32 | // Gray Level (Choose in 4/8/16) 33 | enum GrayLevel 34 | { 35 | GRAY_4, 36 | GRAY_8, 37 | GRAY_16 38 | }; 39 | 40 | // 灰度统计方向 41 | // Gray Value Statistical Direction 42 | // (Choose in 0°, 45°, 90°, 135°) 43 | enum GrayDirection 44 | { 45 | DIR_0, 46 | DIR_45, 47 | DIR_90, 48 | DIR_135 49 | }; 50 | 51 | // 彩色图中的指定通道 52 | // Point out R, G, B Channel of a Image 53 | enum RGBChannel 54 | { 55 | CHANNEL_R, 56 | CHANNEL_G, 57 | CHANNEL_B 58 | }; 59 | 60 | // 纹理特征值结构体 61 | // struct including Texture Eigenvalues 62 | struct TextureEValues 63 | { 64 | // 能量 65 | float energy; 66 | // 对比度 67 | float contrast; 68 | // 相关度 69 | float homogenity; 70 | // 熵 71 | float entropy; 72 | }; 73 | 74 | class GLCM 75 | { 76 | public: 77 | // 从彩色通道中提取一个通道 78 | // Extract a channel from RGB Image 79 | void getOneChannel(Mat src, Mat& dstChannel, RGBChannel channel = CHANNEL_R); 80 | 81 | // 将灰度图中的所有像素值量级化,可以被量化为4/8/16个等级 82 | // Magnitude all pixels of Gray Image, and Magnitude Level can be chosen in 4/8/16; 83 | void GrayMagnitude(Mat src, Mat& dst, GrayLevel level = GRAY_8); 84 | 85 | // 计算一个矩阵窗口中,按照某个方向统计的灰度共生矩阵 86 | // Calculate the GLCM of one Mat Window according to one Statistical Direction. 87 | void CalcuOneGLCM(Mat src, Mat &dst, int src_i, int src_j, int size, GrayLevel level = GRAY_8, GrayDirection direct = DIR_0); 88 | 89 | // 矩阵的归一化,将矩阵所有元素与矩阵中所有元素之和作除运算,得到概率矩阵 90 | // Normalize the Martix, make all pixels of Mat divided by the sum of all pixels of Mat, then get Probability Matrix. 91 | void NormalizeMat(Mat src, Mat& dst); 92 | 93 | // 计算单个窗口矩阵的图像纹理特征值,包括能量、对比度、相关度、熵 94 | // Calculate Texture Eigenvalues of One Window Mat, which is including Energy, Contrast, Homogenity, Entropy. 95 | void CalcuOneTextureEValue(Mat src, TextureEValues& EValue, bool ToCheckMat = false); 96 | 97 | // 计算全图的图像纹理特征值,包括能量、对比度、相关度、熵 98 | // Calculate Texture Eigenvalues of One Window Mat, which is including Energy, Contrast, Homogenity, Entropy. 99 | void CalcuTextureEValue(Mat src, TextureEValues& EValue, 100 | int size = 5, GrayLevel level = GRAY_8); 101 | 102 | // 计算整幅图像的纹理特征 103 | void CalcuTextureImages(Mat src, Mat& imgEnergy, Mat& imgContrast, Mat& imgHomogenity, Mat& imgEntropy, 104 | int size = 5, GrayLevel level = GRAY_8, bool ToAdjustImg = false); 105 | }; 106 | 107 | #endif // GLCM_H 108 | -------------------------------------------------------------------------------- /src/glcm.cpp: -------------------------------------------------------------------------------- 1 | /*================================================================= 2 | * Calculate GLCM(Gray-level Co-occurrence Matrix) By OpenCV. 3 | * 4 | * Copyright (C) 2017 Chandler Geng. All rights reserved. 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public License as published 8 | * by the Free Software Foundation; either version 2 of the License, or (at 9 | * your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, but 12 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 13 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 14 | * more details. 15 | * 16 | * You should have received a copy of the GNU General Public License along 17 | * with this program; if not, write to the Free Software Foundation, Inc., 59 18 | * Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | =================================================================== 20 | */ 21 | 22 | #include "glcm.h" 23 | 24 | /*=================================================================== 25 | * 函数名:getOneChannel 26 | * 说明:从彩色通道中提取一个通道; 27 | * 参数: 28 | * Mat src: 源图像 29 | * Mat& dstChannel: 源图像中的单一通道,并输出为灰度图 30 | * RGBChannel channel: RGB通道中的指定通道 31 | * 返回值:void 32 | *------------------------------------------------------------------ 33 | * Function: getOneChannel 34 | * 35 | * Summary: 36 | * Extract a channel from RGB Image; 37 | * 38 | * Arguments: 39 | * Mat src - source image 40 | * Mat& dstChannel - a channel from RGB source image 41 | * RGBChannel channel - Point out which channel will be extracted 42 | * 43 | * Returns: 44 | * void 45 | ===================================================================== 46 | */ 47 | void GLCM::getOneChannel(Mat src, Mat& dstChannel, RGBChannel channel) 48 | { 49 | // 若输入图像已经是灰度图,则直接输出 50 | if(src.channels() == 1) 51 | dstChannel = src; 52 | 53 | vector bgr; 54 | // 分离图像 55 | split(src, bgr); 56 | 57 | switch(channel) 58 | { 59 | case CHANNEL_B: dstChannel = bgr[0]; break; 60 | case CHANNEL_G: dstChannel = bgr[1]; break; 61 | case CHANNEL_R: dstChannel = bgr[2]; break; 62 | default: 63 | cout<<"ERROR in getOneChannel(): No Such Channel."<(j); 106 | uchar* output = dst.ptr(j); 107 | 108 | for(int i = 0; i < tmp.cols; i++) 109 | { 110 | switch(level) 111 | { 112 | case GRAY_4: 113 | output[i] = cv::saturate_cast(current[i] / 64); 114 | break; 115 | case GRAY_8: 116 | output[i] = cv::saturate_cast(current[i] / 32); 117 | break; 118 | case GRAY_16: 119 | output[i] = cv::saturate_cast(current[i] / 16); 120 | break; 121 | default: 122 | cout<<"ERROR in GrayMagnitude(): No Such GrayLevel."< src.rows 187 | || src_j + (size/2) + 1 > src.cols 188 | || src_i < (size/2) 189 | || src_j < (size/2)) 190 | { 191 | size = 3; 192 | if(src_i <= size/2) 193 | { 194 | if(src_j <= size/2) 195 | srcCut = Mat(src, Range(0, 3), Range(0, 3)); 196 | else if(src_j + (size/2) + 1 > src.cols) 197 | srcCut = Mat(src, Range(0, 3), Range(src.cols - 3, src.cols)); 198 | else 199 | srcCut = Mat(src, Range(0, 3), Range(src_j - size/2, src_j + size/2 + 1)); 200 | } 201 | else if(src_i >= src.rows - size/2) 202 | { 203 | if(src_j <= size/2) 204 | srcCut = Mat(src, Range(src.rows - 3, src.rows), Range(0, 3)); 205 | else if(src_j + (size/2) + 1 > src.cols) 206 | srcCut = Mat(src, Range(src.rows - 3, src.rows), Range(src.cols - 3, src.cols)); 207 | else 208 | srcCut = Mat(src, Range(src.rows - 3, src.rows), Range(src_j - size/2, src_j + size/2 + 1)); 209 | } 210 | else if(src_j <= size/2) 211 | { 212 | if(src_i <= size/2) 213 | srcCut = Mat(src, Range(0, 3), Range(0, 3)); 214 | else if(src_i + (size/2) + 1 > src.rows) 215 | srcCut = Mat(src, Range(src.rows - 3, src.rows), Range(0, 3)); 216 | else 217 | srcCut = Mat(src, Range(src_i - size/2, src_i + size/2 + 1), Range(0, 3)); 218 | } 219 | else if(src_j >= src.cols - size/2) 220 | { 221 | if(src_i <= size/2) 222 | srcCut = Mat(src, Range(0, 3), Range(src.cols - 3, src.cols)); 223 | else if(src_i + (size/2) + 1 > src.rows) 224 | srcCut = Mat(src, Range(src.rows - 3, src.rows), Range(src.cols - 3, src.cols)); 225 | else 226 | srcCut = Mat(src, Range(src_i - size/2, src_i + size/2 + 1), Range(src.cols - 3, src.cols)); 227 | } 228 | else 229 | srcCut = Mat(src, Range(src_i - size/2, src_i + size/2 + 1), Range(src_j - size/2, src_j + size/2 + 1)); 230 | } 231 | else 232 | srcCut = Mat(src, Range(src_i - size/2, src_i + size/2 + 1), Range(src_j - size/2, src_j + size/2 + 1)); 233 | 234 | // 根据灰度等级初始化灰度共生矩阵 235 | // Initialize GLCM according Gray Level 236 | switch(level) 237 | { 238 | case GRAY_4: 239 | { 240 | glcm = Mat_(4, 4); 241 | for(int i = 0; i < 4; i++) 242 | for(int j = 0; j < 4; j++) 243 | glcm.at(j, i) = 0; 244 | break; 245 | } 246 | case GRAY_8: 247 | { 248 | glcm = Mat_(8, 8); 249 | for(int i = 0; i < 8; i++) 250 | for(int j = 0; j < 8; j++) 251 | glcm.at(j, i) = 0; 252 | break; 253 | } 254 | case GRAY_16: 255 | { 256 | glcm = Mat_(16, 16); 257 | for(int i = 0; i < 16; i++) 258 | for(int j = 0; j < 16; j++) 259 | glcm.at(j, i) = 0; 260 | break; 261 | } 262 | default: 263 | cout<<"ERROR in CalcuOneGLCM(): No Such Gray Level."<(srcCut.at(j, i), srcCut.at(j+1, i))++; 275 | break; 276 | case DIR_45: 277 | for(int i = 0; i < srcCut.rows - 1; i++) 278 | for(int j = 0; j < srcCut.cols - 1; j++) 279 | glcm.at(srcCut.at(j, i), srcCut.at(j+1, i+1))++; 280 | break; 281 | case DIR_90: 282 | for(int i = 0; i < srcCut.rows - 1; i++) 283 | for(int j = 0; j < srcCut.cols; j++) 284 | glcm.at(srcCut.at(j, i), srcCut.at(j, i+1))++; 285 | break; 286 | case DIR_135: 287 | for(int i = 1; i < srcCut.rows; i++) 288 | for(int j = 0; j < srcCut.cols - 1; j++) 289 | glcm.at(srcCut.at(j, i), srcCut.at(j+1, i-1))++; 290 | break; 291 | default: 292 | cout<<"ERROR in CalcuOneGLCM(): No such Direct."<(j, i); 334 | if(sum == 0) sum = 1; 335 | 336 | for(int i = 0; i < tmp.rows; i++) 337 | for(int j = 0; j < tmp.cols; j++) 338 | tmp.at(j, i) /= sum; 339 | 340 | tmp.copyTo(dst); 341 | } 342 | 343 | /*=================================================================== 344 | * 函数名:CalcuOneTextureEValue 345 | * 说明:计算单个窗口矩阵的图像纹理特征值,包括能量、对比度、相关度、熵 346 | * 参数: 347 | * Mat src: 源矩阵,窗口矩阵 348 | * TextureEValues& EValue: 纹理特征值变量 349 | * bool ToCheckMat: 检查输入矩阵是否为概率矩阵 350 | * 返回值:void 351 | *------------------------------------------------------------------ 352 | * Function: CalcuOneTextureEValue 353 | * 354 | * Summary: 355 | * Calculate Texture Eigenvalues of the Window Mat, which is including 356 | * Energy, Contrast, Homogenity, Entropy. 357 | * 358 | * Arguments: 359 | * Mat src - source Matrix (Window Mat) 360 | * TextureEValues& EValue - Texture Eigenvalues 361 | * bool ToCheckMat - to check input Mat is Probability Mat or not 362 | * 363 | * Returns: 364 | * void 365 | ===================================================================== 366 | */ 367 | void GLCM::CalcuOneTextureEValue(Mat src, TextureEValues& EValue, bool ToCheckMat) 368 | { 369 | if(ToCheckMat) 370 | { 371 | float sum = 0; 372 | for(int i = 0; i < src.rows; i++) 373 | for(int j = 0; j < src.cols; j++) 374 | sum += src.at(j, i); 375 | if(sum < 0.99 || sum > 1.01) 376 | { 377 | cout<<"ERROR in CalcuOneTextureEValue(): Sum of the Mat is not equal to 1.00."<(j, i), 2); 391 | EValue.contrast += (powf((i - j), 2) * src.at(j, i) ); 392 | EValue.homogenity += (src.at(j, i) / (1 + fabs((float)(i - j))) ); 393 | if(src.at(j, i) != 0) 394 | EValue.entropy -= (src.at(j, i) * log10(src.at(j, i)) ); 395 | } 396 | } 397 | 398 | /*=================================================================== 399 | * 函数名:CalcuTextureEValue 400 | * 说明:计算全图的图像纹理特征值,包括能量、对比度、相关度、熵 401 | * 参数: 402 | * Mat src: 源矩阵,窗口矩阵 403 | * TextureEValues& EValue: 输出目标,全图的纹理特征值变量 404 | * int size: 窗口尺寸(仅支持5*5, 7*7) 405 | * GrayLevel level: 灰度等级 406 | * 返回值:void 407 | *------------------------------------------------------------------ 408 | * Function: CalcuOneTextureEValue 409 | * 410 | * Summary: 411 | * Calculate Texture Eigenvalues of One Window Mat, which is including 412 | * Energy, Contrast, Homogenity, Entropy. 413 | * 414 | * Arguments: 415 | * Mat src - source Matrix (Window Mat) 416 | * TextureEValues& EValue - Output Dst: Texture Eigenvalues of the Whole Image 417 | * int size - size of Mat Window (only support 5*5, 7*7) 418 | * GrayLevel level - Destination image's Gray Level (choose in 4/8/16) 419 | * 420 | * Returns: 421 | * void 422 | ===================================================================== 423 | */ 424 | void GLCM::CalcuTextureEValue(Mat src, TextureEValues& EValue, int size, GrayLevel level) 425 | { 426 | // 原图像的灰度图 427 | // Gray Image of the Source Image 428 | Mat imgGray; 429 | 430 | // 窗口矩阵 431 | // Window Matrix 432 | Mat glcm_win; 433 | 434 | // 归一化后的概率矩阵 435 | // Probability Matrix after Normalizing 436 | Mat glcm_norm; 437 | 438 | // 纹理特征值缓存变量 439 | // Texture Eigenvalues temp variable 440 | TextureEValues EValue_temp; 441 | 442 | // 初始化目标纹理特征值 443 | // Init Dst Texture Eigenvalues 444 | EValue.contrast = 0; EValue.energy = 0; EValue.entropy = 0; EValue.homogenity = 0; 445 | 446 | // 检查输入图像是否为单通道图像,如果不是,则转换其格式 447 | // Check if Input Image is Single Channel Image or not, IF it's Single Channel Image, then Convert its Format to Gray Image. 448 | if(src.channels() != 1) 449 | cvtColor(src, imgGray, CV_BGR2GRAY); 450 | else 451 | src.copyTo(imgGray); 452 | 453 | for(int i = 0; i < imgGray.rows; i++) 454 | { 455 | for(int j = 0; j < imgGray.cols; j++) 456 | { 457 | // 计算所有统计方向的灰度共生矩阵与对应的特征值,并累加至缓存变量中 458 | // Calculate All Statistical Direction's GLCM and Eigenvalues, then accumulate into temp variables 459 | float energy, contrast, homogenity, entropy; 460 | energy = contrast = homogenity = entropy = 0; 461 | 462 | CalcuOneGLCM(imgGray, glcm_win, i, j, size, level, DIR_0); 463 | NormalizeMat(glcm_win, glcm_norm); 464 | CalcuOneTextureEValue(glcm_norm, EValue_temp, false); 465 | energy += EValue_temp.energy; contrast += EValue_temp.contrast; 466 | homogenity += EValue_temp.homogenity; entropy += EValue_temp.entropy; 467 | 468 | CalcuOneGLCM(imgGray, glcm_win, i, j, size, level, DIR_45); 469 | NormalizeMat(glcm_win, glcm_norm); 470 | CalcuOneTextureEValue(glcm_norm, EValue_temp, false); 471 | energy += EValue_temp.energy; contrast += EValue_temp.contrast; 472 | homogenity += EValue_temp.homogenity; entropy += EValue_temp.entropy; 473 | 474 | CalcuOneGLCM(imgGray, glcm_win, i, j, size, level, DIR_90); 475 | NormalizeMat(glcm_win, glcm_norm); 476 | CalcuOneTextureEValue(glcm_norm, EValue_temp, false); 477 | energy += EValue_temp.energy; contrast += EValue_temp.contrast; 478 | homogenity += EValue_temp.homogenity; entropy += EValue_temp.entropy; 479 | 480 | CalcuOneGLCM(imgGray, glcm_win, i, j, size, level, DIR_135); 481 | NormalizeMat(glcm_win, glcm_norm); 482 | CalcuOneTextureEValue(glcm_norm, EValue_temp, false); 483 | energy += EValue_temp.energy; contrast += EValue_temp.contrast; 484 | homogenity += EValue_temp.homogenity; entropy += EValue_temp.entropy; 485 | 486 | // 将所有方向计算得到的特征值平均化,得到的值即可消除统计方向影响 487 | // average Eigenvalues of all Statistical Directions, then the average value has eliminated the effect of Statistical Directions 488 | energy /= 4; contrast /= 4; 489 | homogenity /= 4; entropy /= 4; 490 | 491 | // 累加当前单个窗口的纹理特征值,作为整个图像的纹理特征值 492 | // Accumulate Texture Eigenvalues of Current Window, then make the Sum as Texture Eigenvalues of the Whole Image 493 | EValue.contrast += contrast; 494 | EValue.energy += energy; 495 | EValue.entropy += entropy; 496 | EValue.homogenity += homogenity; 497 | } 498 | } 499 | } 500 | 501 | /*=================================================================== 502 | * 函数名:CalcuTextureImages 503 | * 说明:计算整幅图像的纹理特征,并将结果输出到相应矩阵中 504 | * 参数: 505 | * Mat src: 原图像 506 | * Mat& imgEnergy: 目标能量矩阵 507 | * Mat& imgContrast: 目标对比度矩阵 508 | * Mat& imgHomogenity: 目标相关度矩阵 509 | * Mat& imgEntropy: 目标熵矩阵 510 | * int size: 窗口尺寸(仅支持5*5, 7*7) 511 | * GrayLevel level: 灰度等级 512 | * bool ToAdjustImg: 是否调整输出的纹理特征图像 513 | * 返回值:void 514 | *------------------------------------------------------------------ 515 | * Function: CalcuTextureImages 516 | * 517 | * Summary: 518 | * Calculate Texture Features of the whole Image, and output the result 519 | * into Martixs. 520 | * 521 | * Arguments: 522 | * Mat src - source Image 523 | * Mat& imgEnergy - Destination Mat, Energy Matrix 524 | * Mat& imgContrast - Destination Mat, Contrast Matrix 525 | * Mat& imgHomogenity - Destination Mat, Homogenity Matrix 526 | * Mat& imgEntropy - Destination Mat, Entropy Matrix 527 | * int size - size of Mat Window (only support 5*5, 7*7) 528 | * GrayLevel level - Destination image's Gray Level (choose in 4/8/16) 529 | * bool ToAdjustImg: to Adjust output Texture Feature Images or not 530 | * 531 | * Returns: 532 | * void 533 | ===================================================================== 534 | */ 535 | void GLCM::CalcuTextureImages(Mat src, Mat& imgEnergy, Mat& imgContrast, Mat& imgHomogenity, Mat& imgEntropy, 536 | int size, GrayLevel level, bool ToAdjustImg) 537 | { 538 | // 窗口矩阵 539 | // Window Matrix 540 | Mat glcm_win; 541 | 542 | // 归一化后的概率矩阵 543 | // Probability Matrix after Normalizing 544 | Mat glcm_norm; 545 | 546 | // 纹理特征值缓存变量 547 | // Texture Eigenvalues temp varialbe 548 | TextureEValues EValue; 549 | 550 | imgEnergy.create(src.size(), CV_32FC1); 551 | imgContrast.create(src.size(), CV_32FC1); 552 | imgHomogenity.create(src.size(), CV_32FC1); 553 | imgEntropy.create(src.size(), CV_32FC1); 554 | 555 | for(int i = 0; i < src.rows; i++) 556 | { 557 | float* energyData = imgEnergy.ptr(i); 558 | float* contrastData = imgContrast.ptr(i); 559 | float* homogenityData = imgHomogenity.ptr(i); 560 | float* entropyData = imgEntropy.ptr(i); 561 | 562 | for(int j = 0; j < src.cols; j++) 563 | { 564 | // 计算所有统计方向的灰度共生矩阵与对应的特征值,并累加至缓存变量中 565 | // Calculate All Statistical Direction's GLCM and Eigenvalues, then accumulate into temp variables 566 | float energy, contrast, homogenity, entropy; 567 | energy = contrast = homogenity = entropy = 0; 568 | 569 | CalcuOneGLCM(src, glcm_win, i, j, size, level, DIR_0); 570 | NormalizeMat(glcm_win, glcm_norm); 571 | CalcuOneTextureEValue(glcm_norm, EValue, false); 572 | energy += EValue.energy; contrast += EValue.contrast; 573 | homogenity += EValue.homogenity; entropy += EValue.entropy; 574 | 575 | CalcuOneGLCM(src, glcm_win, i, j, size, level, DIR_45); 576 | NormalizeMat(glcm_win, glcm_norm); 577 | CalcuOneTextureEValue(glcm_norm, EValue, false); 578 | energy += EValue.energy; contrast += EValue.contrast; 579 | homogenity += EValue.homogenity; entropy += EValue.entropy; 580 | 581 | CalcuOneGLCM(src, glcm_win, i, j, size, level, DIR_90); 582 | NormalizeMat(glcm_win, glcm_norm); 583 | CalcuOneTextureEValue(glcm_norm, EValue, false); 584 | energy += EValue.energy; contrast += EValue.contrast; 585 | homogenity += EValue.homogenity; entropy += EValue.entropy; 586 | 587 | CalcuOneGLCM(src, glcm_win, i, j, size, level, DIR_135); 588 | NormalizeMat(glcm_win, glcm_norm); 589 | CalcuOneTextureEValue(glcm_norm, EValue, false); 590 | energy += EValue.energy; contrast += EValue.contrast; 591 | homogenity += EValue.homogenity; entropy += EValue.entropy; 592 | 593 | // 将所有方向计算得到的特征值平均化,得到的值即可消除统计方向影响 594 | // average Eigenvalues of all Statistical Directions, then the average value has eliminated the effect of Statistical Directions 595 | energy /= 4; contrast /= 4; 596 | homogenity /= 4; entropy /= 4; 597 | 598 | energyData[j] = energy; 599 | contrastData[j] = contrast; 600 | homogenityData[j] = homogenity; 601 | entropyData[j] = entropy; 602 | } 603 | } 604 | 605 | // 调整输出特征图像,类型由CV_32FC1改为CV_8UC1,取值范围0--255 606 | // Adjust output Texture Feature Images, Change its type from CV_32FC1 to CV_8UC1, Change its value range as 0--255 607 | if(ToAdjustImg) 608 | { 609 | cv::normalize(imgEnergy, imgEnergy, 0, 255, NORM_MINMAX); 610 | cv::normalize(imgContrast, imgContrast, 0, 255, NORM_MINMAX); 611 | cv::normalize(imgEntropy, imgEntropy, 0, 255, NORM_MINMAX); 612 | cv::normalize(imgHomogenity, imgHomogenity, 0, 255, NORM_MINMAX); 613 | imgEnergy.convertTo(imgEnergy, CV_8UC1); 614 | imgContrast.convertTo(imgContrast, CV_8UC1); 615 | imgEntropy.convertTo(imgEntropy, CV_8UC1); 616 | imgHomogenity.convertTo(imgHomogenity, CV_8UC1); 617 | } 618 | } 619 | --------------------------------------------------------------------------------