灰度共生矩阵

22 篇文章 0 订阅
21 篇文章 4 订阅

使用C++、opencv获取图像的灰度共生矩阵,即能量、熵、对比度、逆差矩等图像特征参数

 灰度共生矩阵,指的是一种通过研究灰度的空间相关特性来描述纹理的常用方法,通俗的说就是图像的一组关于纹理信息图像特征(能量、熵、对比度、逆差矩),可以将纹理数字化。

灰度共生矩阵的原理和四个特征参数的计算公式可参考博客:https://blog.csdn.net/zhangxz259/article/details/81700167https://blog.csdn.net/qq_37059483/article/details/78292869


代码:

#include "stdafx.h"
#include <iostream>
#include <opencv2/highgui.hpp>
#include <opencv2/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;

//灰度等级设为16
const int gray_level = 16;

//0度灰度共生矩阵
void getglcm_horison(Mat& input, Mat& dst)
{
	Mat src = input;
	CV_Assert(1 == src.channels());
	src.convertTo(src, CV_32S);
	int height = src.rows;
	int width = src.cols;
	int max_gray_level = 0;
	for (int j = 0; j < height; j++)//寻找像素灰度最大值
	{
		int* srcdata = src.ptr<int>(j);
		for (int i = 0; i < width; i++)
		{
			if (srcdata[i] > max_gray_level)
			{
				max_gray_level = srcdata[i];
			}
		}
	}
	max_gray_level++;//像素灰度最大值加1即为该矩阵所拥有的灰度级数
	if (max_gray_level > 16)//若灰度级数大于16,则将图像的灰度级缩小至16级,减小灰度共生矩阵的大小。
	{
		for (int i = 0; i < height; i++)
		{
			int*srcdata = src.ptr<int>(i);
			for (int j = 0; j < width; j++)
			{
				srcdata[j] = (int)srcdata[j] / gray_level;
			}
		}

		dst.create(gray_level, gray_level, CV_32SC1);
		dst = Scalar::all(0);
		for (int i = 0; i < height; i++)
		{
			int*srcdata = src.ptr<int>(i);
			for (int j = 0; j < width - 1; j++)
			{
				int rows = srcdata[j];
				int cols = srcdata[j + 1];
				dst.ptr<int>(rows)[cols]++;
			}
		}
	}
	else//若灰度级数小于16,则生成相应的灰度共生矩阵
	{
		dst.create(max_gray_level, max_gray_level, CV_32SC1);
		dst = Scalar::all(0);
		for (int i = 0; i < height; i++)
		{
			int*srcdata = src.ptr<int>(i);
			for (int j = 0; j < width - 1; j++)
			{
				int rows = srcdata[j];
				int cols = srcdata[j + 1];
				dst.ptr<int>(rows)[cols]++;
			}
		}
	}
}
//90度灰度共生矩阵
void getglcm_vertical(Mat& input, Mat& dst)
{
	Mat src = input;
	CV_Assert(1 == src.channels());
	src.convertTo(src, CV_32S);
	int height = src.rows;
	int width = src.cols;
	int max_gray_level = 0;
	for (int j = 0; j < height; j++)
	{
		int* srcdata = src.ptr<int>(j);
		for (int i = 0; i < width; i++)
		{
			if (srcdata[i] > max_gray_level)
			{
				max_gray_level = srcdata[i];
			}
		}
	}
	max_gray_level++;
	if (max_gray_level > 16)
	{
		for (int i = 0; i < height; i++)//将图像的灰度级缩小至16级,减小灰度共生矩阵的大小。
		{
			int*srcdata = src.ptr<int>(i);
			for (int j = 0; j < width; j++)
			{
				srcdata[j] = (int)srcdata[j] / gray_level;
			}
		}

		dst.create(gray_level, gray_level, CV_32SC1);
		dst = Scalar::all(0);
		for (int i = 0; i < height - 1; i++)
		{
			int*srcdata = src.ptr<int>(i);
			int*srcdata1 = src.ptr<int>(i + 1);
			for (int j = 0; j < width; j++)
			{
				int rows = srcdata[j];
				int cols = srcdata1[j];
				dst.ptr<int>(rows)[cols]++;
			}
		}
	}
	else
	{
		dst.create(max_gray_level, max_gray_level, CV_32SC1);
		dst = Scalar::all(0);
		for (int i = 0; i < height - 1; i++)
		{
			int*srcdata = src.ptr<int>(i);
			int*srcdata1 = src.ptr<int>(i + 1);
			for (int j = 0; j < width; j++)
			{
				int rows = srcdata[j];
				int cols = srcdata1[j];
				dst.ptr<int>(rows)[cols]++;
			}
		}
	}
}
//45度灰度共生矩阵
void getglcm_45(Mat& input, Mat& dst)
{
	Mat src = input;
	CV_Assert(1 == src.channels());
	src.convertTo(src, CV_32S);
	int height = src.rows;
	int width = src.cols;
	int max_gray_level = 0;
	for (int j = 0; j < height; j++)
	{
		int* srcdata = src.ptr<int>(j);
		for (int i = 0; i < width; i++)
		{
			if (srcdata[i] > max_gray_level)
			{
				max_gray_level = srcdata[i];
			}
		}
	}
	max_gray_level++;
	if (max_gray_level > 16)
	{
		for (int i = 0; i < height; i++)//将图像的灰度级缩小至16级,减小灰度共生矩阵的大小。
		{
			int*srcdata = src.ptr<int>(i);
			for (int j = 0; j < width; j++)
			{
				srcdata[j] = (int)srcdata[j] / gray_level;
			}
		}

		dst.create(gray_level, gray_level, CV_32SC1);
		dst = Scalar::all(0);
		for (int i = 0; i < height - 1; i++)
		{
			int*srcdata = src.ptr<int>(i);
			int*srcdata1 = src.ptr<int>(i + 1);
			for (int j = 0; j < width - 1; j++)
			{
				int rows = srcdata[j];
				int cols = srcdata1[j + 1];
				dst.ptr<int>(rows)[cols]++;
			}
		}
	}
	else
	{
		dst.create(max_gray_level, max_gray_level, CV_32SC1);
		dst = Scalar::all(0);
		for (int i = 0; i < height - 1; i++)
		{
			int*srcdata = src.ptr<int>(i);
			int*srcdata1 = src.ptr<int>(i + 1);
			for (int j = 0; j < width - 1; j++)
			{
				int rows = srcdata[j];
				int cols = srcdata1[j + 1];
				dst.ptr<int>(rows)[cols]++;
			}
		}
	}
}
//135度灰度共生矩阵
void getglcm_135(Mat& input, Mat& dst)
{
	Mat src = input;
	CV_Assert(1 == src.channels());
	src.convertTo(src, CV_32S);
	int height = src.rows;
	int width = src.cols;
	int max_gray_level = 0;
	for (int j = 0; j < height; j++)
	{
		int* srcdata = src.ptr<int>(j);
		for (int i = 0; i < width; i++)
		{
			if (srcdata[i] > max_gray_level)
			{
				max_gray_level = srcdata[i];
			}
		}
	}
	max_gray_level++;
	if (max_gray_level > 16)
	{
		for (int i = 0; i < height; i++)//将图像的灰度级缩小至16级,减小灰度共生矩阵的大小。
		{
			int*srcdata = src.ptr<int>(i);
			for (int j = 0; j < width; j++)
			{
				srcdata[j] = (int)srcdata[j] / gray_level;
			}
		}

		dst.create(gray_level, gray_level, CV_32SC1);
		dst = Scalar::all(0);
		for (int i = 0; i < height - 1; i++)
		{
			int*srcdata = src.ptr<int>(i);
			int*srcdata1 = src.ptr<int>(i + 1);
			for (int j = 1; j < width; j++)
			{
				int rows = srcdata[j];
				int cols = srcdata1[j - 1];
				dst.ptr<int>(rows)[cols]++;
			}
		}
	}
	else
	{
		dst.create(max_gray_level, max_gray_level, CV_32SC1);
		dst = Scalar::all(0);
		for (int i = 0; i < height - 1; i++)
		{
			int*srcdata = src.ptr<int>(i);
			int*srcdata1 = src.ptr<int>(i + 1);
			for (int j = 1; j < width; j++)
			{
				int rows = srcdata[j];
				int cols = srcdata1[j - 1];
				dst.ptr<int>(rows)[cols]++;
			}
		}
	}
}

