灰度共生矩阵

转载于https://blog.youkuaiyun.com/qq_37059483/article/details/78292869

https://blog.youkuaiyun.com/light_lj/article/details/26098815#commentsedit

灰度共生矩阵(Gray-level Co-occurrence Matrix,GLCM)

又叫做灰度共现矩阵

概念:
像素灰度在空间位置上的反复出现形成图像的纹理,GLCM是描述具有某种空间位置关系两个像素灰度的联合分布

含义:
就是两个像素灰度的联合直方图,是一种二阶统计量

就是两个像素点的关系。像素关系可以根据不同的纹理特性进行选择,也就是的大小可以自由选

像素的空间位置关系:
取。对于较细的纹理分析可以取像素间距为1,是水平扫描;是垂直扫描;是45度扫描;是135度扫描(原博文有错误)。一旦位置空间确定,就可以生成灰度共生矩阵。

矩阵的物理意义:
用表示灰度共生矩阵,它是一个的矩阵(L为灰度级,就是一幅图中包含的不同灰度或者颜色的个数),是具有空间位置关系且灰度分别为i和j的两个像素出现的次数或频率(归一化)

例如: 下图是某纹理像素的放大,和对应的像素灰度矩阵

此图像只有三种灰度,故灰度级为3,灰度共生矩阵是一个3*3的矩阵

归一化形式为

改变位置空间的定义,灰度共生矩阵相应地改变:

归一化形式为:

矩阵的特征量:
从灰度共生矩阵上可以简单的看出,如果对角附近的元素有较大的值,说明图像的像素具有相似的像素值,如果偏离对角线的元素会有比较大的值,说明像素灰度在局部有较大变化。为了得到更多的纹理特征,我们还需要在进行计算:

对比度)(或反差)(contrast):

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

相关度(inverse different moment):

度量空间灰度共生矩阵元素在行或列方向上的相似程度,因此,相关值大小反映了图像中局部灰度相关性。当矩阵元素值均匀相等时,相关值就大;相反,如果矩阵像元值相差很大则相关值小。

能量:是灰度共生矩阵元素值的平方和,所以也称之为能量,反映了图像灰度分布均匀程度和纹理粗细度。ASM值大表明一种较均一和规则变化的纹理模式。

熵(entropy):熵在物理中的含义就是物体的规则度,越有序熵越小,越无序熵越大。此处熵同样表示图像的信息量,当共生矩阵中所有元素有最大的随机性、空间共生矩阵中所有值几乎相等时,共生矩阵中元素分散分布时,熵较大。它表示了图像中纹理的非均匀程度或复杂程度。


自相关(correlation):反应了图像纹理的一致性。如果图像中有水平方向纹理,则水平方向矩阵的COR大于其余矩阵的COR值。
代码:

GLCM.h
#include<iostream>
#include <cassert>
#include <vector>
#include <iterator>
#include <functional>
#include <algorithm>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

typedef vector<vector<int> > VecGLCM;

typedef struct _GLCMFeatures
{
    _GLCMFeatures()
        : energy(0.0)
        , entropy(0.0)
        , contrast(0.0)
        , idMoment(0.0)
    {

    }

    double energy;      // 能量 
    double entropy;     // 熵
    double contrast;    // 对比度
    double idMoment;    // 逆差分矩, inverse difference moment

} GLCMFeatures;

class GLCM
{
public:
    GLCM();
    ~GLCM();

public:
    // 枚举灰度共生矩阵的方向
    enum 
    {
        GLCM_HORIZATION = 0,        // 水平
        GLCM_VERTICAL = 1,          // 垂直
        GLCM_ANGLE45 = 2,           // 45度角
        GLCM_ANGLE135 = 3           // 135度角
    };

public:
    // 计算灰度共生矩阵
    void calGLCM(IplImage* inputImg, VecGLCM& vecGLCM, int angle);
    // 计算特征值
    void getGLCMFeatures(VecGLCM& vecGLCM, GLCMFeatures& features);
public:
    // 初始化灰度共生矩阵
    void initGLCM(VecGLCM& vecGLCM, int size = 16);
    // 设置灰度划分等级,默认值为 16
    void setGrayLevel(int grayLevel) { m_grayLevel = grayLevel; }
    // 获取灰度等级
    int getGrayLevel() const { return m_grayLevel; }
private:
    // 计算水平灰度共生矩阵
    void getHorisonGLCM(VecGLCM &src, VecGLCM &dst, int imgWidth, int imgHeight);
    // 计算垂直灰度共生矩阵
    void getVertialGLCM(VecGLCM &src, VecGLCM &dst, int imgWidth, int imgHeight);
    // 计算 45 度灰度共生矩阵
    void getGLCM45(VecGLCM &src, VecGLCM &dst, int imgWidth, int imgHeight);
    // 计算 135 度灰度共生矩阵
    void getGLCM135(VecGLCM &src, VecGLCM &dst, int imgWidth, int imgHeight);

private:
    int m_grayLevel;        // 将灰度共生矩阵划分为 grayLevel 个等级

};


