在现实生活中,我们要交往一个人,首先要了解这个人的特征,相貌和性格;同样,在基于数字图像的模式识别中,我们也要提取图像的特征。对图像特征的提取与研究提供了一种具有统计意义的图像内容表达,正所谓:“透过现象看本质”。
- 面特征:图像金字塔,图像矩特征
- 线特征:边缘检测
- 局部区域特征:斑点特征检测
- 点特征:角点检测
- 不变点特征:尺度不变特征提取
- 尺度不变特征变换SIFT算法、解压偶数页鲁棒性尺度不变特征提取SURF算法
传统特征提取方法:基于曲率(角点
)。现代方法:基于区域和图像块的分析,尺度不变特征变换(SIFT
)。
角点提取:计算曲率,计算边缘方向的差值,通过亮度变化计算曲率,Harris
检测算子。
形状匹配的特征提取:阈值处理、模板匹配、霍夫变换
。
弹性形状提取:无法正确对形状建模时
-
蛇模型
-
主动形状模型
-
形状骨架化
-
可变形模板
纹理描述
:特征提取(傅里叶变换、共量矩阵、区域)、特征描述(能量、熵、惯性)。
纹理分类
:k-近邻、SVM
纹理分割
:卷积、平铺、阈值
目标描述:矩(Hu矩
、zernike矩)、边界描述。
图像金字塔
图像金字塔:图像经过一个低通滤波器进行平滑,然后对这个平滑图像进行抽样,抽样比例一般在水平和垂直方向上都为1/2,从而得到一系列尺寸缩小、分辨率降低的图像。
% 读入图像并灰度化
I = imread('test.jpg');
I = rgb2gray(I);
% 生成高斯滤波器的核
w = fspecial('gaussian',3,0.5);
size_a = size(I);
% 进行高斯滤波
g = imfilter(I,w,'conv','symmetric','same');
% 降采样
t = g(1:2:size_a(1),1:2:size_a(2));
% 显示结果
figure(1);imshow(I);
figure(2);imshow(t);
- 高斯金字塔分解:低通滤波和降采样
- 拉普拉斯金字塔分解:相当于高斯金字塔与其高一级图像内插放大后图像的差,相当于带通滤波。
function [ pyr ] = genPyr( img, type, level )
% 功能: 产生图像的高斯金字塔或拉普拉斯金字塔
% 输入:img-灰度图像;
% type-变换的类型:'gauss' or 'laplace';
% level-分解层数
% 输出:PYR-1*LEVEL 元胞数组
pyr = cell(1,level);
pyr{1} = im2double(img);
%%%%%%图像的金字塔化%%%%%%
%计算图像的高斯金字塔
for p = 2:level
pyr{p} = pyr_reduce(pyr{p-1});
end
if strcmp(type,'gauss'), return; end
% 调整图像尺寸
for p = level-1:-1:1
osz = size(pyr{p+1})*2-1;
pyr{p} = pyr{p}(1:osz(1),1:osz(2),:);
end
% 计算图像的拉普拉斯金字塔
for p = 1:level-1
pyr{p} = pyr{p}-pyr_expand(pyr{p+1});
end
end
function [ imgout ] = pyr_reduce( img )
% 功能:计算图像的高斯金字塔
% 输入:img-灰度图像;
% 输出:imgout-分解后的金子塔图像数组
% 生成高斯核
kernelWidth = 5;
cw = .375;
ker1d = [.25-cw/2 .25 cw .25 .25-cw/2];
kernel = kron(ker1d,ker1d');
img = im2double(img);
sz = size(img);
imgout = [];
% 产生图像的高斯金字塔
for p = 1:size(img,3)
img1 = img(:,:,p);
imgFiltered = imfilter(img1,kernel,'replicate','same');
imgout(:,:,p) = imgFiltered(1:2:sz(1),1:2:sz(2));
end
end
function [ imgout ] = pyr_expand( img )
% 功能:图像金字塔扩张
% 输入:img-待扩张的图像
% 输出:imgout-扩张后的图像
kw = 5;
cw = .375;
ker1d = [.25-cw/2 .25 cw .25 .25-cw/2];
kernel = kron(ker1d,ker1d')*4;
ker00 = kernel(1:2:kw,1:2:kw);
ker01 = kernel(1:2:kw,2:2:kw);
ker10 = kernel(2:2:kw,1:2:kw);
ker11 = kernel(2:2:kw,2:2:kw);
img = im2double(img);
sz = size(img(:,:,1));
osz = sz*2-1;
imgout = zeros(osz(1),osz(2),size(img,3));
for p = 1:size(img,3)
img1 = img(:,:,p);
img1ph = padarray(img1,[0 1],'replicate','both');
img1pv = padarray(img1,[1 0],'replicate','both');
img00 = imfilter(img1,ker00,'replicate','same');
img01 = conv2(img1pv,ker01,'valid');
img10 = conv2(img1ph,ker10,'valid');
img11 = conv2(img1,ker11,'valid');
imgout(1:2:osz(1),1:2:osz(2),p) = img00;
imgout(2:2:osz(1),1:2:osz(2),p) = img10;
imgout(1:2:osz(1),2:2:osz(2),p) = img01;
imgout(2:2:osz(1),2:2:osz(2),p) = img11;
end
end
%% 金字塔分解函数实现
close all;clear all;clc;
img=imread('qingdao.jpg');
n=3;
%[ pyr ] = genPyr( img, 'gauss', n );%高斯金字塔分解
[ pyr ] = genPyr( img, 'laplace', n );%拉普拉斯金字塔分解
for i=1:n
figure(i);
imshow(pyr{i});
end
图像的矩特征
由于被识别的图像与原图像相比一般有很大程度的失真,如平移、旋转和其他变化。不变矩是一种高度浓缩的图像特征,具有平移、灰度、尺度、旋转不变性,因此矩和矩函数被广泛用于图像的模式识别、图像分类、目标识别和场景分析中。M.K.Hu在1961年首次提出不变矩的概念,并将几何矩用于图像描述,但其低阶几何矩与图像的整体特征有关,不包含太多的图像细节信息,而高阶几何矩易受噪声影响,因此,很难用几何矩恢复图像。Zernike矩能够很容易的构造图像的任意高阶矩,并能使用较少的矩来重建图像。
- 计算Hu矩
function inv_m7 = invariable_moment(in_image)
% 功能:计算图像的Hu的七个不变矩
% 输入:in_image-RGB图像
% 输出:inv_m7-七个不变矩
% 将输入的RGB图像转换为灰度图像
image=rgb2gray(in_image);
%将图像矩阵的数据类型转换成双精度型
image=double(image);
%%%=================计算 、 、 =========================
%计算灰度图像的零阶几何矩
m00=sum(sum(image));
m10=0;
m01=0;
[row,col]=size(image);
for i=1:row
for j=1:col
m10=m10+i*image(i,j);
m01=m01+j*image(i,j);
end
end
%%%=================计算 、 ================================
u10=m10/m00;
u01=m01/m00;
%%%=================计算图像的二阶几何矩、三阶几何矩============
m20 = 0;m02 = 0;m11 = 0;m30 = 0;m12 = 0;m21 = 0;m03 = 0;
for i=1:row
for j=1:col
m20=m20+i^2*image(i,j);
m02=m02+j^2*image(i,j);
m11=m11+i*j*image(i,j);
m30=m30+i^3*image(i,j);
m03=m03+j^3*image(i,j);
m12=m12+i*j^2*image(i,j);
m21=m21+i^2*j*image(i,j);
end
end
%%%=================计算图像的二阶中心矩、三阶中心矩============
y00=m00;
y10=0;
y01=0;
y11=m11-u01*m10;
y20=m20-u10*m10;
y02=m02-u01*m01;
y30=m30-3*u10*m20+2*u10^2*m10;
y12=m12-2*u01*m11-u10*m02+2*u01^2*m10;
y21=m21-2*u10*m11-u01*m20+2*u10^2*m01;
y03=m03-3*u01*m02+2*u01^2*m01;
%%%=================计算图像的归格化中心矩====================
n20=y20/m00^2;
n02=y02/m00^2;
n11=y11/m00^2;
n30=y30/m00^2.5;
n03=y03/m00^2.5;
n12=y12/m00^2.5;
n21=y21/m00^2.5;
%%%=================计算图像的七个不变矩======================
h1 = n20 + n02;
h2 = (n20-n02)^2 + 4*(n11)^2;
h3 = (n30-3*n12)^2 + (3*n21-n03)^2;
h4 = (n30+n12)^2 + (n21+n03)^2;
h5 = (n30-3*n12)*(n30+n12)*((n30+n12)^2-3*(n21+n03)^2)+(3*n21-n03)*(n21+n03)*(3*(n30+n12)^2-(n21+n03)^2);
h6 = (n20-n02)*((n30+n12)^2-(n21+n03)^2)+4*n11*(n30+n12)*(n21+n03);
h7 = (3*n21-n03)*(n30+n12)*((n30+n12)^2-3*(n21+n03)^2)+(3*n12-n30)*(n21+n03)*(3*(n30+n12)^2-(n21+n03)^2);
inv_m7= [h1 h2 h3 h4 h5 h6 h7];
- 计算Zernike矩
- 首先确定图像函数的大小N*N,从而确定N值
- 进一步确定r和delta的范围
- 利用Zernike多项式的快速递推性质计算各阶Rnm,Cnm和Snm
-
对Cnm和Snm求模,求得 Znm
function [A_nm,zmlist,cidx,V_nm] = zernike(img,n,m)
% 功能:计算输入图像的Zernike矩
% 输入:img-灰度图像
% n-阶数
% 输出:V_nm-n阶的Zernike多项式,定义为在极坐标系中p,theta的函数
% cidx-表示虚部值
% A_nm-Zernike矩
if nargin>0
if nargin==1
n=0;
end
d=size(img);
img=double(img);
% 取步长
xstep=2/(d(1)-1);
ystep=2/(d(2)-1);
% 画方格
[x,y]=meshgrid(-1:xstep:1,-1:ystep:1);
circle1= x.^2 + y.^2;
% 提取符合circle1<=1的数
inside=find(circle1<=1);
% 构造size(d)*size(d)的矩阵
mask=zeros(d);
% 构造size(inside)*size(inside)的全为1的矩阵赋值给mask(inside)
mask(inside)=ones(size(inside));
% 计算图像的复数表示
[cimg,cidx]=clipimg(img,mask);
% 计算Z的实部和虚部
z=clipimg(x+i*y,mask);
% 计算复数的模,sqrt(x,y),z=x+iy
p=0.9*abs(z); ;
% 计算复数z的辐角值(tanz)
theta=angle(z);
c=1;
for order=1:length(n)
n1=n(order);
if nargin<3
m=zpossible(n1);
end
for r=1:length(m)
V_nmt=zpoly(n1,m(r),p,theta);
% conj是求复数的共轭
zprod=cimg.*conj(V_nmt);
% (n1+1)/π*∑∑(zprod); 对于图像而言求和代替了求积分
A_nm(c)=(n1+1)*sum(sum(zprod))/pi;
zmlist(c,1:2)=[n1 m(r)];
if nargout==4
V_nm(:,c)=V_nmt;
end
c=c+1;
end
end
else
end
%%%%%子函数%%%%%
function [cimg,cindex,dim]=clipimg(img,mask)
%功能:计算复数的实部和虚部
dim=size(img);
cindex=find(mask~=0);
cimg=img(cindex);
return;
%%%%%子函数%%%%%
function [m]=zpossible(n)
% 功能:判断n是偶数还是奇数,是偶数时,m取0,2,4,6等,否则取奇数赋值m
if iseven(n)
m=0:2:n;
else
m=1:2:n;
end
return;
%%%%%子函数%%%%%
function [V_nm,mag,phase]=zpoly(n,m,p,theta)
%功能:计算Zernike矩多项式
R_nm=zeros(size(p)); % 产生size(p)*size(p)的零矩阵赋给R_nm
a=(n+abs(m))/2;
b=(n-abs(m))/2;
total=b;
for s=0:total
num=((-1)^s)*fac(n-s)*(p.^(n-2*s)); % (-1).-1*(n-s)!r.^(n-2*s)
den=fac(s)*fac(a-s)*fac(b-s); % s!*(a-s)!*(b-s)!
R_nm=R_nm + num/den; % R_nm是一个实数值的径向多项式
end
mag=R_nm; % 赋值
phase=m*theta;
V_nm=mag.*exp(i*phase); % V_nm为n阶的Zernike多项式,定义为在极坐标系中p,theta的函数
return;
%%%%%子函数%%%%%
function [factorial]=fac(n)
%功能:求n的阶乘
maxno=max(max(n));
zerosi=find(n<=0); %取n小于等于0的数
n(zerosi)=ones(size(zerosi));
factorial=n;
findex=n;
for i=maxno:-1:2
cand=find(findex>2);
candidates=findex(cand);
findex(cand)=candidates-1;
factorial(cand)=factorial(cand).*findex(cand);
end
return;
function [verdict]=iseven(candy)
verdict=zeros(size(candy));
isint=find(isint(candy)==1);
divided2=candy(isint)/2;
evens=(divided2==floor(divided2));
verdict(isint)=evens;
return;
function [verdict]=isint(candy)
verdict = double(round(candy))==candy;
return;
%% 函数实现
close all;clear all;clc;
%%
in_image=imread('qingdao.jpg');
inv_m7 = invariable_moment(in_image) %%Hu矩
%%
img=imread('qingdao.jpg');
img=rgb2gray(img);
[A_nm,zmlist,cidx,V_nm] = zernike(img);
A_nm %%Zernike矩
不变矩是一种高度浓缩的图像特征,具有平移、尺度、旋转等不变性;正交矩具有绝对的独立性,没有信息冗余现象,抽样性能好,抗噪能力强,适合于图像识别。
图像的边缘检测
运用一阶微分算子检测边缘
- 梯度边缘算子
运用二阶微分算子检测边缘
- 高斯拉普拉斯算子
close all;clear all;clc;
f=imread('xinglong.jpg');
f=rgb2gray(f);
%% 调用函数
e=log_edge(f,0.5);
figure(1);imshow(f);
figure(2);imshow(e);
function e=log_edge(a, sigma)
%功能:实现LoG算子提取边缘点
%输入:a-灰度图像
% sigma-滤波器参数
%输出:e-边缘图像
%产生同样大小的边缘图像e,初始化为0.
[m,n]=size(a);
e=repmat(logical(uint8(0)),m,n);
rr=2:m-1;cc=2:n-1;
%选择点数为奇数的滤波器的尺寸fsize>6*sigma;
fsize=ceil(sigma*3)*2+1;
%产生LoG滤波器
op=fspecial('log',fsize,sigma);
%将LoG滤波器的均值变为0.
op=op-sum(op(:))/prod(size(op));
%利用LoG算子对图像滤波
b=filter2(op,a);
%设置过零检测的门限
%寻找滤波后的过零点,+-和-+表示水平方向从左到右和从右到左过零
%[+-]'和[-+]'表示垂直方向从上到下和从下到上过零
%这里我们选择边缘点为值为负的点
thresh=.75*mean2(abs(b(rr,cc)));
%[- +]的情况
[rx,cx]=find(b(rr,cc)<0&b(rr,cc+1)>0&abs(b(rr,cc)-b(rr,cc+1))>thresh);
e((rx+1)+cx*m)=1;
%[- +]的情况
[rx,cx]=find(b(rr,cc-1)>0&b(rr,cc)<0&abs(b(rr,cc-1)-b(rr,cc))>thresh);
e((rx+1)+cx*m)=1;
%[- +]的情况
[rx,cx]=find(b(rr,cc)<0&b(rr+1,cc)>0&abs(b(rr,cc)-b(rr+1,cc))>thresh);
e((rx+1)+cx*m)=1;
%[- +]的情况
[rx,cx]=find(b(rr-1,cc)>0&b(rr,cc)<0&abs(b(rr-1,cc)-b(rr,cc))>thresh);
e((rx+1)+cx*m)=1;
%某些情况下LoG滤波结果可能正好为0,下面考虑这种情况:
%寻找滤波后的过零
%+0-和-0+表示水平方向从左到右和从右到左过零
%[+0-]'和[-0+]'表示垂直方向从上到下和从下到上过零
%边缘正好位于滤波值为零点上
[rz,cz]=find(b(rr,cc)==0);
if~isempty(rz)
%零点的线性坐标
zero=(rz+1)+cz*m;
%[-0+]的情况
zz=find(b(zero-1)<0&b(zero+1)>0&abs(b(zero-1)-b(zero+1))>2*thresh);
e(zero(zz))=1;
%[+0-]'的情况
zz=find(b(zero-1)>0&b(zero+1)<0&abs(b(zero-1)-b(zero+1))>2*thresh);
e(zero(zz))=1;
%[-0+]的情况
zz=find(b(zero-m)<0&b(zero+m)>0&abs(b(zero-1)-b(zero+1))>2*thresh);
e(zero(zz))=1;
%[+0-]'的情况
zz=find(b(zero-m)>0&b(zero+m)<0&abs(b(zero-1)-b(zero+1))>2*thresh);
e(zero(zz))=1;
end
Canny算子检测图像边缘
Canny边缘检测算子是边缘检测算子中最常见的一种,也是公认的性能优良的边缘检测算子,它经常被其他算子引用作为标准算子进行优劣的对比分析。
- 高的检测率
- 精确的定位
- 明确的响应
Canny算子采用了高斯函数对图像进行平滑处理,因此,具有较强的噪声抑制能力;同样,该算子也将一些高频边缘平滑掉,易造成边缘丢失。Canny采用了双阈值算法检测和连接边缘,边缘的连续性较好。
SUSAN算子边缘检测
- 抗噪性能好
- 算法使用灵活
- 运算量小,速度快
- 可以检测边缘的方向信息
close all;clear all;clc;
f=imread('diaohua.jpg');
f=rgb2gray(f);
e = susan(f,25);
figure(1);imshow(f);
figure(2);imshow(e);
function image_out = susan(im,threshold)
% 功能:实现运用SUNSAN算子进行边缘检测
% 输入:image_in-输入的待检测的图像
% threshold-阈值
% 输出:image_out-检测边缘出的二值图像
% 将输入的图像矩阵转换成double型
d = length(size(im));
if d==3
image=double(rgb2gray(im));
elseif d==2
image=double(im);
end
% 建立SUSAN模板
mask = ([ 0 0 1 1 1 0 0 ;0 1 1 1 1 1 0;1 1 1 1 1 1 1;1 1 1 1 1 1 1;1 1 1 1 1 1 1;0 1 1 1 1 1 0;0 0 1 1 1 0 0]);
R=zeros(size(image));
% 定义USAN 区域
nmax = 3*37/4;
[a b]=size(image);
new=zeros(a+7,b+7);
[c d]=size(new);
new(4:c-4,4:d-4)=image;
for i=4:c-4
for j=4:d-4
current_image = new(i-3:i+3,j-3:j+3);
current_masked_image = mask.*current_image;
% 调用susan_threshold函数进行阈值比较处理
current_thresholded = susan_threshold(current_masked_image,threshold);
g=sum(current_thresholded(:));
if nmax<g
R(i,j) = g-nmax;
else
R(i,j) = 0;
end
end
end
image_out=R(4:c-4,4:d-4);
function thresholded = susan_threshold(image,threshold)
% 功能:设定SUSAN算法的阈值
[a b]=size(image);
intensity_center = image((a+1)/2,(b+1)/2);
temp1 = (image-intensity_center)/threshold;
temp2 = temp1.^6;
thresholded = exp(-1*temp2);
小波变换模极大值的边缘检测(效果较好)
- 对于原始图像进行二进离散平稳小波变换
- 通过变换系数,得到图像水平方向和垂直方向的小波变换系数
- 求局部模极大值
%% 基于小波变换模极大值的边缘检测
clear all;
load wbarb;
I = ind2gray(X,map);imshow(I);
I1 = imadjust(I,stretchlim(I),[0,1]);figure;imshow(I1);
[N,M] = size(I);
h = [0.125,0.375,0.375,0.125];
g = [0.5,-0.5];
delta = [1,0,0];
J = 3;
a(1:N,1:M,1,1:J+1) = 0;
dx(1:N,1:M,1,1:J+1) = 0;
dy(1:N,1:M,1,1:J+1) = 0;
d(1:N,1:M,1,1:J+1) = 0;
a(:,:,1,1) = conv2(h,h,I,'same');
dx(:,:,1,1) = conv2(delta,g,I,'same');
dy(:,:,1,1) = conv2(g,delta,I,'same');
x = dx(:,:,1,1);
y = dy(:,:,1,1);
d(:,:,1,1) = sqrt(x.^2+y.^2);
I1 = imadjust(d(:,:,1,1),stretchlim(d(:,:,1,1)),[0 1]);figure;imshow(I1);
lh = length(h);
lg = length(g);
for j = 1:J+1
lhj = 2^j*(lh-1)+1;
lgj = 2^j*(lg-1)+1;
hj(1:lhj)=0;
gj(1:lgj)=0;
for n = 1:lh
hj(2^j*(n-1)+1)=h(n);
end
for n = 1:lg
gj(2^j*(n-1)+1)=g(n);
end
a(:,:,1,j+1) = conv2(hj,hj,a(:,:,1,j),'same');
dx(:,:,1,j+1) = conv2(delta,gj,a(:,:,1,j),'same');
dy(:,:,1,j+1) = conv2(gj,delta,a(:,:,1,j),'same');
x = dx(:,:,1,j+1);
y = dy(:,:,1,j+1);
dj(:,:,1,j+1) = sqrt(x.^2+y.^2);
I1 = imadjust(dj(:,:,1,j+1),stretchlim(dj(:,:,1,j+1)),[0 1]);figure;imshow(I1);
end
二维FIR的特定角度边缘检测
% 输入图像,并将其转化成灰度图像
I=imread('qipan.jpg');
I=rgb2gray(I);
% 构造卷积核
%% 提取右侧上方边缘
F1=[-1 0 0 -1 -1
1 1 1 0 0];
% 进行卷积运算
A1=conv2(double(I),double(F1));
% 转换成8位无符号整型并显示
A1=uint8(A1);
figure(1);imshow(A1);
% 构造卷积核
%% 提取左侧上方边缘
F2=[-1 -1 0 0 -1
0 0 1 1 1];
% 进行卷积运算
A2=conv2(double(I),double(F2));
% 转换成8位无符号整型并显示
A2=uint8(A2);
figure(2);imshow(A2);
运用FIR滤波器可以检测任意角度的边缘
function e = straightline(f,alpha)
%% 功能:检测特定角度的边缘
%% 输入:f-待检测的图像
%% alpha-检测角度
%% 1表示H垂直方向
%% 2表示V水平方向
%% 3表示45度
%% 4表示-45度
f = im2double(f);
%% 构造卷积核
H = [-1 -1 -1;2 2 2;-1 -1 -1];
V = [-1 2 -1;-1 2 -1;-1 2 -1];
P45 = [-1 -1 2;-1 2 -1;2 -1 -1];
M45 = [2 -1 -1;-1 2 -1;-1 -1 2];
switch(alpha)
case 1
e = imfilter(f,H);
case 2
e = imfilter(f,V);
case 3
e = imfilter(f,P45);
case 4
e = imfilter(f,M45);
otherwise
e = ones(size(f));
fprintf('请检测输入:\nalpha-检测角度\n1表示H垂直方向\n2表示V水平方向\n3表示45度\n4表示-45度\n');
end
close all;clear all;clc;
f=imread('qipan.jpg');
f=rgb2gray(f);
%% 输入:f-待检测的图像
%% alpha-检测角度
%% 1表示H垂直方向
%% 2表示V水平方向
%% 3表示45度
%% 4表示-45度
e1 = straightline(f,1);
e2 = straightline(f,2);
e3 = straightline(f,3);
e4 = straightline(f,4);
figure(1);imshow(f);
figure(2);imshow(e1);
figure(3);imshow(e2);
figure(4);imshow(e3);
figure(5);imshow(e4);
基于多尺度形态学梯度的边缘检测
Canny、Sobel算子通过计算图像中局部小区域的差分来实现边缘检测。这类边缘检测对噪声比较敏感,并且常常会在检测边缘的同时加强噪声。而形态边缘检测器主要利用形态梯度的概念,虽然对噪声也比较敏感,但不会加强噪声。
% 读入并显示原始图像
I=imread('hehua.jpg');
grayI=rgb2gray(I);
figure,imshow(grayI)
% 利用单尺度形态学梯度进行边缘检测
se=strel('square',3);
grad=imdilate(grayI,se)-imerode(grayI,se);
figure,imshow(grad)
% 利用多尺度形态学梯度进行边缘检测
se1=strel('square',1);
se2=strel('square',3);
se3=strel('square',5);
se4=strel('square',7);
grad1=imerode((imdilate(grayI,se2)-imerode(grayI,se2)),se1);
grad2=imerode((imdilate(grayI,se3)-imerode(grayI,se3)),se2);
grad3=imerode((imdilate(grayI,se4)-imerode(grayI,se4)),se3);
multiscaleGrad=(grad1+grad2+grad3)/3;
figure,imshow(multiscaleGrad)
斑点特征检测
- LoG斑点
- DoH斑点
- Gilles斑点
斑点检测是数字图像处理研究的重要内容,它是区域检测的一种特例,是许多特征生成、目标识别等方法的重要预处理环节。斑点通常是指与周围有着颜色和差别的区域。
LoG斑点(高斯拉普拉斯算子)
计算图像在不同尺度下的离散拉普拉斯响应值,然后,检测位置空间中的每个点,如果该点的拉普拉斯响应值都大于或小于其他26个立方空间的值,那么该点就是被检测到的图像斑点。
close all;clear all;clc;
%% 运行时间较长
img=imread('sunflower.jpg');
imshow(img)
pt=log_Blob(rgb2gray(img));
draw(img,pt,'LoG Lindeberg');
function [points] = log_Blob(img,o_nb_blobs)
% 功能:提取LoG斑点
% 输入:
% img –输入的图像
% o_nb_blobs -需要检测的斑点区域的数量
% 输出:
% points -检测出的斑点
% 参考文献:
% Lindeberg, T. Feature Detection with Automatic Scale Selection
% IEEE Transactions Pattern Analysis Machine Intelligence, 1998, 30,
% 77-116
% 输入图像
img = double(img(:,:,1));
% 设定检测到斑点的数量
if nargin==1
nb_blobs = 120;
else
nb_blobs = o_nb_blobs;
end
% 设定LoG参数
sigma_begin = 2;
sigma_end = 15;
sigma_step = 1;
sigma_array = sigma_begin:sigma_step:sigma_end;
sigma_nb = numel(sigma_array);
% 变量
img_height = size(img,1);
img_width = size(img,2);
% 计算尺度规范化高斯拉普拉斯算子
snlo = zeros(img_height,img_width,sigma_nb);
for i=1:sigma_nb
sigma = sigma_array(i);
snlo(:,:,i) = sigma*sigma*imfilter(img,fspecial('log', floor(6*sigma+1), sigma),'replicate');
end
% 搜索局部极值
snlo_dil = imdilate(snlo,ones(3,3,3));
blob_candidate_index = find(snlo==snlo_dil);
blob_candidate_value = snlo(blob_candidate_index);
[tmp,index] = sort(blob_candidate_value,'descend');
blob_index = blob_candidate_index( index(1:min(nb_blobs,numel(index))) );
[lig,col,sca] = ind2sub([img_height,img_width,sigma_nb],blob_index);
points = [lig,col,3*reshape(sigma_array(sca),[size(lig,1),1])];
end
function draw(img,pt,str)
% 功能:在图像中绘制出特征点
% 输入:
% img –输入的图像
% pt-检测出的特征点的坐标
% str-在图上显示的名称
figure('Name',str);
imshow(img);
hold on;
axis off;
switch size(pt,2)
case 2
s = 2;
for i=1:size(pt,1)
rectangle('Position',[pt(i,2)-s,pt(i,1)-s,2*s,2*s],'Curvature',[0 0],'EdgeColor','b','LineWidth',2);
end
case 3
for i=1:size(pt,1)
rectangle('Position',[pt(i,2)-pt(i,3),pt(i,1)-pt(i,3),2*pt(i,3),2*pt(i,3)],'Curvature',[1,1],'EdgeColor','w','LineWidth',2);
end
end
end
DoH斑点
Gilles斑点
该检测算法基于图像局部纹理特征对斑点进行检测。图像的局部熵值是衡量数字图像局部纹理特征的度量,因此Gilles斑点检测的核心思想是:求待检测图像的局部熵值之后,检测其局部极值。检测的具体步骤如下:
- 建立圆形掩模
- 在图像中求局部邻域(与掩模区域大小相同)的熵值
- 求局部熵的局部极值
- 与设定的阈值相比较,大于阈值的位置便为斑点位置
function points = gilles(im,o_radius)
% 功能:提取Gilles斑点
% 输入:
% im –输入的图像,灰度图
% o_radius -斑点检测半径(可选)
% 输出:
% points -检测出的斑点
%
% 参考文献:
% S. Gilles, Robust Description and Matching of Images. PhD thesis,
% Oxford University, Ph.D. thesis, Oxford University, 1988.
im = im(:,:,1);
% 变量
if nargin==1
radius = 10;
else
radius = o_radius;
end
% 建立掩模(mask)区域
mask = fspecial('disk',radius)>0;
% 计算掩模区域的局部熵值
loc_ent = entropyfilt(im,mask);%% 高版本Matlab
% 寻找局部最值
[l,c,tmp] = findLocalMaximum(loc_ent,radius);
% 超过阈值的斑点确定为所要提取的斑点
[l,c] = find(tmp>0.95*max(tmp(:)));
points = [l,c,repmat(radius,[size(l,1),1])];
end
function [row,col,max_local] = findLocalMaximum(val,radius)
% 功能:查找邻域极大值
% 输入:
% val -NxM 矩阵;
% radius –邻域半径;
% 输出:
% row –邻域极大值的行坐标;
% col – 邻域极大值的列坐标;
% max_local-邻域极大值。
mask = fspecial('disk',radius)>0;
nb = sum(mask(:));
highest = ordfilt2(val, nb, mask);
second_highest = ordfilt2(val, nb-1, mask);
index = highest==val & highest~=second_highest;
max_local = zeros(size(val));
max_local(index) = val(index);
[row,col] = find(index==1);
end
角点特征检测
何谓角点?
现实生活中的道路和房屋的拐角、道路十字交叉口和丁字路口等体现在图像中,就是图像的角点。对角点可以从两个不同的角度定义:角点是两个边缘的交点、角点是邻域内具有两个主方向的特征点。角点具有旋转不变性,尺度不变性、仿射不变性和光照亮度不变性。角点检测分两类:基于图像边缘的检测方法、基于图像灰度的检测方法。前者往往需要对图像边缘进行编码,这在很大程度上依赖于图像的分割和边缘提取,具有较大的计算量,一旦待检测目标局部发生变化,很可能导致操作失败。后者通过计算点的曲率及梯度来检测角点,避免了第一类方法存在的缺陷,是目前研究的重点,主要有:Moravec算子、Forstner算子、Harris算子、SUSAN算子等。
Harris角点
- 计算图像x、y两个方向的梯度Ix、Iy
- 计算图像两个方向梯度的乘积
- 使用高斯函数对Ix.^2、Iy.^2、Ixy进行高斯加权,生成矩阵M的元素A、B、C
- 计算每个像元的Harris响应值R,并对小于某阈值的R置为0
- 在3X3或者5X5的邻域进行非极大值抑制,局部极大值点即为图像角点
close all;clear all;clc;
in_img=imread('long.jpg');
[posr,posc]=Harris1(in_img,0.04);
function [posr, posc]=Harris1(in_image,a)
% 功能:检测图像的Harris角点
% 输入:in_image-待检测的RGB图像数组
% a-角点参数响应,取值范围为:0.04~0.06
% 输出:posr-所检测出角点的行坐标向量
% posc-所检测出角点的列坐标向量
% 将RGB图像转化成灰度图像
in_image=rgb2gray(in_image);
% unit8型转化为双精度double64型
ori_im=double(in_image);
%%%%%%计算图像在x、y 两个方向的梯度%%%%%%
% x方向梯度算子模板
fx = [-1 0 1];
% x方向滤波
Ix = filter2(fx,ori_im);
% y方向梯度算子
fy = [-1;0;1];
% y方向滤波
Iy = filter2(fy,ori_im);
%%%%%%计算两个方向的梯度乘积%%%%%%
Ix2 = Ix.^2;
Iy2 = Iy.^2;
Ixy = Ix.*Iy;
%%%%%%使用高斯函数对梯度乘积进行加权%%%%%%
% 产生7*7的高斯窗函数,sigma=2
h= fspecial('gaussian',[7 7],2);
Ix2 = filter2(h,Ix2);
Iy2 = filter2(h,Iy2);
Ixy = filter2(h,Ixy);
%%%%%%计算每个像元的Harris响应值%%%%%%
[height,width]=size(ori_im);
R = zeros(height,width);
% 像素(i,j)处的Harris响应值
for i = 1:height
for j = 1:width
M = [Ix2(i,j) Ixy(i,j);Ixy(i,j) Iy2(i,j)];
R(i,j) = det(M)-a*(trace(M))^2;
end
end
%%%%%%去掉小于阈值的Harris响应值%%%%%%
Rmax=max(max(R));
% 阈值
t=0.01* Rmax;
for i = 1:height
for j = 1:width
if R(i,j)<t
R(i,j) = 0;
end
end
end
%%%%%%进行3×3邻域非极大值抑制%%%%%%
% 进行非极大抑制,窗口大小3*3
corner_peaks=imregionalmax(R);
countnum=sum(sum(corner_peaks));
%%%%%%显示所提取的Harris角点%%%%%%
% posr是用于存放行坐标的向量
[posr, posc] = find(corner_peaks== 1);
% posc是用于存放列坐标的向量
figure(1);imshow(in_image);
hold on
for i = 1 : length(posr)
plot(posc(i),posr(i),'r+');
end
function [row,col,max_local] = findLocalMaximum(val,radius)
% 功能:查找邻域极大值
% 输入:
% val -NxM 矩阵;
% radius –邻域半径;
% 输出:
% row –邻域极大值的行坐标;
% col – 邻域极大值的列坐标;
% max_local-邻域极大值。
mask = fspecial('disk',radius)>0;
nb = sum(mask(:));
highest = ordfilt2(val, nb, mask);
second_highest = ordfilt2(val, nb-1, mask);
index = highest==val & highest~=second_highest;
max_local = zeros(size(val));
max_local(index) = val(index);
[row,col] = find(index==1);
end
还可以调用如下函数来检测图像的Harris角点特征:
C = cornermetric(I,'Harris');
Harris-Laplace角点检测
close all;clear all;clc;
%% 运行时间长
img=imread('door.jpg');
img=rgb2gray(img);
points=harrislaplace(img);
draw(img,points,'角点检测');
function points = harrislaplace(img)
% 功能:提取Harris-Laplace角点
% 输入:img-输入的RGB图像
% 输出:points-检测出的角点矩阵
% 参考文献:
% ==========
% K. Mikolajczyk and C. Schmid. Scale & affine invariant interest point % detectors.
% International Journal of Computer Vision, 2004
% 图像参数
img = double(img(:,:,1));
img_height = size(img,1);
img_width = size(img,2);
% 尺度参数
sigma_begin = 1.5;
sigma_step = 1.2;
sigma_nb = 13;
sigma_array = (sigma_step.^(0:sigma_nb-1))*sigma_begin;
% 第一部分:提取Harris角点
harris_pts = zeros(0,3);
for i=1:sigma_nb
% 尺度
% 积分尺度
s_I = sigma_array(i);
% 微分尺度
s_D = 0.7*s_I;
% 微分掩模
x = -round(3*s_D):round(3*s_D);
dx = x .* exp(-x.*x/(2*s_D*s_D)) ./ (s_D*s_D*s_D*sqrt(2*pi));
dy = dx';
% 图像微分
Ix = conv2(img, dx, 'same');
Iy = conv2(img, dy, 'same');
% 自相关矩阵
g = fspecial('gaussian',max(1,fix(6*s_I+1)), s_I);
Ix2 = conv2(Ix.^2, g, 'same');
Iy2 = conv2(Iy.^2, g, 'same');
Ixy = conv2(Ix.*Iy, g, 'same');
k = 0.06; cim = (Ix2.*Iy2 - Ixy.^2) - k*(Ix2 + Iy2).^2;
% 查询邻域极值
[l,c,max_local] = findLocalMaximum(cim,3*s_I);
% 设定局部邻域极值阈值
t = 0.2*max(max_local(:));
% 查找大于邻域极值阈值的点
[l,c] = find(max_local>=t);
n = size(l,1);
harris_pts(end+1:end+n,:) = [l,c,repmat(i,[n,1])];
end
%%%%%%第二部分: LAPLACE变换%%%%%%
% 计算尺度归一化Laplace算子
laplace_snlo = zeros(img_height,img_width,sigma_nb);
for i=1:sigma_nb
% 尺度
s_L = sigma_array(i);
laplace_snlo(:,:,i) = s_L*s_L*imfilter(img,fspecial('log', floor(6*s_L+1), s_L),'replicate');
end
% 检测每个特征点在某一尺度LoG相应是否达到最大
n = size(harris_pts,1);
cpt = 0;
points = zeros(n,3);
for i=1:n
l = harris_pts(i,1);
c = harris_pts(i,2);
s = harris_pts(i,3);
val = laplace_snlo(l,c,s);
if s>1 && s<sigma_nb
if val>laplace_snlo(l,c,s-1) && val>laplace_snlo(l,c,s+1)
cpt = cpt+1;
points(cpt,:) = harris_pts(i,:);
end
elseif s==1
if val>laplace_snlo(l,c,2)
cpt = cpt+1;
points(cpt,:) = harris_pts(i,:);
end
elseif s==sigma_nb
if val>laplace_snlo(l,c,s-1)
cpt = cpt+1;
points(cpt,:) = harris_pts(i,:);
end
end
end
points(cpt+1:end,:) = [];
points(:,3) = 3*sigma_array(points(:,3));
end
function [row,col,max_local] = findLocalMaximum(val,radius)
% 功能:查找邻域极大值
% 输入:
% val -NxM 矩阵;
% radius –邻域半径;
% 输出:
% row –邻域极大值的行坐标;
% col – 邻域极大值的列坐标;
% max_local-邻域极大值。
mask = fspecial('disk',radius)>0;
nb = sum(mask(:));
highest = ordfilt2(val, nb, mask);
second_highest = ordfilt2(val, nb-1, mask);
index = highest==val & highest~=second_highest;
max_local = zeros(size(val));
max_local(index) = val(index);
[row,col] = find(index==1);
end
function draw(img,pt,str)
% 功能:在图像中绘制出特征点
% 输入:
% img –输入的图像
% pt-检测出的特征点的坐标
% str-在图上显示的名称
figure('Name',str);
imshow(img);
hold on;
axis off;
switch size(pt,2)
case 2
s = 2;
for i=1:size(pt,1)
rectangle('Position',[pt(i,2)-s,pt(i,1)-s,2*s,2*s],'Curvature',[0 0],'EdgeColor','b','LineWidth',2);
end
case 3
for i=1:size(pt,1)
rectangle('Position',[pt(i,2)-pt(i,3),pt(i,1)-pt(i,3),2*pt(i,3),2*pt(i,3)],'Curvature',[1,1],'EdgeColor','w','LineWidth',2);
end
end
end
尺度不变特征提取
主要介绍SIFT和SURF特征点的提取。
SIFT特征提取
尺度不变特征变换(SIFT)是一种图像特征提取与描述算法。与1999年提出,2004年完善。可以处理两幅图像之间发生平移、旋转、尺度变化、光照变化情况下的特征匹配问题,并能在一定程度上对视角变化、仿射彼岸花也具备较为稳定的特征匹配能力。一幅图像的SIFT特征向量的生成主要包括4步:尺度空间极值检测、关键点位置及尺度确定、关键点方向确定、特征向量生成。
SURF特征描述算子
SIFT特征描述算子在生成特征矢量时使用的是高斯图像,而SURF特征描述算子在生成特征矢量时使用的则是积分图像。这样做的目的就是要充分利用在特征点检测时形成的中间结果(积分图像),避免在特征矢量生成时对图像进行重复运算。
应用
- 基于尺度不变特征点的目标识别
- 基于尺度不变特征点的图像拼接
此博客均属原创或译文,欢迎转载但请注明出处 GithubPage:https://zhangquan1995.github.io