//计算特征值
void feature_computer(Mat&src, double& Asm, double& Eng, double& Con, double& Idm)
{
	int height = src.rows;
	int width = src.cols;
	int total = 0;
	for (int i = 0; i < height; i++)
	{
		int*srcdata = src.ptr<int>(i);
		for (int j = 0; j < width; j++)
		{
			total += srcdata[j];//求图像所有像素的灰度值的和
		}
	}

	Mat copy;
	copy.create(height, width, CV_64FC1);
	for (int i = 0; i < height; i++)
	{
		int*srcdata = src.ptr<int>(i);
		double*copydata = copy.ptr<double>(i);
		for (int j = 0; j < width; j++)
		{
			copydata[j] = (double)srcdata[j] / (double)total;//图像每一个像素的的值除以像素总和
		}
	}

	for (int i = 0; i < height; i++)
	{
		double*srcdata = copy.ptr<double>(i);
		for (int j = 0; j < width; j++)
		{
			Asm += srcdata[j] * srcdata[j];//能量
			if (srcdata[j]>0)
				Eng -= srcdata[j] * log(srcdata[j]);//熵             
			Con += (double)(i - j)*(double)(i - j)*srcdata[j];//对比度
			Idm += srcdata[j] / (1 + (double)(i - j)*(double)(i - j));//逆差矩
		}
	}
}