GLCM.cpp

#include "GLCM.h"

GLCM::GLCM() : m_grayLevel(16)
{

}

GLCM::~GLCM()
{

}

//==============================================================================
// 函数名称: initGLCM
// 参数说明: vecGLCM,要进行初始化的共生矩阵,为二维方阵
//          size, 二维矩阵的大小,必须与图像划分的灰度等级相等
// 函数功能: 初始化二维矩阵
//==============================================================================

void GLCM::initGLCM(VecGLCM& vecGLCM, int size)
{
    assert(size == m_grayLevel);
    vecGLCM.resize(size);
    for (int i = 0; i < size; ++i)
    {
        vecGLCM[i].resize(size);
    }

    for (int i = 0; i < size; ++i)
    {
        for (int j = 0; j < size; ++j)
        {
            vecGLCM[i][j] = 0;
        }
    }
}

//==============================================================================
// 函数名称: getHorisonGLCM
// 参数说明: src,要进行处理的矩阵,源数据
//          dst,输出矩阵,计算后的矩阵,即要求的灰度共生矩阵
//          imgWidth, 图像宽度
//          imgHeight, 图像高度
// 函数功能: 计算水平方向的灰度共生矩阵
//==============================================================================

void GLCM::getHorisonGLCM(VecGLCM &src, VecGLCM &dst, int imgWidth, int imgHeight)
{
    int height = imgHeight;
    int width = imgWidth;

    for (int i = 0; i < height; ++i)
    {
        for (int j = 0; j < width - 1; ++j)
        {
            int rows = src[i][j];
            int cols = src[i][j + 1];
            dst[rows][cols]++;
        }
    }


}

//==============================================================================
// 函数名称: getVertialGLCM
// 参数说明: src,要进行处理的矩阵,源数据
//          dst,输出矩阵,计算后的矩阵,即要求的灰度共生矩阵
//          imgWidth, 图像宽度
//          imgHeight, 图像高度
// 函数功能: 计算垂直方向的灰度共生矩阵
//==============================================================================

void GLCM::getVertialGLCM(VecGLCM &src, VecGLCM &dst, int imgWidth, int imgHeight)
{
    int height = imgHeight;
    int width = imgWidth;
    for (int i = 0; i < height - 1; ++i)
    {
        for (int j = 0; j < width; ++j)
        {
            int rows = src[i][j];
            int cols = src[i + 1][j];
            dst[rows][cols]++;
        }
    }
}

//==============================================================================
// 函数名称: getGLCM45
// 参数说明: src,要进行处理的矩阵,源数据
//          dst,输出矩阵,计算后的矩阵,即要求的灰度共生矩阵
//          imgWidth, 图像宽度
//          imgHeight, 图像高度
// 函数功能: 计算45度的灰度共生矩阵
//==============================================================================

void GLCM::getGLCM45(VecGLCM &src, VecGLCM &dst, int imgWidth, int imgHeight)
{
    int height = imgHeight;
    int width = imgWidth;
    for (int i = 0; i < height - 1; ++i)
    {
        for (int j = 0; j < width - 1; ++j)
        {
            int rows = src[i][j];
            int cols = src[i + 1][j + 1];
            dst[rows][cols]++;
        }
    }
}


//==============================================================================
// 函数名称: getGLCM135
// 参数说明: src,要进行处理的矩阵,源数据
//          dst,输出矩阵,计算后的矩阵,即要求的灰度共生矩阵
//          imgWidth, 图像宽度
//          imgHeight, 图像高度
// 函数功能: 计算 135 度的灰度共生矩阵
//==============================================================================

