SUSAN算子既可以檢測角點也可以檢測邊緣,不過角點似乎比不過harris,邊緣似乎比不過Canny。不過思想還是有點意思的。
主要思想就是:首先做一個和原圖像等大的目標圖像。然后用一個圓形的模板,用模板去遍歷原圖像每個像素,把模板內的每個像素都和模板中心像素比較,如果灰度小於一個閾值,那么就對目標圖像當前和原圖像相同位置的像素加一,直到結束。目標圖像中在原圖像是角點的位置就會取局部極小,所以做一個反向的相減。img=max(img)-img,if img<g,這里的g也是自己給定的閾值,我這里取了2*max(img)/3這樣的閾值,g越大,得到的點就越多。這步之后角點的值就成為局部極大了。最后進行非極大抑制,去除一些雜點就行了。
代碼如下:
clear all; close all; clc; img=imread('i.jpg'); img=rgb2gray(img); imshow(img); [m n]=size(img); img=double(img); t=45; %模板中心像素灰度和周圍灰度差別的閾值,自己設置 usan=[]; %當前像素和周圍在像素差別在t以下的個數 %這里用了37個像素的模板 for i=4:m-3 %沒有在外圍擴展圖像,最終圖像會縮小 for j=4:n-3 tmp=img(i-3:i+3,j-3:j+3); %先構造7*7的模板,49個像素 c=0; for p=1:7 for q=1:7 if (p-4)^2+(q-4)^2<=12 %在其中篩選,最終模板類似一個圓形 % usan(k)=usan(k)+exp(-(((img(i,j)-tmp(p,q))/t)^6)); if abs(img(i,j)-tmp(p,q))<t %判斷灰度是否相近,t是自己設置的 c=c+1; end end end end usan=[usan c]; end end g=2*max(usan)/3; %確定角點提取的數量,值比較高時會提取出邊緣,自己設置 for i=1:length(usan) if usan(i)<g usan(i)=g-usan(i); else usan(i)=0; end end imgn=reshape(usan,[n-6,m-6])'; figure; imshow(imgn) %非極大抑制 [m n]=size(imgn); re=zeros(m,n); for i=2:m-1 for j=2:n-1 if imgn(i,j)>max([max(imgn(i-1,j-1:j+1)) imgn(i,j-1) imgn(i,j+1) max(imgn(i+1,j-1:j+1))]); re(i,j)=1; else re(i,j)=0; end end end figure; imshow(re==1);
后兩幅比第一幅小,我沒進行邊緣擴展。
原圖
未進行非極大抑制,似乎就是邊緣了
最后結果