基于opencv的灰度梯度共生矩阵

来自于gitee,直接上源代码:

//
// Created by lihao on 2020/4/15.
//https://gitee.com/lihao-20200423/lihao-code/commit/67962c76cd08257d08d078e5b47152352754e9a1

#ifndef DETECT_SOCKS_GGCM_H
#define DETECT_SOCKS_GGCM_H

#include <iostream>
#include <vector>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

typedef vector<vector<int>> VecGGCM;


typedef struct _GGCMFeatures
{
    _GGCMFeatures()
            : small_grads_dominance(0.0)
            , big_grads_dominance(0.0)
            , gray_asymmetry(0.0)
            , grads_asymmetry(0.0)
            , energy(0.0)
            , gray_mean(0.0)
            , grads_mean(0.0)
            , gray_variance(0.0)
            , grads_variance(0.0)
            , corelation(0.0)
            , gray_entropy(0.0)
            , grads_entropy(0.0)
            , entropy(0.0)
            , inertia(0.0)
            , differ_moment(0.0)
    {}
    float small_grads_dominance;  //小梯度优势
    float big_grads_dominance;  //大梯度优势
    float gray_asymmetry;  //灰度分布不均匀性
    float grads_asymmetry;  //梯度分布不均匀性
    float energy;  //能量
    float gray_mean ;  // 灰度均值
    float grads_mean ;  // 梯度均值
    float gray_variance ;  // 灰度均方差
    float grads_variance ;  // 梯度均方差
    float corelation ;  // 相关性
    float gray_entropy ;  //灰度熵
    float grads_entropy ;  // 梯度熵
    float entropy ;   // 混合熵
    float inertia ;  // 惯性
    float differ_moment ;   // 逆差距
} GGCMFeatures;

class GGCM {

public:
    GGCM();
    ~GGCM();

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

public:
    // 初始化灰度-梯度共生矩阵
    void initGGCM(VecGGCM& vecGGCM, int size = 16);
    // 计算灰度-梯度共生矩阵
    void calGGCM(Mat &inputImg,VecGGCM &vecGGCM,VecGGCM &tempVec_Gray,VecGGCM &tempVec_Gradient);
    // 计算特征值
    void getGGCMFeatures(VecGGCM& vecGGCM, GGCMFeatures& features);
};


#endif //DETECT_SOCKS_GGCM_H

然后是实现文件:

//
// Created by lihao on 2020/4/15.
//

#include "GGCM.h"


GGCM::GGCM() : m_grayLevel(16){}

GGCM::~GGCM(){}