void GLCM::getGLCM135(VecGLCM& src, VecGLCM& dst, int imgWidth, int imgHeight)
{
    int height = imgHeight;
    int width = imgWidth;
    for (int i = 0; i < height - 1; ++i)
    {
        for (int j = 1; j < width; ++j)
        {
            int rows = src[i][j];
            int cols = src[i + 1][j - 1];
            dst[rows][cols]++;
        }
    }
}

//==============================================================================
// 函数名称: calGLCM
// 参数说明: inputImg,要进行纹理特征计算的图像,为灰度图像
//          vecGLCM, 输出矩阵,根据灰度图像计算出的灰度共生阵
//          angle,灰度共生矩阵的方向,有水平、垂直、45度、135度四个方向
// 函数功能: 计算灰度共生矩阵
//==============================================================================

void GLCM::calGLCM(IplImage* inputImg, VecGLCM& vecGLCM, int angle)
{
    assert(inputImg->nChannels == 1);
    IplImage* src = NULL;
    src = cvCreateImage(cvGetSize(inputImg), IPL_DEPTH_32S, inputImg->nChannels);
    cvConvert(inputImg, src);

    int height = src->height;
    int width = src->width;
    int maxGrayLevel = 0;
    // 寻找最大像素灰度最大值
    for (int i = 0; i < height; ++i)
    {
        for (int j = 0; j < width; ++j)
        {
            int grayVal = cvGetReal2D(src, i, j);
            if (grayVal > maxGrayLevel)
            {
                maxGrayLevel = grayVal;
            }

        }
    }// end for i

    ++maxGrayLevel;
    VecGLCM tempVec;
    // 初始化动态数组
    tempVec.resize(height);
    for (int i = 0; i < height; ++i)
    {
        tempVec[i].resize(width);
    }

    if (maxGrayLevel > 16)//若灰度级数大于16,则将图像的灰度级缩小至16级,减小灰度共生矩阵的大小。
    {
        for (int i = 0; i < height; ++i)
        {
            for (int j = 0; j < width; ++j)
            {
                int tmpVal = cvGetReal2D(src, i, j);
                tmpVal /= m_grayLevel;
                tempVec[i][j] = tmpVal;
            }
        }

        if (angle == GLCM_HORIZATION)  // 水平方向
            getHorisonGLCM(tempVec, vecGLCM, width, height);
        if (angle == GLCM_VERTICAL)    // 垂直方向
            getVertialGLCM(tempVec, vecGLCM, width, height);
        if (angle == GLCM_ANGLE45)     // 45 度灰度共生阵
            getGLCM45(tempVec, vecGLCM, width, height);
        if (angle == GLCM_ANGLE135)    // 135 度灰度共生阵
            getGLCM135(tempVec, vecGLCM, width, height);
    }
    else//若灰度级数小于16,则生成相应的灰度共生矩阵
    {
        for (int i = 0; i < height; ++i)
        {
            for (int j = 1; j < width; ++j)
            {
                int tmpVal = cvGetReal2D(src, i, j);
                tempVec[i][j] = tmpVal;
            }
        }

        if (angle == GLCM_HORIZATION)  // 水平方向
            getHorisonGLCM(tempVec, vecGLCM, width, height);
        if (angle == GLCM_VERTICAL)    // 垂直方向
            getVertialGLCM(tempVec, vecGLCM, width, height);
        if (angle == GLCM_ANGLE45)     // 45 度灰度共生阵
            getGLCM45(tempVec, vecGLCM, width, height);
        if (angle == GLCM_ANGLE135)    // 135 度灰度共生阵
            getGLCM135(tempVec, vecGLCM, width, height);
    }

    cvReleaseImage(&src);
}

//==============================================================================
// 函数名称: getGLCMFeatures
// 参数说明: vecGLCM, 输入矩阵,灰度共生阵
//          features,灰度共生矩阵计算的特征值,主要包含了能量、熵、对比度、逆差分矩
// 函数功能: 根据灰度共生矩阵计算的特征值
//==============================================================================

