灰度共生矩阵及其统计量使用

      网上关于灰度共生矩阵及其统计量的介绍有很多,这里就不再赘述了。这篇博客https://blog.csdn.net/guanyuqiu/article/details/53117507,介绍的还算清楚。本篇博客主要讲如何使用灰度共生矩阵统计量。Haralick等人定义了14个纹理分析的灰度共生矩阵特征参数。Ulaby等人研究发现:在基GLCM的14个纹理特征中,仅有4个特征是不相关的,这4个特征即便于计算又能给出较高的分类精度,一般采用这四种特征Contrast、Correlation、Energy、Homogemeity。

1.纹理特征值的计算

  • a. 'Contrast' : 对比度。返回整幅图像中像素和它相邻像素之间的亮度反差。取值范围:[0,(GLCM行数-1)^2]。灰度一致的图 像,对比度为0。
  • b. 'Correlation' : 相关。返回整幅图像中像素与其相邻像素是如何相关的度量值。取值范围:[-1,1]。灰度一致的图像,相关性为NaN。
  • c. 'Energy' : 能量。返回GLCM中元素的平方和。取值范围:[0 1]。灰度一致的图像能量为1。
  • d. 'Homogemeity' : 同质性。返回度量GLCM中元素的分布到对角线紧密程度。取值范围:[0 1]。对角矩阵的同质性为1。

     取步长为1,对0,45,90,135方向求统计量。对上诉指标进行归一化(特征),可以送到神经网络或支持向量机进行相关学习(分类,识别等任务)。经常看到分类纺织品、木材纹路等。提取纹理特征时主要存在两方面的缺陷:1.缺乏移动不变性,输入信号很小的位移会造成能量分布的很大变化。2. 较差的方向选择性,图像的微小改变会造成识别效果的降低。

 2.纹理特征影像的生成

       其主要思想:用5*5或7*7滑动窗口遍历图像,计算窗口内的对比度、相关性、能量、同质性值,然后替换该像素的像素值。生成的纹理特征影像图可以认识是边缘图。下图是5*5滑动窗口,步长为1,0方向生成的结果图。论文“基于灰度共生矩阵提取纹理特征图像的研究”冯建辉,说纹理特征影像可以提高分类效果,但是每个小窗口都要计算灰度共生矩阵,然后计算统计量。计算过于复杂,耗费时间。目前有很多种方法提高分类效果,所以这种方法目前并不常用了。

        

                                    原图                                                                                           对比度


         

                                  相关性                                                                                          能量

        我学习灰度共生矩阵,主要想计算图像复杂度,应用到其他图像处理其他方面。但是对比度、相关、能量、同质之间的权重不同很合理的定义。映射到的灰度级不同,会导致对比度有较大的变化,所以在和其他统计量加权求和时,最好归一化。 只要复杂度,与目测结果一致就可。比如a图看着比b图复杂,a图的复杂度比b图的复杂度高即可。

附件:

#include<algorithm>
#include <opencv2/opencv.hpp>
#include <vector>
using namespace std;
using namespace cv;

 
// 0°灰度共生矩阵  
void getGLCM0(Mat& src, Mat& dst, int gray_level)// 0度灰度共生矩阵  
{
	CV_Assert(1 == src.channels());

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

	dst.create(gray_level, gray_level, CV_32SC1);
	dst = Scalar::all(0);
	for (int i = 0; i < height; i++)
	{
	uchar  *srcdata = src.ptr<uchar>(i);
		 
		for (int j = 0; j < width - 1; j++)
		{
			// 同样的像素对,水平相邻  
			int rows = srcdata[j] * gray_level/256;
			int cols = srcdata[j + 1] * gray_level / 256;
			dst.at<int>(rows, cols)++;
			
		}
	}
}

// 90°灰度共生矩阵  
void getGLCM90(Mat& src, Mat& dst, int gray_level)
{
	CV_Assert(1 == src.channels());

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

	dst = Mat(gray_level, gray_level, CV_32SC1, Scalar(0));

	for (int i = 0; i < height - 1; i++)
	{
		uchar*srcdata = src.ptr<uchar>(i)  ;
		uchar*srcdata1 = src.ptr<uchar>(i + 1);
		for (int j = 0; j < width; j++)
		{
			// 同样的像素对,垂直相邻  
			int rows = srcdata[j] / 256;
			int cols = srcdata1[j] / 256;
			dst.ptr<int>(rows)[cols]++;
		}
	}
}

// 45°灰度共生矩阵  
void getGLCM45(Mat& src, Mat& dst, int gray_level)
{
	CV_Assert(1 == src.channels());

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

	dst = Mat(gray_level, gray_level, CV_32SC1, Scalar(0));

	for (int i = 0; i < height - 1; i++)
	{
		uchar*srcdata = src.ptr<uchar>(i);
		uchar*srcdata1 = src.ptr<uchar>(i + 1);
		for (int j = 0; j < width - 1; j++)
		{
			// 同样的像素对,45°相邻  
			int rows = srcdata[j] / 256;
			int cols = srcdata1[j + 1] / 256;
			dst.ptr<int>(rows)[cols]++;
		}
	}
}

