glcm灰度共生矩阵即特征值的提取

共生矩阵用两个位置的象素的联合概率密度来定义,它不仅反映亮度的分布特性,也反映具有同样亮度或接近亮度的象素之间的位置分布特性,是有关图象亮度变化的二阶统计特征。它是定义一组纹理特征的基础。

一幅图象的灰度共生矩阵能反映出图象灰度关于方向、相邻间隔、变化幅度的综合信息,它是分析图象的局部模式和它们排列规则的基础。

  设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,θ)。

纹理特征提取的一种有效方法是以灰度级的空间相关矩阵即共生矩阵为基础的,因为图像中相距(Δx,Δy)的两个灰度像素同时出现的联合频率分布可以用灰度共生矩阵来表示。若将图像的灰度级定为N级,那么共生矩阵为N×N矩阵,可表示为M(Δx,Δy)(h,k),其中位于(h,k)的元素mhk的值表示一个灰度为h而另一个灰度为k的两个相距为(Δx,Δy)的像素对出现的次数。
  对粗纹理的区域,其灰度共生矩阵的mhk值较集中于主对角线附近。因为对于粗纹理,像素对趋于具有相同的灰度。而对于细纹理的区域,其灰度共生矩阵中的mhk值则散布在各处。

为了能更直观地以共生矩阵描述纹理状况,从共生矩阵导出一些反映矩阵状况的参数,典型的有以下几种:

(1)能量: 是灰度共生矩阵元素值的平方和,所以也称能量,反映了图像灰度分布均匀程度和纹理粗细度。如果共生矩阵的所有值均相等,则ASM值小;相反,如果其中一些值大而其它值小,则ASM值大。当共生矩阵中元素集中分布时,此时ASM值大。ASM值大表明一种较均一和规则变化的纹理模式。

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

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

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

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

其它参数:

中值

协方差

同质性/逆差距

反差

差异性



二阶距

自相关

当图像的局部有较小的方差时,则灰度值占有支配地位,当图像的局部有较大的方差时,则纹理占有支配地位。纹理是和局部灰度及其空间组织相联系的,纹理在识别感兴趣的目标和地区中有着非常重要的作用。

灰度共生矩阵表示了灰度的空间依赖性,它表示了在一种纹理模式下的像素灰度的空间关系。它的弱点是没有完全抓住局部灰度的图形特点,因此对于较大的局部,此方法的效果不太理想。灰度共生矩阵为方阵,维数等于图像的灰度级。灰度共生矩阵中的元素(i,j)的值表示了在图像中其中一个像素的灰度值为i,另一个像素的灰度值为j,并且相邻距离为d,方向为A的这样两个像素出现的次数。在实际应用中A一般选择为0°、45°、90°、135°。一般来说灰度图像的灰度级为256,在计算由灰度共生矩阵推导出的纹理特征时,要求图像的灰度级远小于256,主要是因为矩阵维数较大而窗口的尺寸较小则灰度共生矩阵不能很好表示纹理,如要能够很好表示纹理则要求窗口尺寸较大,这样使计算量大大增加,而且当窗口尺寸较大时对于每类的边界区域误识率较大。所以在计算灰度共生矩阵之前需要对图像进行直方图规定化,以减小图像的灰度级,一般规定化后的图像的灰度级为8或16。由灰度共生矩阵能够导出许多纹理特征,本文计算了14种灰度共生矩阵特征,分别为纹理二阶距、纹理熵、纹理对比度、纹理均匀性、纹理相关、逆差分矩、最大概率、纹理方差、共生和均值、共生和方差、共生和熵、共生差均值、共生差方差、共生差熵。

由灰度共生矩阵能够导出许多纹理特征,计算了14种灰度共生矩阵特征,分别为纹理二阶距、纹理熵、纹理对比度、纹理均匀性、纹理相关、逆差分矩、最大概率、纹理方差、共生和均值、共生和方差、共生和熵、共生差均值、共生差方差、共生差熵。

目前,人们对遥感影像上的纹理特征的含义理解不尽相同,纹理有时被称为结构、影纹和纹形等。Pickett认为纹理为保持一定的特征重复性并且间隔规律可以任意安排的空间结构。HawKins认为纹理具有三大标志:某种局部序列性不断重复、非随机排列和纹理区域内大致为均匀的统一体。LiWang和D. C. He认为,纹理是纹理基元组成的,纹理基元被认为是表现纹理特征的最小单元,是一个像元在

其周围8个方向上的特征反应。纹理特征有时是明显的,以某种基本图形在某一地区有规律的周期性出现,例如:大面积森林覆盖地区的影像构成的纹理为斑点状,沙漠地区的影像构成的纹理为链状、新月状等;而有时纹理特征是不明显的、隐晦的,具有不稳定性。一般来说,前者纹理比较均一,后者纹理比较复杂。

纹理作为一种区域特征,是对于图像各像元之间空间分布的一种描述。由于纹理能充分利用图像信息,无论从理论上或常识出发它都可以成为描述与识别图像的重要依据,与其他图像特征相比,它能更好地兼顾图像宏观性质与细微结构两个方面,因此纹理成为目标识别需要提取的重要特征。提取纹理特征的方法很多,如基于局部统计特性的特征、基于随机场模型的特征、基于空间频率的特征、分形特征等,其中,应用最广泛的是基于灰值共生矩阵的特征。


我这里是已以下方式,来求得灰度共生矩阵,其间距为1

glcm灰度共生矩阵即特征值的提取_第1张图片


也将灰度级进行了等概率量化,减小维度。

代码如下:

// c++_glcm.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include 
#include "glcm_make.h"
#include "defautVal.h"
#include "feature_extra.h"

