计算机视觉识别

一、特征提取

1.1 颜色直方图

随机生成微小图像颜色直方图代码如下(示例):

import matplotlib.pyplot
import numpy

rand_img = numpy.random.uniform(low=0, high=4, size=(5, 5))#图像大小和像素分配的上下限
rand_img = numpy.uint8(rand_img) #将值从浮点型转化为整型
hist = numpy.histogram(rand_img, bins=4) #接受的图像和柱状区间的数目
matplotlib.pyplot.bar(x=[0,1,2,3], height=hist[0], align="center", width=0.3)
matplotlib.pyplot.xticks([0, 1, 2, 3], fontsize=20)#x轴的范围和字体大小
matplotlib.pyplot.yticks(numpy.arange(0, 16, 2), fontsize=20)#y轴的范围
matplotlib.pyplot.show()

生成彩色图像的颜色直方图代码如下(示例):

#彩色图像转换成黑白图像后的直方图,读取彩色图像
import matplotlib.pyplot as plt
import numpy
import skimage.io as ski

im = ski.imread("keji.jpg", as_gray=True)#as_gray为True时将读取的图像并转换成灰度图
                                         #返回的是float64,并是0~1的区间
im = numpy.uint8(im * 255)               #将0~1的区间转换成0~255的区间


hist = numpy.histogram(im, bins=256)#使用八个位表示所以区间数为256,即2^8个等级
plt.bar(x=numpy.arange(256), height=hist[0], align='center', width=1)
plt.show()

显示图像色调的直方图代码如下(示例):

'''
另一种色彩空间:HSV(色调-饱和度-值)
色彩信息和亮度信息分离,色调通道持有色彩信息,饱和度和值指定色彩的亮度
色调通道是圆形0~360,0表示红色,120绿色,240蓝色,360回到红色:即色彩通道始于红终于红
'''
import matplotlib.pyplot as plt
import numpy
import skimage.io as skii
import skimage.color as skic

im = skii.imread("keji.jpg", as_gray=False)#as_gray为True时将读取的图像并转换成灰度图
                                         #返回的是float64,并是0~1的区间
im_HSV = skic.rgb2hsv(im)
Hue=im_HSV[:,:,0]#色调通道是HSV色彩空间的第一个通道,被赋予索引0并返回

hist = numpy.histogram(Hue, bins=360)#颜色通道0~360
plt.bar(x=numpy.arange(360), height=hist[0], align='center', width=1)
plt.show()

1.2 纹理特征

GLCM:灰度共生矩阵GLCM输入为灰度图像,输出为返回的GLCM矩阵,我们可以将GLCM描述为二维直方图,根据每个灰度对等级之间的距离计数它们之间的共生个数。
和一阶直方图不同的是,GLCM不止依赖于强度,也依赖于像素的空间关系。对于每两个像素,一个称之为参考像素,另一个称之为邻居像素。已知两个强度等级之间的距离D和角度θ时,可找到这两个强度等级的共生次数(参考像素存在于邻居像素的左侧)

计算GLCM步骤如下:
(1) 如果输入图像为灰度格式或二进制格式,直接使用。彩色图像需转换成灰度图像或者使用其中一个通道。
(2)找出图像强度等级总数。L个数目从0~L-1进行计数。
(3)创建L*L矩阵,其中行列0~L-1计数
(4)选择适当的GLCM参数(D,θ)
(5)找出两对强度等级之间的共生的次数

1.D值

最好的D值范围为1~10。较大的值GLCM不能捕捉到详细的纹理信息。D=1,2,4,8 结果都精确;D=1,2 最好。通常像素与邻近它的像素更相关,因此D小的时候效果更好

2.θ值

因为GLCM(1,3),θ=0等价于GLCM(3,1),θ=180°,所以我们需要注意只使用互补角度中的一个。附上GLCM矩阵计算的代码:

import numpy
import skimage.feature as skif

arr=numpy.array([[3,2,2,0,3],
                 [1,3,0,2,2],
                 [2,2,2,2,3],
                 [3,3,3,2,3],
                 [0,2,3,2,2]])
co_mat=skif.greycomatrix(image=arr,distances=[1,4],angles=[0,45,90],levels=4)#输入图像 矩阵计算的距离 矩阵计算的角度 矩阵的等级数目
print(co_mat.shape)#co_mat.shape=(4,4,2,3) 前两个数表示行和列,第三个表示使用的距离的数目,第四个表示角度的数目

由于有两个距离和三个角度,会返回2*3=6个GLCM

print(co_mat[:,:,0,0])#输出距离1,角度0的GLCM
print(co_mat[:,:,1,2])#输出距离4,角度90的GLCM

GLCM归一化就是将矩阵中每个元素除以矩阵元素的总和,来预测每个强度等级和其他强度等级共生的概率,python中只需要将normad设置为True(默认为False)就能得到归一化矩阵。如下:

co_mat=skif.greycomatrix(image=arr,distances=[1,4],angles=[0,45,90],levels=4,normad=True)