// 135°灰度共生矩阵  
void getGLCM135(Mat& src, Mat& dst, int gray_level)
{
	CV_Assert(1 == src.channels());

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

	dst = Mat(gray_level, gray_level, CV_32SC1, Scalar(0));

	for (int i = 0; i < height - 1; i++)
	{
		uchar*srcdata = src.ptr<uchar>(i);
		uchar*srcdata1 = src.ptr<uchar>(i + 1);
		for (int j = 1; j < width; j++)
		{
			// 同样的像素对,135°相邻  
			int rows = srcdata[j] / 256;
			int cols = srcdata1[j - 1] / 256;
			dst.ptr<int>(rows)[cols]++;
		}
	}

}

// 计算特征值  
void featureGLCM(Mat&src, double& Asm, double& Ent, double& Con, double& Idm,double &Res)
{

	CV_Assert(src.channels() == 1);

	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 mean;
	mean.create(height, width, CV_64FC1);
	float u1=0., u2=0.;
	float imean = 0, jmean = 0;
	float ivar = 0, jvar = 0;

	for (int i = 0; i < height; i++)
	{
		int*srcdata = src.ptr<int>(i);
		double*copydata = mean.ptr<double>(i);
		for (int j = 0; j < width; j++)
		{
			copydata[j] = (double)srcdata[j] / (double)total;
			imean += copydata[j] * i;
			jmean += copydata[j] * j;	 
		}
	}
	 

	for (int i = 0; i < height; i++)
	{
		double*srcdata = mean.ptr<double>(i);
		for (int j = 0; j < width; j++)
		{
			// 能量  
			Asm += srcdata[j] * srcdata[j];

			// 熵(Entropy)   
			if (srcdata[j]>0)
				Ent -= srcdata[j] * log(srcdata[j]);

			// 对比度  
			Con += ((double)(i - j)*(double)(i - j)*srcdata[j]);

			// 逆差矩  同质
			Idm += srcdata[j] / (1 + (double)(i - j)*(double)(i - j));

			//相关性
			ivar += srcdata[j] * (i - imean)*(i - imean);
			jvar += srcdata[j] * (j - jmean)*(j - jmean);
		}
	}

	for (int i = 0; i < height; i++)
	{
		double*srcdata = mean.ptr<double>(i);
		for (int j = 0; j < width; j++)
		{
			Res += (srcdata[j] *(i - imean)*(j - jmean)) / sqrt(ivar*jvar);
			 
		}
	}

}

  
void TexturalMat(Mat & src, Mat &dst, int size,int angle,int level)
{
	dst=Mat(src.size(), CV_32SC1, Scalar(0));
	Mat srcROI = Mat(size, size, CV_32SC1, Scalar(0));
	 
	Mat ROI, ROIdst;
	int basis = size / 2;
	for (int i = 0; i < src.size().height-size-1; i++)
	{
		for (int j = 0; j < src.size().width-size-1; j++)
		{
			double Asm = 0.0, Ent = 0.0, Con = 0.0, Idm = 0.0, Res = 0.0;
			if (i + size <= src.size().width&& j + size <= src.size().height)
			{
				Mat ROI = src(Rect(j, i, size, size));
				switch (angle)
				{
				case 0:	getGLCM0(ROI, ROIdst, level);
						break;
				case 45:getGLCM45(ROI, ROIdst, level);
						break;
				case 90:getGLCM90(ROI, ROIdst, level);
						break;
				case 135:getGLCM135(ROI, ROIdst, level);
						break;

				}
				featureGLCM(ROIdst, Asm, Ent, Con, Idm, Res);
				dst.ptr<int>(i + basis)[j + basis] = Asm*255  ;
			}
		}
	}
	 
}



#include<opencv/cxcore.h>
void main()
{
	Mat src = imread("lena.jpg",1);
	Mat gray;
	cvtColor(src,gray,CV_RGB2GRAY);
	
	Mat dst;//纹理特征影像图
	//5*5  size
	// 0-255  映射到0-8
	TexturalMat(gray, dst, 5, 0, 8);
	 imshow("dst",dst*255);
 
	getGLCM0(gray, dst, 8);
	double Asm=0.0,  Ent=0.0,  Con=0.0, Idm=0.0,Res=0.0;
	featureGLCM(dst, Asm, Ent, Con, Idm,Res);
	cout << "Asm:" << Asm << "\n" << "Ent:" << Ent << "\n" << "Con: " << Con << "\n" << "Idm: " << Idm << "\n" << "Res: " << Res << endl;
	waitKey(0);
}





/*   matlab   灰度共生矩阵计算及其统计量
I=imread('lena.jpg');
gray=rgb2gray(I)
GLCM2 = graycomatrix(gray,'NumLevels',16,'Offset',[0,2;-2,2;-2,0;-2,-2]);
stats = graycoprops(GLCM2,{'all'})
 


I=imread('lena.jpg');
gray=rgb2gray(I);
GS=graycomatrix(gray,'NumLevels',256);%水平位置算子计算共生矩阵
GSn=GS/sum(GS(:));%归一化矩阵
stats=graycoprops(GS,'all');%共生矩阵的描述子
maxProbability=max(GSn(:));%最大概率
corr=stats.Correlation;%相关
contrast=stats.Contrast;%对比度
energy=stats.Energy;%能量
hom=stats.Homogeneity;%同质
for J=1:size(GSn,1)
sumcols(J)=sum(-GSn(J,1:end).*log2(GSn(J,1:end)+eps));
end
entropy=sum(sumcols);%熵
Y=[maxProbability,corr,contrast,energy,hom,entropy];

*/


  • 7
    点赞
  • 75
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值