|
计算灰度共生矩阵
共生矩阵用两个位置的象素的联合概率密度来定义,它不仅反映亮度的分布特性,也反映具有同样亮度或接近亮度的象素之间的位置分布特性,是有关图象亮度变化的二阶统计特征。它是定义一组纹理特征的基础。
灰度共生矩阵能反映出图象灰度关于方向、相邻间隔、变化幅度的综合信息。设f(x,y)为一幅二维数字图象,其大小为M×N,灰度级别为Ng,则满足一定空间关系的灰度共生矩阵为:
P(i,j)=#{(x1,y1),(x2,y2)∈M×N|f(x1,y1)=i,f(x2,y2)=j}
其中#(x)表示集合x中的元素个数,显然P为Ng×Ng的矩阵,若(x1,y1)与(x2,y2)间距离为d,两者与坐标横轴的夹角为θ,则可以得到各种间距及角度的灰度共生矩阵P(i,j,d,θ)。
 
class CGlcm{public:CGlcm(void);virtual ~CGlcm(void);public:int *m_pMat1;int *m_pMat2;int *m_pMat3;int *m_pMat4;protected:int *m_pLine[4][256];int m_nMin;int m_nMax;int m_nSum;public:// 计算共生矩阵// 参数:// 1. pImageData: 图像数据指针,单通道,8位。// 2. nLeft,nTop,nWidth,nHeight: 计算共生矩阵的区域。// 3. nWidthStep: 行偏移量。// 4. nScale: 尺度。// 5. nReduction: 灰度级压缩。bool CalGlcm(unsigned char *pImageData, int nLeft, int nTop, int nWidth, int nHeight, int nWidthStep, int nScale, int nReduction);};// 灰度共生矩阵CGlcm::CGlcm(void): m_pMat1(NULL), m_pMat2(NULL), m_pMat3(NULL), m_pMat4(NULL), m_nMin(0), m_nMax(0), m_nSum(0){int i, j;unsigned int nSize = sizeof(int) * 256 * 256;// 创建共生矩阵m_pMat1 = (int*) malloc(nSize);m_pMat2 = (int*) malloc(nSize);m_pMat3 = (int*) malloc(nSize);m_pMat4 = (int*) malloc(nSize);if (m_pMat1 && m_pMat2 && m_pMat3 && m_pMat4){for (i = 0, j = 0; i < 256; i++, j += 256){m_pLine[0] = m_pMat1 + j;m_pLine[1] = m_pMat2 + j;m_pLine[2] = m_pMat3 + j;m_pLine[3] = m_pMat4 + j;}}}CGlcm::~CGlcm(void){// 释放共生矩阵if (m_pMat1) free(m_pMat1);if (m_pMat2) free(m_pMat2);if (m_pMat3) free(m_pMat3);if (m_pMat4) free(m_pMat4);}// 计算共生矩阵bool CGlcm::CalGlcm(unsigned char *pImageData, int nLeft, int nTop, int nWidth, int nHeight, int nWidthStep, int nScale, int nReduction){bool bResult = false;int x0, x1, x2;int y0, y1, y2;int nGray;unsigned int nSize;unsigned char *pLine[3];if (pImageData){// 灰度最值m_nMin = 0xFF;m_nMax = 0;pLine[1] = pImageData + nWidthStep * nTop + nLeft;for (y1 = 0; y1 < nHeight; y1++){for (x1 = 0; x1 < nWidth; x1++){// 灰度级压缩if (nReduction > 0){pLine[1][x1] = pLine[1][x1] >> nReduction;}nGray = pLine[1][x1];if (nGray < m_nMin){m_nMin = nGray;}else if (nGray > m_nMax){m_nMax = nGray;}}pLine[1] += nWidthStep;}// 累加和m_nSum = nWidth * nHeight * 2;if (m_nMax >= m_nMin){// 清空内存nSize = sizeof(int) * (m_nMax - m_nMin + 1);for (y1 = m_nMin; y1 <= m_nMax; y1++){memset(&m_pLine[0][y1][m_nMin], 0, nSize);memset(&m_pLine[1][y1][m_nMin], 0, nSize);memset(&m_pLine[2][y1][m_nMin], 0, nSize);memset(&m_pLine[3][y1][m_nMin], 0, nSize);}// 计算共生矩阵pLine[1] = pImageData + nWidthStep * nTop + nLeft;for (y0 = -nScale, y1 = 0, y2 = nScale; y1 < nHeight; y0++, y1++, y2++){pLine[0] = pLine[1] - nWidthStep;pLine[2] = pLine[1] + nWidthStep;for (x0 = -nScale, x1 = 0, x2 = nScale; x1 < nWidth; x0++, x1++, x2++){nGray = pLine[1][x1];// 0 度if (x2 < nWidth){m_pLine[0][nGray][pLine[1][x2]]++;}// 45 度if (y0 > 0 && x2 < nWidth){m_pLine[1][nGray][pLine[0][x2]]++;}// 90 度if (y0 > 0){m_pLine[2][nGray][pLine[0][x1]]++;}// 135 度if (y0 > 0 && x0 > 0){m_pLine[3][nGray][pLine[0][x0]]++;}// 180 度if (x0 > 0){m_pLine[0][nGray][pLine[1][x0]]++;}// 225 度if (x0 > 0 && y2 < nHeight){m_pLine[1][nGray][pLine[2][x0]]++;}// 270 度if (y2 < nHeight){m_pLine[2][nGray][pLine[2][x1]]++;}// 315 度if (y2 < nHeight && x2 < nWidth){m_pLine[3][nGray][pLine[2][x2]]++;}}pLine[1] += nWidthStep;}bResult = true;}}return bResult;}
提取共生矩阵特征
为了能更直观地以共生矩阵描述纹理状况,从共生矩阵导出一些反映矩阵状况的参数,典型的有以下几种:
- 角二阶矩(ASM):是灰度共生矩阵元素值的平方和,所以也称能量。它反映了图像灰度分布均匀程度和纹理粗细度。如果共生矩阵的所有值均相等,则ASM值小;相反,如果其中一些值大而其它值小,则ASM值大。当共生矩阵中元素集中分布时,此时ASM值大。ASM值大表明一种较均一和规则变化的纹理模式。

- 熵(ENT):是图像所具有的信息量的度量,纹理信息也属于图像的信息,是一个随机性的度量,当共生矩阵中所有元素有最大的随机性、空间共生矩阵中所有值几乎相等时,共生矩阵中元素分散分布时,熵较大。它表示了图像中纹理的非均匀程度或复杂程度。

- 对比度(CON):反映了图像的清晰度和纹理沟纹深浅的程度。纹理沟纹越深,其对比度越大,视觉效果越清晰;反之,对比度小,则沟纹浅,效果模糊。灰度差即对比度大的象素对越多,这个值越大。灰度公生矩阵中远离对角线的元素值越大,CON越大。

- 逆差距(HOM):反映图像纹理的同质性,度量图像纹理局部变化的多少。其值大则说明图像纹理的不同区域间缺少变化,局部非常均匀。

- 相关(COR):度量空间灰度共生矩阵元素在行或列方向上的相似程度,因此,相关值大小反映了图像中局部灰度相关性。当矩阵元素值均匀相等时,相关值就大;相反,如果矩阵像元值相差很大则相关值小。如果图像中有水平方向纹理,则水平方向矩阵的COR大于其余矩阵的COR值。

#include <math.h>// 共生矩阵特征struct GlcmFeature{double ASM[4]; // 角二阶矩/能量double ENT[4]; // 熵double CON[4]; // 对比度double HOM[4]; // 逆差矩/同质性double COR[4]; // 相关性};// 灰度共生矩阵class CGlcm{public:CGlcm(void);virtual ~CGlcm(void);public:int *m_pMat1;int *m_pMat2;int *m_pMat3;int *m_pMat4;protected:int *m_pLine[4][256];int m_nMin;int m_nMax;int m_nSum;public:// 计算共生矩阵// 参数:// 1. pImageData: 图像数据指针,单通道,8位。// 2. nLeft,nTop,nWidth,nHeight: 计算共生矩阵的区域。// 3. nWidthStep: 行偏移量。// 4. nScale: 尺度。// 5. nReduction: 灰度级压缩。bool CalGlcm(unsigned char *pImageData, int nLeft, int nTop, int nWidth, int nHeight, int nWidthStep, int nScale, int nReduction);// 共生矩阵特征// 参数:// 1. Feature: 输出共生矩阵特征。void GetFeature(GlcmFeature& Feature);};// 共生矩阵特征void CGlcm::GetFeature(GlcmFeature& Feature){int x, y;int nTheta;int nValue;int nTemp;double dValue;double dMean, dStdDev;double dSum[256];// 清空内存memset(&Feature, 0, sizeof(Feature));// 方向循环for (nTheta = 0; nTheta < 4; nTheta++){dMean = 0;dStdDev = 0;// 清空内存memset(dSum, 0, sizeof(dSum));for (y = m_nMin; y <= m_nMax; y++){for (x = m_nMin; x <= m_nMax; x++){nValue = m_pLine[nTheta][y][x];if (nValue != 0){// 归一化共生矩阵dValue = (double) nValue / (double) m_nSum;nTemp = (x - y) * (x - y);// 角二阶矩/能量Feature.ASM[nTheta] += (dValue * dValue);// 熵Feature.ENT[nTheta] -= (dValue * log(dValue));// 对比度Feature.CON[nTheta] += (nTemp * dValue);// 逆差矩/同质性Feature.HOM[nTheta] += (dValue / (1 + nTemp));// 相关性Feature.COR[nTheta] += (x * y * dValue);dSum[y] += dValue;}}}for (y = m_nMin; y <= m_nMax; y++){dMean += (y * dSum[y]);}for (y = m_nMin; y <= m_nMax; y++){dStdDev += ((y - dMean) * (y - dMean) * dSum[y]);}// 相关性if (abs(dStdDev) > 1e-15){Feature.COR[nTheta] = (Feature.COR[nTheta] - dMean * dMean) / dStdDev;}else{Feature.COR[nTheta] = 0;}}}
|
|