我正在使用MATLAB。我想使用canny方法进行边缘检测。但我需要对角线的边缘或仅40到50度角的边缘。我怎么能这样做?
答案 0 :(得分:2)
你需要在互联网上自己编写canny边缘检测器的代码(你会得到很多实现)。然后,您将在第二步中计算梯度幅度和梯度方向。在那里你需要滤除角度和相应的大小。
希望这会对你有所帮助。
答案 1 :(得分:0)
我已经回答了一个类似的问题,关于如何使用Matlab的edge
函数来找到Canny(Orientational Canny Edge Detection)的定向边,但我也想尝试Avijit建议的自定义实现。
从图像开始,我将使用内置的演示图像。
A = im2double(rgb2gray(imread('peppers.png')));
高斯滤波器
A_filter = imgaussfilt(A);
Sobel Edge Detection - 我们无法使用内置实现(edge(A_filter, 'Sobel')
),因为我们需要边缘角度,而不仅仅是边缘位置,因此我们实现了自己的运算符。
一个。卷积找到定向梯度
%These filters measure the difference in values between vertically or horizontally adjacent pixels.
%Effectively, this finds vertical and horizontal gradients.
vertical_filter = [-1 0 1; -2 0 2; -1 0 1];
horizontal_filter = [-1 -2 -1; 0 0 0; 1 2 1];
A_vertical = conv2(A_filter, vertical_filter, 'same');
A_horizontal = conv2(A_filter, horizontal_filter, 'same');
湾计算角度
A_angle = arctan(A_vertical./A_horizontal);
在此步骤中,我们传统上按方向(0°,45°,90°,135°)对边缘进行分类,但由于您只需要40到50度之间的对角线边缘,我们将保留这些边缘并丢弃其余的。
% I lowered the thresholds to include more pixels
% But for your original post, you would use 40 and 50
lower_angle_threshold = 22.5;
upper_angle_threshold = 67.5;
diagonal_map = zeros(size(A), 'logical');
diagonal_map (A_angle>(lower_angle_threshold*pi/180) & A_angle<(upper_angle_threshold*pi/180)) = 1;
对剩余边缘执行非最大抑制 - 这是适应不同角度的最难部分。为了找到确切的边缘位置,比较两个相邻的像素:对于0°边缘,比较东西向,45°西南像素到东北像素,90°比较南北,和135°北 - 西像素到东南像素。
由于您所需的角度接近45°,我只是使用了西南方向,但是如果您想要10°到20°,那么您必须更多地考虑这些比较。
non_max = A_sobel;
[n_rows, n_col] = size(A);
%For every pixel
for row = 2:n_rows-1
for col = 2:n_col-1
%If we are at a diagonal edge
if(diagonal_map(row, col))
%Compare north east and south west pixels
if(A_sobel(row, col)<A_sobel(row-1, col-1) || ...
A_sobel(row, col)<A_sobel(row+1, col+1))
non_max(row, col) = 0;
end
else
non_max(row, col) = 0;
end
end
end
带滞后的边缘跟踪 - 确定弱边缘像素是否足够接近(我使用3x3窗口)到强边缘像素。如果是,请将它们包含在边缘。如果没有,它们就是噪音;删除它们。
high_threshold = 0.5; %These thresholds are tunable parameters
low_threshold = 0.01;
weak_edge_pixels = non_max > low_threshold & non_max < high_threshold;
strong_edge_pixels = non_max > high_threshold;
final = strong_edge_pixels;
for row = 2:n_rows-1
for col = 2:n_col-1
window = strong_edge_pixels(row-1:row+1, col-1:col+1);
if(weak_edge_pixels(row, col) && any(window(:)))
final(row, col) = 1;
end
end
end
以下是我的结果。
如您所见,丢弃其他边缘方向对滞后步骤有非常不利的影响,因为检测到较少的强像素。调整high_threshold会有所帮助。另一种选择是使用所有边缘方向执行步骤5和6,然后使用diagonal_map提取对角线边缘。