void GLCM::getGLCMFeatures(VecGLCM& vecGLCM, GLCMFeatures& features)
{
    int total = 0;

    for (int i = 0; i < m_grayLevel; ++i)
    {
        for (int j = 0; j < m_grayLevel; ++j)
        {
            total += vecGLCM[i][j];     // 求所有图像的灰度值的和
        }
    }

    vector<vector<double> > temp;
    temp.resize(m_grayLevel);
    for (int i = 0; i < m_grayLevel; ++i)
    {
        temp[i].resize(m_grayLevel);
    }

    // 归一化
    for (int i = 0; i < m_grayLevel; ++i)
    {
        for (int j = 0; j < m_grayLevel; ++j)
        {
            temp[i][j] = (double)vecGLCM[i][j] / (double)total;
        }
    }

    for (int i = 0; i < m_grayLevel; ++i)
    {
        for (int j = 0; j < m_grayLevel; ++j)
        {
            features.energy += temp[i][j] * temp[i][j];

            if (temp[i][j]>0)
                features.entropy -= temp[i][j] * log(temp[i][j]);               //熵     

            features.contrast += (double)(i - j)*(double)(i - j)*temp[i][j];        //对比度
            features.idMoment += temp[i][j] / (1 + (double)(i - j)*(double)(i - j));//逆差矩
        }
    }
}
main.cpp

#include "GLCM.h"
#include <string>

void getFileName();
string names[2000];
char data[20];
const string filename = "C:\\Users\\ltc\\Desktop\\data5\\Sobel\\数值处理\\背景\\";

int main()
{
    fstream finout1("data.txt", ios::in | ios::out|ios::trunc);
    getFileName();
    int i = 0;
    char data1[20];
    while (names[i].length() > 5){
        strcpy_s(data1, names[i].c_str());
        string imagename = data1;
        //灰度共生矩阵
        IplImage* img = cvLoadImage(data1, 0);
        cvSetImageROI(img, cvRect(1453, 1149,557, 557));
        /*cvNamedWindow("ShowSRC"); 
        cvShowImage("ShowSRC",img); 
        cvWaitKey(0);  */

        GLCM glcm;
        VecGLCM vec;
        GLCMFeatures features;
        glcm.initGLCM(vec);
        // 水平
        glcm.calGLCM(img, vec, GLCM::GLCM_HORIZATION);
        glcm.getGLCMFeatures(vec, features);
        double energy_hor = features.energy;
        double entropy_hor = features.entropy;
        double contrast_hor = features.contrast;
        double idMoment_hor = features.idMoment;

        // 垂直
        glcm.calGLCM(img, vec, GLCM::GLCM_VERTICAL);
        glcm.getGLCMFeatures(vec, features);
        double energy_vetical = features.energy;
        double entropy_vetical = features.entropy;
        double contrast_vetical = features.contrast;
        double idMoment_vetical = features.idMoment;


        // 45 度
        glcm.calGLCM(img, vec, GLCM::GLCM_ANGLE45);
        glcm.getGLCMFeatures(vec, features);
        double energy_45 = features.energy;
        double entropy_45 = features.entropy;
        double contrast_45 = features.contrast;
        double idMoment_45 = features.idMoment;


        // 135 度
        glcm.calGLCM(img, vec, GLCM::GLCM_ANGLE135);
        glcm.getGLCMFeatures(vec, features);
        double energy_135 = features.energy;
        double entropy_135 = features.entropy;
        double contrast_135 = features.contrast;
        double idMoment_135 = features.idMoment;

        double energy_average = (energy_135 + energy_45 + energy_hor + energy_vetical) / 4;
        double entropy_average = (entropy_135 + entropy_45 + entropy_hor + entropy_vetical) / 4;
        double contrast_average = (contrast_135 + contrast_45 + contrast_hor + contrast_vetical) / 4;
        double idMoment_average = (idMoment_135 + idMoment_45 + idMoment_hor + idMoment_vetical) / 4;


        cout<< energy_average<<"  " <<entropy_average <<"  "<< contrast_average<<"  " << idMoment_average << endl;
        finout1 << energy_average<<"  " <<entropy_average <<"  "<< contrast_average<<"  " << idMoment_average << endl;
        i++;
    }
    system("pause");
    return 0;
}

void getFileName(){
    fstream finout("C:\\Users\\ltc\\Desktop\\data5\\FILENAME.TXT", ios::in | ios::out);
    ostringstream outstr;
    if (finout.is_open()){
        finout.seekg(0);
        int i = 0;
        while (finout.getline(data, 19)){
            outstr << data;

            names[i] = outstr.str();
            //cout <<setw(30)<<i<<setw(30)<<names[i]<<'\n';
            i++;
            outstr.str("");

        }
    }
    else
        cout << "failed" << endl;
}
 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值