int main()
{
	system("color 02");

	Mat dst_horison, dst_vertical, dst_45, dst_135;

	//读取源图像
	Mat src = imread("D:\\哀.jpg");
	if (src.empty())
	{
		return -1;
	}
	namedWindow("原图", WINDOW_NORMAL);
	imshow("原图", src);
	Mat src_gray;
	//src.create(src.size(), CV_8UC1);
	//src_gray = Scalar::all(0);
	cvtColor(src, src_gray, COLOR_BGR2GRAY);
	namedWindow("灰度图", WINDOW_NORMAL);
	imshow("灰度图", src_gray);

	getglcm_horison(src_gray, dst_horison);
	getglcm_vertical(src_gray, dst_vertical);
	getglcm_45(src_gray, dst_45);
	getglcm_135(src_gray, dst_135);

	double eng_horison = 0, con_horison = 0, idm_horison = 0, asm_horison = 0;
	feature_computer(dst_horison, asm_horison, eng_horison, con_horison, idm_horison);

	cout << "能量asm_horison:" << asm_horison << endl;
	cout << "熵eng_horison:" << eng_horison << endl;
	cout << "对比度con_horison:" << con_horison << endl;
	cout << "逆差矩idm_horison:" << idm_horison << endl;

	double eng_vertical = 0, con_vertical = 0, idm_vertical = 0, asm_vertical = 0;
	feature_computer(dst_vertical, asm_vertical, eng_vertical, con_vertical, idm_vertical);

	cout << "能量asm_vertical:" << asm_vertical << endl;
	cout << "熵eng_vertical:" << eng_vertical << endl;
	cout << "对比度con_vertical:" << con_vertical << endl;
	cout << "逆差矩idm_vertical:" << idm_vertical << endl;

	double eng_45 = 0, con_45 = 0, idm_45 = 0, asm_45 = 0;
	feature_computer(dst_45, asm_45, eng_45, con_45, idm_45);

	cout << "能量asm_45:" << asm_45 << endl;
	cout << "熵eng_45:" << eng_45 << endl;
	cout << "对比度con_45:" << con_45 << endl;
	cout << "逆差矩idm_45:" << idm_45 << endl;

	double eng_135 = 0, con_135 = 0, idm_135 = 0, asm_135 = 0;
	feature_computer(dst_135, asm_135, eng_135, con_135, idm_135);

	cout << "能量asm_135:" << asm_135 << endl;
	cout << "熵eng_135:" << eng_135 << endl;
	cout << "对比度con_135:" << con_135 << endl;
	cout << "逆差矩idm_135:" << idm_135 << endl;

	//写入文件
	/*FILE *fp;
	fp = fopen("灰度共生矩阵数据.txt", "a");
	if (fp != NULL)
		fprintf(fp, "\n水平:%f\t%f\t%f\t%f\n垂直:%f\t%f\t%f\t%f\n45:%f\t%f\t%f\t%f\n135:%f\t%f\t%f\t%f\n", asm_horison, eng_horison, con_horison, idm_horison,asm_vertical, eng_vertical, con_vertical, idm_vertical, asm_45, eng_45, con_45, idm_45, asm_135, eng_135, con_135, idm_135);
	fclose(fp);*/


	waitKey(0);
	return 0;
}

原图:

结果:

  • 1
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值