第一步:原始图像预处理:灰度图、伽马矫正
导入图片后,转化为灰度图,对图像进行滤波、矫正。滤波、矫正使用的方法、参数根据图片的情况进行选择。
第二步:计算各像素的总梯度、梯度方向
使用[-1,0,1]作x方向的算子;[-1;0;1]作y方向的算子;x方向梯度存入f1(i,j);y方向梯度存入f2(i,j)。计算总梯度与梯度方向。
总梯度:rho(i,j)=((f1(i,j))^2+(f2(i,j)^2))^0.5
梯度方向:theta(i,j)=(atan(f2(i,j)/f1(i,j)))*180/3.14
matlab图像左向右为正,上向下为正,计算完梯度方向后需要将其转换为平面直角坐标系中的角度以y轴正方向为0°,顺时针旋转,角度由0°变化至360°。便于后续统计方向梯度直方图。
matlab中图像坐标与角度如下图所示:
为了方便后续不同角度区间的统计,可将上图的角度转换为下图的坐标,本例子中将360°划分为6个区间,间隔为60°,统计6个区间的的方向梯度直方图(角度划分方法、划分间隔可根据需要做不同选择):
第三步:设置1个cell为cellx×celly的图片区域,该例中取10×10个像素,统计10×10=100个像素6个方向上的直方图特征。
本例子图像大小为300×400像素,因此需要统计(300/10)×(400/10)=30×40=1200个cell,每个cell中包含100个像素点,每个点都包含总梯度、梯度方向的信息,将这100个像素点根据梯度方向,划分为6个组,统计每个组的总梯度累加值(统计完后选用合适的方法对每个cell的6个方向上的总梯度累加值做归一化处理,得到1个cell的特征值。或者统计时不做简单累加,采用插值方法进行各方向的累加,得到1个cell的特征值)。
(cell的大小可根据实际需要做不同选择。)
第四步:设置1个block为n×n个cell,该例中取1个block为3×3个cell,因每个cell中包含6个方向的直方图特征,则每个block包含9×6=54个特征。
逐行、逐列取block,每个cell会多次进入不同的block进行统计。本例子中1个block由3×3个cell组成,一共可取得(30-2)×(40-2)=1064个block,每个cell包含6个特征值,因此1个block中包含9×6=54个特征值,最终产生1064×54=57456个特征值。(每个block中的54个特征值可选用合适的方法进行归一化处理)。
matlab实现程序如下:
F=imread('D:\Desktop\matlab\13.png');
%第一步:原始图像预处理:灰度图、伽马矫正。
F=rgb2gray(F);
subplot(2,3,1),imshow(F);title('灰度图');
f=double(F);
[row,col]=size(f);
for i=1:row
for j=1:col
f(i,j)=(f(i,j))^0.5; %伽马矫正Gamma=1/2,
end
end
subplot(2,3,2),imshow(f,[]);title('伽马矫正');
%第二步:计算各像素的总梯度、梯度方向
f1=zeros(row,col); %f1用于存x方向梯度
f2=zeros(row,col); %f2用于存y方向梯度
rho=zeros(row,col); %rho用于存总方向梯度
theta=zeros(row,col); %theta用于存梯度方向
gx=[-1,0,1]; %计算x方向的算子,matlab图像左向右为正
gy=[-1;0;1]; %计算x方向的算子,matlab图像上向下为正
for i=2:row-1
for j=2:col-1
fx=[f(i,j-1),f(i,j),f(i,j+1)];
fy=[f(i-1,j);f(i,j);f(i+1,j)];
Gx=gx.*fx;
Gy=gy.*fy;
f1(i,j)=sum(Gx,"all"); %计算x方向梯度
f2(i,j)=sum(Gy,"all"); %计算y方向梯度
rho(i,j)=((f1(i,j))^2+(f1(i,j)^2))^0.5; %计算总梯度
%下面计算梯度方向,matlab图像左向右为正,上向下为正,使用f2(i,j)/f1(i,j)计算方向后需要将其转换为平面直角坐标系中的角度
%以y轴正方向为0°,顺时针旋转,角度由0°变化至360°。便于统计方向梯度直方图
if f1(i,j)>0 && f2(i,j)<0
theta(i,j)=(atan(f2(i,j)/f1(i,j)))*180/3.14+90; %x方向梯度>0,y方向梯度<0,平面直角坐标系中的第一象限,转换为0°~90°范围
end
if f1(i,j)>0 && f2(i,j)>0
theta(i,j)=(atan(f2(i,j)/f1(i,j)))*180/3.14+90; %x方向梯度>0,y方向梯度>0,平面直角坐标系中的第四象限,转换为90°~180°范围
end
if f1(i,j)<0 && f2(i,j)>0
theta(i,j)=(atan(f2(i,j)/f1(i,j)))*180/3.14+270; %x方向梯度<0,y方向梯度>0,平面直角坐标系中的第三象限,转换为180°~270°范围
end
if f1(i,j)<0 && f2(i,j)<0
theta(i,j)=(atan(f2(i,j)/f1(i,j)))*180/3.14+270; %x方向梯度<0,y方向梯度<0,平面直角坐标系中的第二象限,转换为270°~360°范围
end
if f1(i,j)==0 && f2(i,j)<0
theta(i,j)=0.00001; %x方向梯度=0,y方向梯度<0,平面直角坐标系中的y轴正方向,转换为0°,为了和无梯度方向(f2(i,j)、f1(i,j)均为0的情况)区别开,设该方向为极小的正值
end
if f1(i,j)>0 && f2(i,j)==0
theta(i,j)=90; %x方向梯度>0,y方向梯度=0,平面直角坐标系中的x轴正方向,转换为90°
end
if f1(i,j)==0 && f2(i,j)>0
theta(i,j)=180; %x方向梯度=0,y方向梯度>0,平面直角坐标系中的y轴负方向,转换为180°
end
if f1(i,j)<0 && f2(i,j)==0
theta(i,j)=270; %x方向梯度<0,y方向梯度=0,平面直角坐标系中的x轴负方向,转换为270°
end
if f1(i,j)==0 && f2(i,j)==0
theta(i,j)=0; %f2(i,j)、f1(i,j)均为0,无梯度方向
end
end
end
subplot(2,3,3),imshow(f1,[]);title('x方向梯度');
subplot(2,3,4),imshow(f2,[]);title('y方向梯度');
subplot(2,3,5),imshow(rho,[]);title('总梯度');
subplot(2,3,6),imshow(theta,[]);title('梯度方向');
%第三步:设置1个cell为cellx×celly的图片区域,该例中取10×10个像素,统计10×10=100个像素6个方向上的直方图特征.
% 需要统计(300/10)×(400/10)=30×40=1200个cell
theta_num=6; %设置统计6个方向的直方图特征(也可设置为统计9个或其他n个方向)
cellx=10; %设置1个cell有几行像素
celly=10; %设置1个cell有几列像素
theta_size=360/theta_num; %统计6个方向上的直方图,每个方向60°
cell_rho=zeros(cellx,celly); %创建cell_rho矩阵,用来放1个cell中各像素的总梯度
cell_theta=zeros(cellx,celly); %创建cell_theta矩阵,用来放1个cell中各像素的梯度方向
histogram=zeros(1,theta_num); %创建histogram数组,用来放1个cell中的6个统计直方图特征
Cell=cell(row/cellx,col/celly); %定义元胞数组大小,用于存放所有cell中的6个直方图特征
for x=1:row/cellx %需要确定图片尺寸的行数可被整除,即可得到图片可分为几行cell
for y=1:col/celly %需要确定图片尺寸的列数可被整除,即可得到图片可分为几列cell
cell_rho=rho(10*x-9:10*x,10*y-9:10*y);
cell_theta=theta(10*x-9:10*x,10*y-9:10*y); %把每个cell中的总梯度、梯度方向放入矩阵cell_rho、cell_theta中,便于后面统计
for i=1:cellx
for j=1:celly
if cell_theta(i,j)>0
histogram(ceil(cell_theta(i,j)/theta_size))=histogram(ceil(cell_theta(i,j)/theta_size))+cell_rho(i,j); %统计10×10像素中各6个方向的直方图特征,放入histogram这个1×6的数组中
end
end
end
s=sum(histogram,"all");
for h=1:theta_num
histogram(h)=histogram(h)/s; %归一化
end
figure(2),plot(histogram);
Cell{x,y}=histogram; %将归一化后的histogram(1×6)放入元胞数组中
for h=1:theta_num
histogram(h)=0; %将histogram各元素置0,为下一个cell统计做好准备
end
histogram=zeros(1,6);
end
end
%第四步:设置1个block为n×n个cell,该例中取1个block为3×3个cell,因每个cell中包含6个方向的直方图特征,则每个block包含9×6=54个特征.
% 逐行、逐列取block,一共可取得(30-2)×(40-2)=1064个block,最终产生1064×6=6384个特征值
n=3;
[v,w]=size(Cell);
feature=cell(1,(v-(n-1))*(w-(n-1)));
for xx=1:v-2
for yy=1:w-2
feature{(xx-1)*(w-2)+yy}=[Cell{xx:xx+(n-1),yy:yy+(n-1)}]; %将3×3个cell的特征向量合并放入1个block中,作为1个block的特征
end
end
%feature包含整图1064个block中所有的特征值
l=length(feature);
fmesh=[];
for i=1:l
fmesh=[fmesh;feature{i}(:)']; %用于画图
end
figure(3);
mesh(fmesh);
下图为完成第一步、第二步的结果:
下图为完成第三步,其中1个cell的6个方向的特征值:
下图为各block特征值的可视化结果,即本图片提取得到的HOG特征值:
需要能够识别图片为汽车,则需要其他的训练方法与检测方法,本例子仅简单介绍提取HOG特征值的流程,其中有多处需要根据实际情况选择参数、方法。
本例子参考了以下内容:
HOG特征提取原理_沈子恒的博客-CSDN博客
MATLAB HOG方向梯度直方图 - 一杯清酒邀明月 - 博客园 (cnblogs.com)文章来源:https://www.toymoban.com/news/detail-484591.html
【人脸识别】基于matlab HOG特征提取人脸识别【含Matlab源码 641期】_matlab提取hog特征_海神之光的博客-CSDN博客文章来源地址https://www.toymoban.com/news/detail-484591.html
到了这里,关于MATLAB代码实现HOG方向梯度直方图特征提取的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!