wap网站生成系统,企业网站建设哪家正规,教程,网站备案证书本文以实验为导向#xff0c;使用vgg16GLCM实现一场精彩的新冠肺炎的分类识别#xff0c;并且对比不加GLCM后的效果。在这之前#xff0c;我们需要弄明白一些前缀知识和概念问题#xff1a; GLCM#xff08;Gray-Level Co-occurrence Matrix#xff09;#xff0c;中文称… 本文以实验为导向使用vgg16GLCM实现一场精彩的新冠肺炎的分类识别并且对比不加GLCM后的效果。在这之前我们需要弄明白一些前缀知识和概念问题 GLCMGray-Level Co-occurrence Matrix中文称为灰度共生矩阵是一种用于图像纹理特征提取的统计方法。它是由Tamura等人在1978年首次提出的用于描述图像中灰度级别之间的相互关系。GLCM在图像处理和计算机视觉领域中广泛应用特别是在纹理分析、目标识别和图像分类等任务中作为单独特征提取的一环并与CNN结合达到非凡的效果。 灰度级别是指图像中每个像素的灰度值的取值范围。在数字图像中每个像素的灰度值表示了该像素在灰度图像中的亮度程度。灰度级别通常用整数表示其取值范围取决于图像的位深度。在一个8位灰度图像中灰度级别的范围为0到255其中0表示最暗的黑色255表示最亮的白色。这意味着该图像中每个像素的灰度值可以取256个不同的值这些值之间以等间距分布。对于一个黑白图像每个像素只有一个灰度值而对于彩色图像每个像素则有多个通道每个通道都有自己的灰度级别范围。 一、GLCM算法原理
1.1 GLCM计算原理 共生矩阵用两个位置的像素的联合概率密度来定义它不仅反映亮度的分布特性也反映具有同样亮度或接近亮度的象素之间的位置分布特性是有关图象亮度变化的二阶统计特征。它是定义一组纹理特征的基础。一幅图象的灰度共生矩阵能反映出图象灰度关于方向、相邻间隔、变化幅度的综合信息它是分析图象的局部模式和它们排列规则的基础。
设为一幅二维数字图像其大小为M × N灰度级别为,则满足一定空间关系的灰度共生矩阵为:
(x1,y1),(x2,y2)∈M×Nf(x1,y1)i, f(x2,y2)j 其中表示集合x中的元素个数显然P为Ng×Ng的矩阵若(x1,y1)与(x2,y2)间距离为d,两者与坐标横轴的夹角为θ则可以得到各种间距及角度的灰度共生矩阵 i为f(x,y)中灰度值为i的元素位置列表j为f(x,y)中灰度值为j的元素位置列表d为x1,y1x2,y2之间的距离θ为x1,y1x2,y2之间连线与横坐标的夹角
最后我们遍历i,j列表找出和(d,θ)所描述的空间位置一样的一对位置x1,y1)和x2,y2)有多少个从而得到P(i,j的值。也就是说这其实不是最终形态的灰度共生矩阵真正的灰度共生矩阵应该是一个大小和一样的但它可以从中得到
假设我们令d1θ0°, 以Pxy10°点为例
P1110° 1 即GLCM11说明左侧原图只有一对灰度为1的像素水平相邻。P1210° 2 即GLCM12说明左侧原图有两对灰度为1和2的像素水平相邻。 根据不同的d, θ组合其实我们可以得到不同纹理的灰度共生矩阵在GLCM灰度共生矩阵中不同的距离和角度意味着在图像中计算纹理特征时考虑的像素之间的相对位置和方向从而影响到后续纹理特征的提取。 距离Distance 距离指的是在GLCM中计算像素对共现频率时像素之间的间隔距离。通常距离会影响纹理特征的大小和尺度。较小的距离可以捕捉图像中更细小的纹理细节而较大的距离则能够考虑更广阔的像素关系提取出更大范围的纹理特征。选择合适的距离取决于应用场景和所关注的纹理细节大小。 角度Angle 角度是指在GLCM中计算像素对共现频率时相对于水平方向的偏转角度。常用的角度通常是0°、45°、90°和135°。不同的角度能够捕捉图像中不同方向的纹理特征。例如0°角度对应着水平方向的纹理能够检测到图像中水平的纹理结构45°和135°角度对应着对角线方向的纹理能够检测到图像中的对角线纹理结构90°角度对应着垂直方向的纹理能够检测到图像中垂直的纹理结构。因此选择不同的角度可以从不同方向上提取纹理信息。
在实际应用中通常会对多个距离和角度进行计算得到多个GLCM然后结合这些GLCM来计算一系列的纹理特征如对比度、能量、相关性等。通过考虑不同的距离和角度可以全面地捕捉图像中的纹理信息使得GLCM在纹理分析、图像分类和目标识别等任务中发挥出更强大的能力。 1.2 GLCM纹理特征提取原理 纹理特征提取的一种有效方法是以灰度级的空间相关矩阵即共生矩阵为基础的,因为图像中相距(ΔxΔy)的两个灰度像素同时出现的联合频率分布可以用灰度共生矩阵来表示。若将图像的灰度级定为N级那么共生矩阵为N×N矩阵可表示为M(ΔxΔy)(h,k)其中位于(h,k)的元素m(h,k)的值表示一个灰度为h而另一个灰度为k的两个相距为(ΔxΔy)的像素对出现的次数。 对粗纹理的区域其灰度共生矩阵的m(h,k)值较集中于主对角线附近。因为对于粗纹理像素对趋于具有相同的灰度。而对于细纹理的区域其灰度共生矩阵中的mhk值则散布在各处。 为了能更直观地以共生矩阵描述纹理状况从共生矩阵导出一些反映矩阵状况的参数典型的有以下几种:1能量是灰度共生矩阵元素值的平方和所以也称能量反映了图像灰度分布均匀程度和纹理粗细度。如果共生矩阵的所有值均相等则ASM值小相反如果其中一些值大而其它值小则ASM值大。当共生矩阵中元素集中分布时此时ASM值大。ASM值大表明一种较均一和规则变化的纹理模式。2对比度反映了图像的清晰度和纹理沟纹深浅的程度。纹理沟纹越深其对比度越大视觉效果越清晰反之对比度小则沟纹浅效果模糊。灰度差即对比度大的象素对越多这个值越大。灰度公生矩阵中远离对角线的元素值越大CON越大。3相关它度量空间灰度共生矩阵元素在行或列方向上的相似程度因此相关值大小反映了图像中局部灰度相关性。当矩阵元素值均匀相等时相关值就大相反如果矩阵像元值相差很大则相关值小。如果图像中有水平方向纹理则水平方向矩阵的COR大于其余矩阵的COR值。4熵是图像所具有的信息量的度量纹理信息也属于图像的信息是一个随机性的度量当共生矩阵中所有元素有最大的随机性、空间共生矩阵中所有值几乎相等时共生矩阵中元素分散分布时熵较大。它表示了图像中纹理的非均匀程度或复杂程度。5逆差距反映图像纹理的同质性度量图像纹理局部变化的多少。其值大则说明图像纹理的不同区域间缺少变化局部非常均匀。
1.3 GLCM代码实践
#import package
from skimage.feature import graycomatrix, graycoprops
import numpy as np
import pandas as pd#Feature Extraction with GLCM
def feature_extractor(images):image_dataset pd.DataFrame()for image in images:df pd.DataFrame()#greycomatrix(image, distances, angles, levels256, symmetricFalse, normedFalse)#distances - List of pixel pair distance offsets.#angles - List of pixel pair angles in radians.#5 configuration for the grey-level co-occurrence matrix calculationdists [[1],[3],[5],[3],[3]]angles [[0],[0],[0],[np.pi/4],[np.pi/2]]for n ,(dist, angle) in enumerate(zip(dists, angles)):GLCM graycomatrix(image, dist, angle)GLCM_Energy graycoprops(GLCM, energy)[0]df[Energystr(n)] GLCM_EnergyGLCM_corr graycoprops(GLCM, correlation)[0]df[Corrstr(n)] GLCM_corrGLCM_diss graycoprops(GLCM, dissimilarity)[0]df[Diss_simstr(n)] GLCM_dissGLCM_hom graycoprops(GLCM, homogeneity)[0]df[Homogenstr(n)] GLCM_homGLCM_contr graycoprops(GLCM, contrast)[0]df[Contraststr(n)] GLCM_contrimage_dataset image_dataset.append(df)return image_dataset 看懂上面的理论知识相信这份code已经不需要解释了。
二、GLCMCNN网络构成
2.1 数据集构成
2.2.2 CNN网络训练数据集
train_images torch.tensor(images_train,dtypetorch.float32).unsqueeze(1)#Convert the shape of the training set images to [*, 1, 256, 256].
train_labels torch.tensor(labels,dtypetorch.int64)
val_images torch.tensor(images_val,dtypetorch.float32).unsqueeze(1)#Convert the shape of the validation set images to [*, 1, 256, 256].
val_labels torch.tensor(labels_val,dtypetorch.int64)
test_images torch.tensor(images_test,dtypetorch.float32).unsqueeze(1)#Convert the shape of the test set images to [*, 1, 256, 256].
test_labels torch.tensor(labels_test,dtypetorch.int64)
2.2.3 GLCM网络训练数据集
NOTEimages_train、images_val、images_test是numpy数组形式的数据集用于提取GLCM特征。
train_extr_features feature_extractor(images_train)
val_extr_features feature_extractor(images_val)
test_extr_features feature_extractor(images_test)
NOTE 提取完特征后变成torch.tensor类型用于CNN网络训练。
trainFeatures np.array(train_extr_features)
train_features torch.tensor(trainFeatures,dtypetorch.float32)
validFeatures np.array(val_extr_features)
valid_features torch.tensor(validFeatures,dtypetorch.float32)
testFeatures np.array(test_extr_features)
test_features torch.tensor(testFeatures,dtypetorch.float32)
2.2 GLCM_CNN网络结构 class GLCM_CNN(nn.Module):def __init__(self):super(GLCM_CNN,self).__init__()# 构建VGG16网络self.img_output nn.Sequential(#input is (*,1,256,256)#nn.Conv2d(in_channels1,out_channels64,kernel_size3,stride1,paddingsame),nn.Conv2d(in_channels1,out_channels64,kernel_size3,stride1,padding(1, 1)),# nn.BatchNorm2d(64),nn.ReLU(inplaceTrue),# nn.Conv2d(in_channels64,out_channels64,kernel_size3,stride1,paddingsame),nn.Conv2d(in_channels64,out_channels64,kernel_size3,stride1,padding(1, 1)),# nn.BatchNorm2d(64),nn.ReLU(inplaceTrue),nn.MaxPool2d(kernel_size2,stride2),# input is (*,64,128,128)# nn.Conv2d(in_channels64, out_channels128, kernel_size3, stride1, paddingsame),nn.Conv2d(in_channels64, out_channels128, kernel_size3, stride1, padding(1, 1)),# nn.BatchNorm2d(128),nn.ReLU(inplaceTrue),# nn.Conv2d(in_channels128, out_channels128, kernel_size3, stride1, paddingsame),nn.Conv2d(in_channels128, out_channels128, kernel_size3, stride1, padding(1, 1)),# nn.BatchNorm2d(128),nn.ReLU(inplaceTrue),nn.MaxPool2d(kernel_size2, stride2),# input is (*,128,64,64)# nn.Conv2d(in_channels128, out_channels256, kernel_size3, stride1, paddingsame),nn.Conv2d(in_channels128, out_channels256, kernel_size3, stride1, padding(1, 1)),# nn.BatchNorm2d(256),nn.ReLU(inplaceTrue),# nn.Conv2d(in_channels256, out_channels256, kernel_size3, stride1, paddingsame),nn.Conv2d(in_channels256, out_channels256, kernel_size3, stride1, padding(1, 1)),# nn.BatchNorm2d(256),nn.ReLU(inplaceTrue),# nn.Conv2d(in_channels256, out_channels256, kernel_size3, stride1, paddingsame),nn.Conv2d(in_channels256, out_channels256, kernel_size3, stride1, padding(1, 1)),# nn.BatchNorm2d(256),nn.ReLU(inplaceTrue),nn.MaxPool2d(kernel_size2,stride2),# input is (*,256,32,32)# nn.Conv2d(in_channels256, out_channels512, kernel_size3, stride1, paddingsame),nn.Conv2d(in_channels256, out_channels512, kernel_size3, stride1, padding(1, 1)),# nn.BatchNorm2d(512),nn.ReLU(inplaceTrue),# nn.Conv2d(in_channels512, out_channels512, kernel_size3, stride1, paddingsame),nn.Conv2d(in_channels512, out_channels512, kernel_size3, stride1, padding(1, 1)),# nn.BatchNorm2d(512),nn.ReLU(inplaceTrue),# nn.Conv2d(in_channels512, out_channels512, kernel_size3, stride1, paddingsame),nn.Conv2d(in_channels512, out_channels512, kernel_size3, stride1, padding(1, 1)),# nn.BatchNorm2d(512),nn.ReLU(inplaceTrue),nn.MaxPool2d(kernel_size2, stride2),# input is (*,512,16,16)# nn.Conv2d(in_channels512, out_channels512, kernel_size3, stride1, paddingsame),nn.Conv2d(in_channels512, out_channels512, kernel_size3, stride1, padding(1, 1)),# nn.BatchNorm2d(512),nn.ReLU(inplaceTrue),# nn.Conv2d(in_channels512, out_channels512, kernel_size3, stride1, paddingsame),nn.Conv2d(in_channels512, out_channels512, kernel_size3, stride1, padding(1, 1)),# nn.BatchNorm2d(512),nn.ReLU(inplaceTrue),# nn.Conv2d(in_channels512, out_channels512, kernel_size3, stride1, paddingsame),nn.Conv2d(in_channels512, out_channels512, kernel_size3, stride1, padding(1, 1)),# nn.BatchNorm2d(512),nn.ReLU(inplaceTrue),nn.MaxPool2d(kernel_size2, stride2),# input is (*,512,8,8)nn.AdaptiveAvgPool2d((7, 7)),nn.Flatten(),nn.Linear(in_features512*7*7,out_features4096),nn.ReLU(inplaceTrue),nn.Dropout(0.5),nn.Linear(in_features4096,out_features4096),nn.ReLU(inplaceTrue),nn.Dropout(0.5),nn.Linear(in_features4096,out_features8))# 构建GLCM特征提取分类网络self.feature_output nn.Sequential(nn.Linear(in_features25,out_features8),nn.ReLU(),nn.Linear(in_features8,out_features4),# nn.ReLU(),)# 构建整合网络self.model nn.Sequential(nn.Linear(in_features12,out_features8),nn.ReLU(),nn.Linear(in_features8,out_features2),)# 前向传播def forward(self,train_extr_features,imgs):img_output self.img_output(imgs)feature self.feature_output(train_extr_features)concat torch.cat([feature,img_output],dim1)return self.model(concat)self.img_output是一个VGG16的CNN网络用于提取原数据的特征进行前向传播得到各个神经元的激活值也就是 原始数据的各个特征值。self.feature_output是一个线性分类器是用GLCM从源数据中提取的特征是一个大小为25的向量通过1.3代码可知然后投入线性分类器做与上述一样的操作。最后将两者得到的特征值进行合并传入最后一个融合网络得到输出层最终的预测结果用于反向传播权重更新等进行网络训练。
三、实验结果
3.1 GLCMCNN
3.1.1 前10个epoch 3.1.2 后10个epoch 3.2 CNN
哎呀实验的时候忘记加验证集了反正最后结果是valid Accuracy93.012几来着哈哈尴尬了这就写到这里才发现,,ԾㅂԾ,,