- 特征提取的简介
- LBP特征提取
- 介绍
- 原理
- 代码实现
- Gabor特征提取
- 介绍
- Gabor滤波器介绍
- Gabor特征介绍
- 原理
- 代码实现
- 生成一个Gabor滤波器并对图像进行滤波
- Gabor特征提取
- 基于颜色直方图的特征提取与反向投影
- 介绍
- 代码
- 末尾
特征提取:通过统计或学习等方法从图像中提取出能够有效表示原始图像内容的特征向量的集合
这位大哥讲的很不错
介绍局部二值模式(Local Binary Patter,LBP)是一种用来描述图像局部纹理特征的算子
由于计算简单,可用于基于纹理分类的实时应用场景,例如目标检测,人脸识别(LBP+AdaBoost)
LBP特征只考虑纹理信息,不包含颜色信息,因此彩色图需转换为灰度图
原理LBP特征提取操作可以去除光照对图片的影响
对于一张单通道灰度图,我们对每一个像素进行如下操作:
首先,我们可以取这个像素点X以及其周围一圈8个像素点,组成3x3的像素矩阵(每个像素的灰度值的范围 0-255)
对于这个3x3的矩阵,对其进行LBP操作,将其二值化
公式:
L
B
P
(
x
c
,
y
c
)
=
∑
p
=
0
p
−
1
2
p
s
(
i
p
−
i
c
)
LBP(x_c,y_c)=sum^{p-1}_{p=0}2^ps(i_p-i_c)
LBP(xc,yc)=p=0∑p−12ps(ip−ic)
s
(
x
)
=
{
1
i
f
x
≥
0
0
e
l
s
e
s(x)= begin{cases} 1& if x geq 0\ 0& else end{cases}
s(x)={10if x≥0else
二值化后的矩阵
然后将像素点X外的一圈01值重组为一个长度为9的二进制数,这个二进制数对应的十进制数即为像素点X的新值
代码实现导入算法所需的包
import cv2 as cv import numpy as np import matplotlib.pyplot as plt import matplotlib.cm as cm
读入所需处理的单通道灰度图
filepath='anime2.PNG'
img=cv.imread(filepath,0)
plt.imshow(img,cmap='gray')
print("img shape:",img.shape)
img shape: (654, 843)
这是自己实现的LBP函数
def LBP(img):
dst=np.zeros(img.shape,dtype=img.dtype)
for i in range(1,img.shape[0]-1):
for j in range(1,img.shape[1]-1):
center=img[i][j]
code=0
code |= (img[i-1][j-1]>=center)<<7
code |= (img[i-1][j ]>=center)<<6
code |= (img[i-1][j+1]>=center)<<5
code |= (img[i ][j+1]>=center)<<4
code |= (img[i+1][j+1]>=center)<<3
code |= (img[i+1][j ]>=center)<<2
code |= (img[i+1][j-1]>=center)<<1
code |= (img[i ][j-1]>=center)<<0
dst[i][j]=code
return dst
进行LBP处理
plt.imshow(LBP(img),cmap='gray')
再测试一下,是否对阳光干扰有作用
img_=cv.imread('beam_face.jpg',0)
plt.figure(figsize=[8,8])
plt.subplot(2,2,1)
plt.imshow(cv.cvtColor(img_,cv.COLOR_BGR2RGB))
plt.title('src image')
plt.subplot(2,2,2)
plt.imshow(cv.cvtColor(LBP(img_),cv.COLOR_BGR2RGB))
plt.title('LBP image')
Gabor特征提取 介绍 Gabor滤波器介绍貌似有用?
实在看不懂,转载一位大哥的博客内容
在图像处理中,Gabor函数是一个用于边缘提取的线性滤波器,Gabor函数十分适合纹理表达和分离。
在空间域中,一个二维Gabor滤波器是一个由正弦平面波调制的高斯核函数。
Gabor滤波器的脉冲响应,可以定义为一个正弦波(对于二维Gabor滤波器是正弦平面波)乘以高斯函数。由于乘法的卷积性质,Gabor滤波器的脉冲响应的傅立叶变换是其调和函数的傅立叶变换和高斯函数傅立叶变换的卷积。该滤波器由实部和虚部组成,二者相互正交。
一组不同频率不同方向的Gabor函数对于图像特征提取非常有用。
Gabor特征介绍Gabor函数可以在频域上不同尺度,不同方向上提取相关的特征(采用不同参数的Gabor函数),由于Gabor函数与人眼的作用相仿,所以常用在纹理识别上。
Gabor特征提取主要包含取模,特征降维,特征归一化和特征选取等操作。
- 取模
就是使用图像变换后的实部和虚部的模(二范数)作为图像特征.
m o d ( c o m b i n e ) = r e a l 2 + i m a g 2 mod(combine)=sqrt{real^2+imag^2} mod(combine)=real2+imag2 - 特征降维
图像识别领域一般使用8个方向和5个尺度的Gabor滤波器,会得到40幅变换图像,这些变换图像的特征串联起来即为图像的特征(40维的特征),由于特征维度较高,故需要降维。最简单的方法就是对每个模图像进行下采样。
下图为图像的一个变换图像(即使用了一个Gabor滤波器对原图像滤波后得到的图像)
- 特征归一化
一般使用Z-score标准化方法
x = x − μ σ x=frac{x-mu}{sigma} x=σx−μ- 本方法要求原始数据的分布为高斯分布,不然归一化的效果很糟糕。
- 在分类,聚类算法中,需要使用距离来度量相似性的时候,或者使用PCA技术进行降维的时候,Z-score 标准化方法表现更好
- 特征选取
在经过以上三步之后,图像特征(各模图像串联得到)可能存在大量冗余,最好在进行一次特征选择操作,可以使用PCA或Fisher等线性子空间分析方法
通过Gabor函数生成Gabor滤波器(size x size的矩阵),再利用Gabor滤波器对图像进行卷积(滤波)操作,得到包含Gabor特征的图像
Gabor函数:
g
ϕ
(
x
,
y
)
=
g
(
x
,
y
,
σ
x
,
σ
y
,
f
x
,
f
y
,
θ
)
g^phi(x,y)=g(x,y,σ_x,σ_y,f_x,f_y,theta)
gϕ(x,y)=g(x,y,σx,σy,fx,fy,θ)
=
e
x
p
(
−
(
(
X
(
x
,
y
,
θ
)
σ
x
)
+
(
Y
(
x
,
y
,
θ
)
σ
y
)
)
)
e
x
p
(
i
(
f
x
x
+
f
y
y
)
)
=exp(-((frac{X(x,y,theta)}{σ_x})+(frac{Y(x,y,theta)}{σ_y})))exp(i(f_xx+f_yy))
=exp(−((σxX(x,y,θ))+(σyY(x,y,θ))))exp(i(fxx+fyy))
其中:
X
(
x
,
y
,
θ
)
=
x
c
o
s
(
θ
)
+
y
s
i
n
(
θ
)
X(x,y,theta)=xcos(theta)+ysin(theta)
X(x,y,θ)=xcos(θ)+ysin(θ)
Y
(
x
,
y
,
θ
)
=
−
x
s
i
n
(
θ
)
+
y
c
o
s
(
θ
)
Y(x,y,theta)=-xsin(theta)+ycos(theta)
Y(x,y,θ)=−xsin(θ)+ycos(θ)
- x和y为坐标,θ是Gabor的方向
- σ x sigma_x σx和 σ y sigma_y σy分别是x和y方向的带宽,是一个标量参数
- f x f_x fx和 f y f_y fy分别是x和y方向的中心调频,是一个标量参数
实部:
g
e
ϕ
(
x
,
y
)
=
e
x
p
(
−
(
(
X
σ
x
)
2
+
(
Y
σ
y
)
2
)
)
c
o
s
(
f
x
x
+
f
y
y
)
g_e^phi(x,y)=exp(-((frac{X}{σ_x})^2+(frac{Y}{σ_y})^2))cos(f_xx+f_yy)
geϕ(x,y)=exp(−((σxX)2+(σyY)2))cos(fxx+fyy)
虚部:
g
o
ϕ
(
x
,
y
)
=
e
x
p
(
−
(
(
X
σ
x
)
2
+
(
Y
σ
y
)
2
)
)
s
i
n
(
f
x
x
+
f
y
y
)
g_o^phi(x,y)=exp(-((frac{X}{σ_x})^2+(frac{Y}{σ_y})^2))sin(f_xx+f_yy)
goϕ(x,y)=exp(−((σxX)2+(σyY)2))sin(fxx+fyy)
matlab代码
主要功能是生成一个Gabor滤波器
function [RealTemplate,ImagTemplate,CombineTemplate]=CreateGaborTemplate(Diameter_x,Diameter_y,Band_sigma_x,Band_sigma_y,Frequency_fx,Frequency_fy,Rotation_sita) [GridX,GridY]=meshgrid(-Diameter_x:Diameter_x,-Diameter_y:Diameter_y); X=GridX*cos(Rotation_sita)+GridY*sin(Rotation_sita); Y=-GridX*sin(Rotation_sita)+GridY*cos(Rotation_sita); %实部计算 RealTemplate=exp(-((X/Band_sigma_x).^2 + (Y/Band_sigma_y).^2)).*cos( Frequency_fx*GridX +Frequency_fy*GridY); %虚部计算 ImagTemplate=exp(-((X/Band_sigma_x).^2 + (Y/Band_sigma_y).^2)).*sin( Frequency_fx*GridX +Frequency_fy*GridY); %计算结合的模版 CombineTemplate=sqrt(RealTemplate.*RealTemplate + ImagTemplate.*ImagTemplate);
clear;clc;close all
Diameter_x=15;%Gabor滤波x方向半径大小
Diameter_y=15;%Gabor滤波y方向半径大小
Band_sigma_x=8;%x方向带宽
Band_sigma_y=2;%y方向带宽
Frequency_fx=1;%x方向中心调频
Frequency_fy=0.25;%y方向中心调频
Rotation_sita=3*pi/4;%
[RealTemplate,ImagTemplate,CombineTemplate]=CreateGaborTemplate(Diameter_x,Diameter_y,Band_sigma_x,Band_sigma_y,Frequency_fx,Frequency_fy,Rotation_sita);
[X,Y]=meshgrid(-Diameter_x:Diameter_x,-Diameter_y:Diameter_y);
figure
subplot(1,3,1)
surf(X,Y,RealTemplate)
xlabel('x')
ylabel('y')
title('Real')
subplot(1,3,2)
surf(X,Y,ImagTemplate)
xlabel('x')
ylabel('y')
title('imaginary')
subplot(1,3,3)
surf(X,Y,CombineTemplate)
xlabel('x')
ylabel('y')
title('combined')
python实现
主要功能也是生成一个Gabor滤波器
def Gabor(x,y,sigma_x,sigma_y,f_x,f_y,theta):
range_x=np.array(list(range(-x,x+1,1)))
range_y=np.array(list(range(-y,y+1,1)))
grid_x,grid_y=np.meshgrid(range_x,range_y)
X=grid_x*np.cos(theta)+grid_y*np.sin(theta)
Y=-grid_x*np.sin(theta)+grid_y*np.cos(theta)
# 实部计算
real_template=np.exp(-((X/sigma_x)**2+(Y/sigma_y)**2))*
np.cos(f_x*grid_x+f_y*grid_y)
# 虚部计算
imag_template=np.exp(-((X/sigma_x)**2+(Y/sigma_y)**2))*
np.sin(f_x*grid_x+f_y*grid_y)
# 计算结合的模板
combine_template=np.sqrt(real_template**2+imag_template**2)
return real_template,imag_template,combine_template
# 测试 x=15 y=15 sigma_x=8# 8 sigma_y=2# 2 f_x=1 f_y=0.25 theta=3*np.pi/4 real,imag,combine=Gabor(x,y,sigma_x,sigma_y,f_x,f_y,theta) range_x=np.array(list(range(-x,x+1,1))) range_y=np.array(list(range(-y,y+1,1))) x,y=np.meshgrid(range_x,range_y)
我们可以看看
%matplotlib inline
def plot_surface(types):
fig=plt.figure(figsize=[10,10])
titles=['real','imag','combine']
for i,type in enumerate(types):
ax=fig.add_subplot(2,2,i+1,projection='3d')
ax.view_init(elev=0,azim=45)
ax.set_xlabel('x-label',color='r')
ax.set_ylabel('y-label',color='g')
ax.set_zlabel('z-label',color='b')
ax.plot_surface(x,y,type,cmap=cm.coolwarm)
plt.title(titles[i])
下图打印得就是Gabor滤波器的实部,虚部和模的三维图像
(x,y轴为矩阵的行与列,z轴为矩阵的元素值)
plot_surface([real,imag,combine])
将三维图俯视来看看
def plot_overlook(types):
fig=plt.figure(figsize=[10,10])
titles=['real','imag','combine']
for i,type in enumerate(types):
ax=fig.add_subplot(2,2,i+1,projection='3d')
ax.view_init(elev=90,azim=0)
ax.plot_surface(x,y,type,cmap=cm.coolwarm)
plt.title(titles[i])
plot_overlook([real,imag,combine])
各种不同参数的Gabor滤波器的实部的三维曲面图
对图像进行Gabor滤波测试
img=cv.imread('anime2.PNG')
img=cv.cvtColor(img,cv.COLOR_BGR2RGB)
plt.imshow(img,cmap='gray')
img.shape
调用库函数进行滤波
retval1=cv.getGaborKernel(ksize=(31,31),sigma=10,theta=0,lambd=10,gamma=1.2) result=cv.filter2D(img,-1,retval1) plt.imshow(result,cmap='gray')
测试一下自己实现的
# 自己实现的Gabor进行滤波 ## 别人的(效果不好) # Gabor_kernel=Gabor_filter() # result=cv.filter2D(img,-1,Gabor_kernel) ## 自己的(效果也不好) # 测试 x=15 y=15 sigma_x=8# 8 sigma_y=2# 2 f_x=1 f_y=0.25 theta=0 _,_,combine=Gabor(x,y,sigma_x,sigma_y,f_x,f_y,theta) result=cv.filter2D(img,-1,combine) plt.imshow(result,cmap='gray')
龟龟,根本没有作用,可能是参数没调好吧(以后来填坑,也欢迎dude指导操作)
在上面我们利用了生成的Gabor滤波器对图像进行了一次滤波,得到了变换图像(即滤波后的图像)
在下面的代码,我们利用Gabor滤波得到的图像的实部和虚部,对它们进行取模,特征降维,特征归一化等操作后,得到图像的一个特征向量
当然,在下面代码中,我们只使用了一个Gabor滤波器进行滤波,在实际的目标识别任务上,一般会使用40个Gabor滤波器进行滤波
from skimage import filters filename='anime2.PNG' img = cv.imread(filename)#读图像 img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)#转灰度 #gabor变换 real, imag = filters.gabor(img_gray, frequency=0.6,theta=45,n_stds=5) #取模 img_mod=np.sqrt(real.astype(float)**2+imag.astype(float)**2) #图像缩放(下采样) newimg = cv.resize(img_mod,(0,0),fx=1/4,fy=1/4,interpolation=cv.INTER_AREA) tempfea = newimg.flatten()#矩阵展平 tmean = np.mean(tempfea)#求均值 tstd = np.std(tempfea)#求方差 newfea = (tempfea - tmean)/tstd#数值归一化 print(newfea)
这是最终得到的图像的特征向量
[-0.62839034 -0.62531086 -0.62531086 ... -0.62839034 -0.63146983 -0.63146983]基于颜色直方图的特征提取与反向投影 介绍
对于原灰度矩阵
Image=
1 2 3 4
5 6 7 7
9 8 0 1
5 6 7 6
我们经过将灰度值划分区间,便可得到该图像的灰度直方图
我们 将灰度值划分为如下四个区间:
[0,2] [3,5] [6,7] [8,10]
例子:
然后我们计算反向投影矩阵
back_Projection=
4 4 4 4
4 6 6 6
2 2 4 4
4 6 6 6
所以直方图的反向投影就是将原图像中256个灰度值变成了bins个灰度值,我们实际上把原图简化了,这个过程就是提取出了图像的某个特征,然后我们就可以用这个特征(反向投影矩阵)来对比两幅图,如果两幅图的反射投影矩阵相似或相同,那么我们可以判定两幅图的这个特征是相同的
这种性质可以用来定位图像中某个局部图像所在的位置
代码导入图片
# 源图片
target=cv.imread('anime4.PNG')
hsvt=cv.cvtColor(target,cv.COLOR_BGR2HSV)
# 感兴趣区域
roi=cv.imread('anime4_target.PNG')
hsv=cv.cvtColor(roi,cv.COLOR_BGR2HSV)
# 提取了h,s两个通道,绘制二维直方图
## roi区域
M=cv.calcHist([hsv],[0,1],None,[180,256],[0,180,0,256])
## target区域
I=cv.calcHist([hsvt],[0,1],None,[180,256],[0,180,0,256])
# 打印原图片
plt.figure(figsize=[10,8])
plt.subplot(2,2,1)
plt.imshow(cv.cvtColor(target,cv.COLOR_BGR2RGB))
plt.title('target image')
plt.subplot(2,2,2)
plt.imshow(cv.cvtColor(roi,cv.COLOR_BGR2RGB))
plt.title('roi image')
plt.show()
# 计算比率,M为roi image,I为target image R=M/I h,s,v = cv.split(hsvt)# 分割目标的通道 ''' h: 色调值 s: 饱和度 ''' B = R[h.ravel(),s.ravel()]# 计算概率 B = np.minimum(B,1) B = B.reshape(hsvt.shape[:2])
对图像B进行卷积操作
disc = cv.getStructuringElement(cv.MORPH_ELLIPSE,(5,5))#定义结构形状,5×5的椭圆 B=cv.filter2D(B,-1,disc)#对图像进行卷积运算 B = np.uint8(B) cv.normalize(B,B,0,255,cv.NORM_MINMAX)
概率图像
plt.imshow(B,cmap='gray')
图像B经过阈值处理后的图像
ret,thresh=cv.threshold(B,2,255,0) plt.imshow(thresh,cmap='gray')
反向投影,将thresh矩阵与原图像进行按位和,保留thresh=1的像素点
tmp_target=cv.cvtColor(target,cv.COLOR_BGR2RGB) res=cv.bitwise_and(tmp_target,tmp_target,mask=thresh) plt.imshow(res,cmap='gray')末尾
个人感觉Gabor和直方图反向投影的部分讲的不太透彻,若有不懂的地方可以在评论区留下问题