void GGCM::initGGCM(VecGGCM& vecGGCM, int size){
    assert(size == m_grayLevel);
    vecGGCM.resize(size);
    for (int i = 0; i < size; ++i){
        vecGGCM[i].resize(size);
    }

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

void GGCM::calGGCM(Mat &inputImg, VecGGCM& vecGGCM,VecGGCM &tempVec_Gray,VecGGCM &tempVec_Gradient){
    Mat src;
    src=inputImg.clone();

    int height = src.rows;
    int width = src.cols;

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

    tempVec_Gray.resize(height);
    for (int i = 0; i < height; ++i){
        tempVec_Gray[i].resize(width);
    }

    //  灰度归一化
    if (maxGrayLevel > m_grayLevel)//若灰度级数大于16,则将图像的灰度级缩小至16级。
    {
        for (int i = 0; i < height; ++i){
            for (int j = 0; j < width; ++j){
                int tmpVal = src.at<uchar>(i,j);
                tempVec_Gray[i][j] = int(tmpVal*m_grayLevel/maxGrayLevel);
            }
        }
    }
    else{   //若灰度级数小于16,则生成相应的灰度矩阵
        for (int i = 0; i < height; ++i){
            for (int j = 0; j < width; ++j){
                int tmpVal = src.at<uchar>(i,j);
                tempVec_Gray[i][j] = tmpVal;
            }
        }
    }

    tempVec_Gradient.resize(height);
    for (int i = 0; i < height; ++i){
        tempVec_Gradient[i].resize(width);
    }
    int maxGradientLevel = 0;
    //  求图像的梯度
    for (int i = 0; i < height; ++i){
        for (int j = 0; j < width; ++j){
            if(i==0||i==height-1||j==0||j==width-1){
                tempVec_Gradient[i][j]=0;
            }else{
                int g_x=src.at<uchar>(i+1,j-1)+2*src.at<uchar>(i+1,j)+src.at<uchar>(i+1,j+1)
                        -src.at<uchar>(i-1,j-1)-2*src.at<uchar>(i-1,j)-src.at<uchar>(i-1,j+1);
                int g_y=src.at<uchar>(i-1,j+1)+2*src.at<uchar>(i,j+1)+src.at<uchar>(i+1,j+1)
                        -src.at<uchar>(i-1,j+1)-2*src.at<uchar>(i,j-1)-src.at<uchar>(i+1,j-1);
                int g=sqrt(g_x*g_x+g_y*g_y);
                tempVec_Gradient[i][j]=g;
                if(g>maxGradientLevel){
                    maxGradientLevel=g;
                }
            }
        }
    }
    ++maxGradientLevel;
    //  梯度归一化
    if(maxGradientLevel>m_grayLevel){
        for (int i = 0; i < height; ++i){
            for (int j = 0; j < width; ++j){
                int tmpVal = tempVec_Gradient[i][j];
                tempVec_Gradient[i][j] = int(tmpVal*m_grayLevel/maxGradientLevel);
            }
        }
    }
    //得到梯度-灰度共生矩阵
    for (int i = 0; i < height; ++i){
        for (int j = 0; j < width; ++j){
            int row=tempVec_Gray[i][j];
            int col=tempVec_Gradient[i][j];
            vecGGCM[row][col]++;
        }
    }
}

// 二维数组求和
template<typename T>
float sumVVector(vector<vector<T>> v)
{
    float ans = 0;
    for(int i = 0; i < v.size(); ++i)
    {
        for(int j = 0; j < v[i].size(); ++j)
        {
            ans += v[i][j];
        }
    }
    return ans;
}

// 二维数组按行求和
template<typename T>
float sumRowVVector(vector<vector<T>> v, int num)
{
    float ans = 0;
    for(int i = 0; i < v.size(); ++i)
    {
        ans += v[num][i];
    }
    return ans;
}

// 二维数组按列求和
template<typename T>
float sumColVVector(vector<vector<T>> v, int num)
{
    float ans = 0;
    for(int i = 0; i < v.size(); ++i)
    {
        ans += v[i][num];
    }
    return ans;
}

void GGCM::getGGCMFeatures(VecGGCM& vecGGCM, GGCMFeatures& features){
    float total=sumVVector(vecGGCM);
    for (int i = 0; i < m_grayLevel; ++i){
        float sumRowGray = 0;
        sumRowGray = sumRowVVector(vecGGCM, i);
        float sumColGrad =0;
        sumColGrad=sumColVVector(vecGGCM, i);
        for (int j = 0; j < m_grayLevel; ++j){
            features.small_grads_dominance += vecGGCM[i][j] / pow(j+1, 2);
            features.big_grads_dominance+=vecGGCM[i][j] * pow(j+1 ,2);
        }
        features.gray_asymmetry += pow(sumRowGray, 2);
        features.grads_asymmetry += pow(sumColGrad, 2);
    }

    features.small_grads_dominance /= total;
    features.big_grads_dominance /= total;
    features.gray_asymmetry /= total;
    features.grads_asymmetry /= total;

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

    for(int i=0;i<vecGGCM.size();i++){
        for(int j=0;j<vecGGCM[i].size();j++){
            int tmp=vecGGCM[i][j];
            vecPGGCM[i][j]=tmp/total;
        }
    }

    for(int i=0;i<m_grayLevel;i++){
        float sumRowGray = 0;
        sumRowGray = sumRowVVector(vecPGGCM, i);
        float sumColGrad=0;
        sumColGrad = sumColVVector(vecPGGCM, i);
        for(int j=0;j<m_grayLevel;j++){
            features.energy += pow(vecPGGCM[i][j], 2);
            if(vecGGCM[i][j] != 0)
            {
                features.entropy -= vecPGGCM[i][j] * log(vecPGGCM[i][j]);
                features.inertia += pow((i-j), 2) * vecPGGCM[i][j];
            }
            features.differ_moment += vecPGGCM[i][j] / (1 + pow((i-j), 2));
        }
        features.gray_mean += (i+1) * sumRowGray;
        features.grads_mean += (i+1) * sumColGrad;
        if(sumRowGray != 0){
            features.gray_entropy -= sumRowGray * log(sumRowGray);
        }
        if(sumColGrad!=0){
            features.grads_entropy-=sumColGrad*log(sumColGrad);
        }
    }

    for(int i=0;i<m_grayLevel;i++){
        float sumRowGray = 0;
        sumRowGray = sumRowVVector(vecPGGCM, i);
        features.gray_variance+=pow(i+1-features.gray_mean,2)*sumRowGray;
        float sumColGrad=0;
        sumColGrad = sumColVVector(vecPGGCM, i);
        features.grads_variance+=pow(i+1-features.grads_mean,2)*sumColGrad;
    }
    features.gray_variance = pow(features.gray_variance, 0.5);
    features.grads_variance = pow(features.grads_variance, 0.5);

    for(int i = 0; i < m_grayLevel; ++i){
        for(int j = 0; j < m_grayLevel; ++j){
            features.corelation += (i+1-features.gray_mean) * (j+1-features.grads_mean) * vecPGGCM[i][j];
        }
    }
    features.corelation=features.corelation/(features.gray_variance*features.grads_variance);

}

用法很简单,直接按照顺序调用三个public函数即可!

原文地址:https://www.cnblogs.com/autumoonchina/p/14911527.html