但是实际中的图像有八位,即256个强度等级,因此生成的矩阵大小256*256共65536个数据。在特征向量中使用所有的元素不现实,因此要从这些矩阵中提取特征来减小这个数字,提取的特征包括:相异度、相关性、均匀性、能量、对比度和ASM(角二阶矩),提取这些特征的代码如下:

import numpy
import skimage.feature as skif
import skimage.io as skio

img=skio.imread('2.jpg',as_gray=True)
img=numpy.uint8(img*255)
glcm=skif.greycomatrix(img,distances=[6],angles=[0],levels=256,normed=True)

dissimilarity=skif.greycoprops(P=glcm,prop='dissimilarity')#相异度
correlation=skif.greycoprops(P=glcm,prop='correlation')#相关性
homogeneity=skif.greycoprops(P=glcm,prop='homogeneity')#均匀性
energy=skif.greycoprops(P=glcm,prop='energy')#能量
contrast=skif.greycoprops(P=glcm,prop='contrast')#对比度
ASM=skif.greycoprops(P=glcm,prop='ASM')#角二阶矩

glcm_props=[dissimilarity,correlation,homogeneity,energy,contrast,ASM]

print('Dissimilarity',dissimilarity,'\nCorrelation',correlation,'\nHomogeneity',homogeneity,'\nEnergy',energy,'\nContrast',contrast,'\nASM',ASM)

显然灰度共生矩阵依赖于灰度值。亮度会影响得到的灰度共生矩阵。可以使用梯度而不是强度构建共生矩阵。基于梯度的灰色共生矩阵(GLGCM)亮度变化时不变,但图像转换时(如旋转),描述子会获得不同的特征,可见也还是有缺陷。


1.3 取向梯度直方图(HOG)

纹理特征不能描述图像强度的突然变化(如边缘),所以我们用HOG描述图像边缘取向。

1.HOG步骤

简单来说就是先把图片按1:2比例(横1竖2)分成片,再把片分成块,再把每个块分成小的单元格,单元格大小不固定,且块之间可能重叠,单元格可能属于多个不同的块。对每个单元格计算所有像素的梯度大小和方向。然后基于梯度的大小和方向构建每个单元格的直方图。用于构成直方图的角度为n,则返回n*1个特征向量。
基于块内的每个单元格,串联块内的所有直方图,返回整个块的直方图。比如每个单元格直方图有9个单元条,每块有4个单元格,那么返回的块级直方图就有36个单元条,作为一个向量返回结果。然后再归一化向量使其对亮度变化具有健壮性,再串联所有块的归一化向量返回最终的特征向量。

值得注意的是垂直梯度能让横向边界很好地显现出来,水平梯度能让竖直方向上的边界很好地显现出来。
#使用不同的template分别计算垂直梯度和水平梯度
def calculate_gradient(img, template):
    ts = template.size
    #
    new_img = np.zeros((img.shape[0] + ts - 1, img.shape[1] + ts - 1))
    new_img[np.uint16((ts - 1) / 2.0):img.shape[0] + np.uint16((ts - 1) / 2.0),
    np.uint16((ts - 1) / 2.0):img.shape[1] + np.uint16((ts - 1) / 2.0)] = img
    result = np.zeros((new_img.sahpe))
    for r in np.uint16(np.arange((ts - 1) / 2.0), img.shape[0] + (ts - 1) / 2.0):
        for c in np.uint16(np.arange((ts - 1) / 2.0), img.shape[1] + (ts - 1) / 2.0):
            curr_region=new_img[r-np.uint16((ts - 1) / 2.0):r+np.uint16((ts - 1) / 2.0)+1,c-np.uint16((ts - 1) / 2.0):c+np.uint16((ts - 1) / 2.0)+1]
            curr_result=curr_region*template
            score=np.sum(curr_result)
            result[r,c]=score
    result_img=result[np.uint16((ts - 1) / 2):result.shape[0]-np.uint16((ts - 1) / 2),np.uint16((ts - 1) / 2):result.shape[1]-np.uint16((ts - 1) / 2)]
    return result_img

1.4 局部二值模式LBP

LBP是一种二阶纹理描述子,提取LBP特征步骤如下:
(1)将图像划分成块
(2)对每个块的每个像素,都和与其相邻的8个像素比大小,中心像素小的为1,否则为0,然后将这些1和0按顺序排列得到一个范围0~255的整数。
(3)用这个整数来替代中心像素的值
(4)得到块内所有像素的新值后计算直方图
(5)将所有块的直方图串联起来

import skimage.feature as skif
import skimage.io as skii
import matplotlib.pyplot as plt

im=skii.imread("2.jpg",as_gray=True)
lbp=skif.local_binary_pattern(image=im,P=9,R=3)#P表示相邻的数目:旋转不变形;R表示圆圈的半径:缩放不变形
plt.imshow(lbp,cmap="Greys")
plt.show()
plt.xticks([])
plt.yticks([])

名词含义

噪声:即无关特征,和所需求的预测不相关,不会增强反而会降低识别率。
特征缩减:移除无关特征而保留其他元素的做法。分为监督方法和非监督方法,监督方法有过滤器和包装器方法,无监督包括嵌入式方法。
过滤器方法:

  • 10
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值