【數字影象處理】作業二 邊緣檢測與追蹤
阿新 • • 發佈:2018-12-10
作業二 邊緣檢測與追蹤
吳政億 151220129 [email protected]
(南京大學 電腦科學與技術系, 南京 210093)
邊緣檢測
在邊緣檢測中,我使用了sobel
,roberts
,prewitt
,marr
作為運算元,對每一種運算元調參,並進行了比較。
主體框架(marr單獨介紹)
在my_edge.m
中13~24行分別對應三個運算元的high與low引數,大於high的被識別為邊界,小於low的則被識別為非邊界,在low~high之間的則根據鄰域是否有邊界來決定是否是邊界。這樣可以排除一部分的孤立點與噪聲。
function output = my_edge(input_image)
input_image=im2double(input_image);
[M,N]=size(input_image);
SX = zeros(M,N);
SY = zeros(M,N);
% %sobel
% high = 0.3; % moon:0.3 others:1.5
% low = 0.2; % moon:0.2 others:0.5
% %roberts
% high = 0.09; % moon:0.09 key:0.4 cap:0.5
% low = 0.05; % moon:0.05 others:0.2
%prewitt
high = 0.25; % moon:0.25 others:0.8
low = 0.1; % moon:0.1 others:0.5
gray_image = zeros(M-2,N-2);
for i=2:M-1
for j = 2:N-1
% gray_image(i-1,j-1) = sobel(input_image(i-1,j-1),input_image(i-1,j),input_image(i-1,j+1),input_image(i,j-1),input_image(i,j),input_image(i,j+1),input_image(i+1,j-1),input_image(i+1,j),input_image(i+1,j+1));
% gray_image(i-1,j-1) = roberts(input_image(i-1,j-1),input_image(i-1,j),input_image(i-1,j+1),input_image(i,j-1),input_image(i,j),input_image(i,j+1),input_image(i+1,j-1),input_image(i+1,j),input_image(i+1,j+1));
gray_image(i-1,j-1) = prewitt(input_image(i-1,j-1),input_image(i-1,j),input_image(i-1,j+1),input_image(i,j-1),input_image(i,j),input_image(i,j+1),input_image(i+1,j-1),input_image(i+1,j),input_image(i+1,j+1));
end
end
edge_image = zeros(M-2,N-2);
for i = 1:M-2
for j = 1:N-2
if gray_image(i,j) > high
edge_image(i,j) = 1;
elseif gray_image(i,j) < low
edge_image(i,j) = 0;
elseif i==1 || j ==1 || i == M-2 || j == N-2
edge_image(i,j) = 0;
else
edge_image(i,j) = -1;
end
end
end
for i = 2:M-3
for j = 2:N-3
if edge_image(i,j) == -1
if edge_image(i-1,j-1) == 1 ||edge_image(i-1,j) == 1 ||edge_image(i-1,j+1) == 1 ||edge_image(i,j-1) == 1 ||edge_image(i,j+1) == 1 ||edge_image(i+1,j-1) == 1 ||edge_image(i+1,j) == 1 ||edge_image(i+1,j+1) == 1
edge_image(i,j) = 1;
else
edge_image(i,j) = 0;
end
end
end
end
output = logical(edge_image);
sobel運算元
function sobel_value = sobel(v1,v2,v3,v4,v5,v6,v7,v8,v9)
SX= -v1+v3-2*v4+2*v6-v7+v9;
SY= v1+2*v2+v3-v7-2*v8-v9;
sobel_value = sqrt(SX^2 + SY^2);
roberts運算元
function roberts_value = roberts(v1,v2,v3,v4,v5,v6,v7,v8,v9)
SX= abs(v9-v5);
SY= abs(v6-v8);
roberts_value = SX + SY;
prewitt運算元
function prewitt_value = prewitt(v1,v2,v3,v4,v5,v6,v7,v8,v9)
SX= -v1+v3-v4+v6-v7+v9;
SY= v1+v2+v3-v7-v8-v9;
prewitt_value = sqrt(SX^2 + SY^2);
Marr運算元
先對影象進行復制外邊界的值來擴充套件的卷積,然後通過零交叉點判斷邊緣,最後用線性插值的方法估計邊緣位置。
function output = my_edge_marr(input_image)
% input:gray image output:image edge logical
% marr
[m,n] = size(input_image);
e = false(m,n);
sigma = 2.5;
row = 2:m-1;
col=2:n-1;
op = fspecial('log',ceil(sigma*3) * 2 + 1,sigma);
op = op - sum(op(:))/numel(op); % make the op to sum to zero
b = imfilter(input_image,op,'replicate');
thresh = 0.75 * sum(abs(b(:)),'double') / numel(b);
% Look for the zero crossings
[r,c] = find(( b(row,col) < 0 & b(row,col+1) > 0 & abs( b(row,col)-b(row,col+1) ) > thresh )...
|(b(row,col-1) > 0 & b(row,col) < 0 & abs( b(row,col-1)-b(row,col) ) > thresh)...
|(b(row,col) < 0 & b(row+1,col) > 0 & abs( b(row,col)-b(row+1,col) ) > thresh)...
|(b(row-1,col) > 0 & b(row,col) < 0 & abs( b(row-1,col)-b(row,col) ) > thresh));
e((r+1) + c*m) = 1;
% check to see if there are any points where the LoG was precisely zero:
[rz,cz] = find( b(row,col)==0 );
if ~isempty(rz)
zero = (rz+1) + cz*m; % Linear index for zero points
zz = ((b(zero-1) < 0 & b(zero+1) > 0 & abs( b(zero-1)-b(zero+1) ) > 2*thresh)...
|(b(zero-1) > 0 & b(zero+1) < 0 & abs( b(zero-1)-b(zero+1) ) > 2*thresh)...
|(b(zero-m) < 0 & b(zero+m) > 0 & abs( b(zero-m)-b(zero+m) ) > 2*thresh)...
|(b(zero-m) > 0 & b(zero+m) < 0 & abs( b(zero-m)-b(zero+m) ) > 2*thresh));
e(zero(zz)) = 1;
end
output = e;
end
四者對比
Roberts
運算元定位比較精確,但由於不包括平滑,所以對於噪聲比較敏感。Prewitt
運算元和Sobel
運算元都是一階的微分運算元,而前者是平均濾波,後者是加權平均濾波且檢測的影象邊緣可能大於2個畫素。這兩者對灰度漸變低噪聲的影象有較好的檢測效果,但是對於混合多複雜噪聲的影象,處理效果就不理想了。Prewitt
和Sobel
運算元比Roberts
效果要好一些,因為前兩者參考了周圍8個畫素的灰度值,得到的資訊更廣。
Marr
運算元相比與上面三種非常突出,因為他考慮了梯度等因素,但是相比之下他被噪聲影響的更為明顯。
邊緣連結
由於邊緣連結的傳入引數是一個二值影象,我應用一個佇列將初始點入列,然後應用四鄰域與八鄰域兩種情況分別對其作邊緣連結,並返回所有連通分支上的點。 定義一個neighbour用來運算pix,即他的八/四鄰域所有點座標。
function output = my_edgelinking(binary_image, row, col)
[M,N]=size(binary_image);
tmp=[];
queue_head=1;
queue_tail=1;
neighbour=[-1 -1;-1 0;-1 1;0 -1;0 1;1 -1;1 0;1 1]; %8-neighbourhood
% neighbour=[-1 0;1 0;0 1;0 -1]; %4-neighbourhood
q{queue_tail}=[row col];
queue_tail=queue_tail+1;
[ser1 , ~]=size(neighbour);
num = 1;
while queue_head~=queue_tail
pix=q{queue_head};
tmp(num,1)=pix(1,1);
tmp(num,2)=pix(1,2);
num = num + 1;
for i=1:ser1
pix1=pix+neighbour(i,:);
if pix1(1)>=1 && pix1(2)>=1 &&pix1(1)<=M && pix1(2)<=N
if binary_image(pix1(1),pix1(2)) == true
binary_image(pix1(1),pix1(2)) = false;
q{queue_tail}=[pix1(1) pix1(2)];
queue_tail=queue_tail+1;
end
end
end
queue_head=queue_head+1;
end
output = tmp;