GLCM(Gray-level co-occurrence matrix)也就是灰度共生矩阵,是在处理纹理图像时候常用的手段。glcm顾名思义其实就是一个矩阵,矩阵内放的是指定距离、方向的两个像素点的灰度关系,它可以将亦庄图片中的像素点对的灰度信息表示成一个矩阵,通过对矩阵特征的提取从而达到提取图片中信息的目的。详细的原理也不多说了,下面主要说几个经常用到的特征:
1.ASM能量
也就是矩阵中每个矩阵元素的平方和,可以直觉得判断,当图片纹理很规整的时候,矩阵元素通常会集中在谋片区域中,这样的矩阵ASM能量也就比较大,相反,如果图片比较随机,矩阵元素的分布也就十分均匀,ASM能量较小。
2.CON对比度
反应某像素值及其领域像素值亮度的对比情况,图像亮度值变化快,换句话说纹理较深,它的对比度就越大,也就是它的纹理越清晰。
3.IDM逆差矩
矩阵的对角元素值越大,逆差矩越大,反映了图片纹理的局部变化,局部变化越小,图像越均匀,逆差矩越大。
4.entropy熵
表示矩阵中元素的分散程度,也表示图像纹理的复杂程度。
5.correlation自相关
计算比较复杂,度量矩阵在行或列上的相似程度,反映了图像中局部灰度的相关性。
取灰度共生矩阵前我们通常会将图片进行灰度分级,最终得到的矩阵的元素数是灰度级数的平方。对分级后的图片选择合适的步长、窗口大小、灰度方向后得到灰度矩阵,之后可以计算出各特征的值。
在这里我需要处理的是具有瑕疵的纺织物图像,当然在取GLCM之前还有很多的处理步骤,这里就省去不写了,直接贴出应用skimage里greycomatrix库进行特征提取,并用SVM进行分类的代码。先来看看skimage中的参数:
skimage.feature.greycomatrix(image, distances, angles, levels=None, symmetric=False, normed=False)
其中image是向量表示的图像,distances和angels都是向量,分别表示步长和角度,也就是说skimage允许我们同时计算多个步长和方向上的共生矩阵,levels是图像的灰度等级,symmetric默认是false,将其设置成true时将忽略像素点灰度值得顺序,生成一个对称矩阵,也就是说程序认为[i,j]和[j,i]是同样的两对像素点,normed选择是否标准化输出矩阵。其输出向量是一个四维矩阵,[:,:,i,j]是第i个步长第j个角度对应的共生矩阵,在下面只选择了0度和180度两个方向,至于步长经过试验之后选择了比较合适的5。首先定义了获得矩阵特征的函数
def get_feature(file):
feature = []
im = cv2.imread(file,0)
m = gm (im,[5],[0,np.pi/2],levels=256,symmetric = True)
con = gp(m,'contrast')
feature.append(con[0,0])
feature.append(con[0,1])
dis = gp(m,'dissimilarity')
feature.append(dis[0,0])
#feat
ure.append(dis[0,1])
hom = gp(m,'homogeneity')
feature.append(hom[0,0])
feature.append(hom[0,1])
'''asm = gp(m,'ASM')
feature.append(asm[0,0])
feature.append(asm[0,1])'''
df = np.array(feature)
return df
之后定义用于读取文件得到训练集和测试集的函数
def get_xy(file,savex,savey):
pic_l = os.listdir(file)
rd.shuffle(pic_l)
count = 0
x = []
y = []
xx = []
for pic in pic_l:
print('getting')
print(pic)
if pic[-3:]=='jpg':
x_raw = get_feature(file+'\\'+pic)
x.append(x_raw)
y.append(pic[-5])
x = np.array(x)
y = np.array(y)
xtr_df = pd.DataFrame(x)
xtr_df.to_csv('D:\\1.3\\40s\\'+savex,mode='a',header=None,index = None)
ytr_df = pd.DataFrame(y)
ytr_df.to_csv('D:\\1.3\\40s\\'+savey,mode='a',header=None,index = None)
count+=1
x = []
y = []
print(count)
xx = np.array(x)
yy = np.array(y)
return pic_l
之后可以开始使用svm进行分类,先计算一下特征
import os
import cv2
import numpy as np
from skimage.feature import greycomatrix as gm
from skimage.feature import greycoprops as gp
import random as rd
import pandas as pd
l1 = get_xy('D:\\1.3\\40s','x_train.csv','y_train.csv')
l2 = get_xy('D:\\1.3\\40s\\test','x_test.csv','y_test.csv')
然后读取训练集和测试集
import pandas as pd
import numpy as np
x_train = np.array(pd.read_csv('D:\\1.3\\40s\\x_train.csv',header = None))
y_train = np.array(pd.read_csv('D:\\1.3\\40s\\y_train.csv',header = None))
x_test = np.array(pd.read_csv('D:\\1.3\\40s\\x_test.csv',header = None))
y_test = np.array(pd.read_csv('D:\\1.3\\40s\\y_test.csv',header = None))
from sklearn import svm
clf = svm.SVC(kernel = 'linear',C=0.5,degree = 4)
clf.fit(x_train, y_train)
print(clf.score(x_train,y_train))
最终得到了0.9967的得分,效果十分不错了。
ps. 在特征选取中舍去了部分区分度不好的特征,这一部分需要经过试验选择。