using namespace cv;
using namespace std;




int _tmain(int argc, _TCHAR* argv[])
{

	Mat src = imread("C:\\Users\\sony\\Desktop\\a1_001.jpg",0); 

	/*imshow("1", src);*/

	normalize(src, src, 0.0, 255.0, NORM_MINMAX);

	/*imshow("2",src);
	waitKey(0);*/
	
	Mat img = src.clone();

	Mat glcm(grayScal, grayScal, CV_32FC1, Scalar(0.0));

	

	//0度的灰度共生矩阵
	glcm_make(glcm, img);

	cout << glcm << endl;

	
	feature_extra(glcm);



	return 0;
}


//defautVal.h

#define grayScal  16

//double contrast;              //对比度
//double correlation;           //纹理相关性
//double energy;                //能量
//double homogeneity;           //一致性
//double entropy;               //熵

//feature_extra.h
#include 

using namespace std;
using namespace cv;




void feature_extra(Mat& glcm);

//glcm_make.h

#include 

using namespace cv;
using namespace std;


void glcm_make(Mat& glcm, Mat& image);


//feature_extra.cpp

#include "stdafx.h"
#include "glcm_make.h"
#include "feature_extra.h"
#include 

double contrast = 0;              //对比度
double correlation = 0;           //纹理相关性
double energy = 0;                //能量
double homogeneity = 0;           //一致性
double entropy = 0;               //熵


void feature_extra(Mat& glcm)
{
	//灰度共生矩阵归一化
	double sum = 0.0;

	for (int i = 0; i < glcm.rows - 1; ++i)
	{
		for (int j = 0; j < glcm.cols - 1; ++j)
		{
			sum += glcm.at(i,j);
		}
	}

	Mat glcm1(glcm.size(), CV_32FC1, Scalar(0.0));

	for (int i = 0; i < glcm1.rows - 1; ++i)
	{
		for (int j = 0; j < glcm1.cols - 1; ++j)
		{
			 
			
			glcm1.at(i,j) = glcm.at(i,j)/sum;
		}
	}


	cout << glcm1 << endl;
	

	double m = 0;
	double k = 0;
	double ui = 0;
	double uj = 0;
	double si_2 = 0;
	double sj_2 = 0;
	

	for (int i = 0; i < glcm1.rows - 1; ++i)
	{
		for (int j = 0; j < glcm1.cols - 1; ++j)
		{
			m = glcm1.at(i,j);
			
			//能量
			energy += m*m;

			

			//对比度
			contrast += (i-j)*(i-j)*m;

			//  'Homogeneity'  即齐次性(同质性),返回的值反映了GLCM中元素相对于GLCM对角线的分布的紧密度
			homogeneity += m*(1 + abs(i - j));

			//自相关的一些参数
			ui += i*m;
			uj += j*m;

		}
	}
	m = 0;

	for (int i = 0; i < glcm1.rows - 1; ++i)
	{
		for (int j = 0; j < glcm1.cols - 1; ++j)
		{
			m = glcm1.at(i,j);
			si_2 += m*(i - ui)*(i - ui);
			sj_2 += m*(j - ui)*(j - ui);
		}
	}
	m = 0;

	for (int i = 0; i < glcm1.rows - 1; ++i)
	{
		for (int j = 0; j < glcm1.cols - 1; ++j)
		{
			m = glcm1.at(i,j);
			//自相关
			correlation += (i*j*m - ui*uj)/sqrt(si_2)*sqrt(sj_2);
		}
	}
	m = 0;


	for (int i = 0; i < glcm1.rows - 1; ++i)
		for (int j = 0; j < glcm1.cols - 1; ++j)
		{

			m = glcm1.at(i,j);
			//熵
			if (m == 0)
			continue;
			
			entropy += m*log10(1/m);
		}


	cout << "能量为: " <

//glcm_make.cpp

#include "stdafx.h"
#include "glcm_make.h"
#include "defautVal.h"


int numbers_0 = 0;
int numbers_45 = 0;
int numbers_90 = 0;
int numbers_135 = 0;

//得到0度,灰度对的个数
void pairsNumber(int grayVal1, int grayVal2,  Mat image)
{
	
	for (int i = 1; i < image.rows - 2; ++i)
	{
		for(int j = 1; j < image.cols - 2; ++j)
		{
			if ( (image.at(i,j) == grayVal1) && (image.at(i + 1, j) == grayVal2) )
			{
				numbers_0++;
			}
			if ( (image.at(i,j) == grayVal1) && (image.at(i + 1, j - 1) == grayVal2) )
			{
				numbers_45++;
			}
			if ( (image.at(i,j) == grayVal1) && (image.at(i , j - 1) == grayVal2) )
			{
				numbers_90++;
			}
			if ( (image.at(i,j) == grayVal1) && (image.at(i - 1 , j - 1) == grayVal2) )
			{
				numbers_135++;
			}
		}
	}
	
}




void glcm_make(Mat& glcm, Mat& image)
{


	//把图片灰度级0到255等值量化为0到15
	for (int i = 0 ; i < image.rows; ++i)
	{
		for (int j = 0; j < image.cols; ++j)
		{
			image.at(i, j) = image.at(i, j)/grayScal;
		}
	}

	//表示灰度级16
	for (int i = 0; i < glcm.rows - 1; ++i)
	{
		for(int j = 0; j < glcm.cols - 1; ++j)
		{
			pairsNumber(i, j, image);
			glcm.at(i,j) = numbers_0;
			numbers_0 = 0;
		}
	}
}



你可能感兴趣的:(opencv)