Matlab亚像素边缘检测结果全黑问题解决
Matlab亚像素边缘检测结果全黑问题解决
在使用Matlab进行亚像素边缘检测时,有时会遇到检测结果为全黑图像的情况。这通常是由于亚像素插值点超出图像范围导致的。
问题代码示例:
% 读取图像
img = imread('lena.jpg');
gray_img = im2gray(img);
% 阈值化图像
threshold = graythresh(gray_img);
binary_img = imbinarize(gray_img, threshold);
% 提取边缘
edge_img = edge(binary_img,'canny');
% 计算Zernike矩
order =8; % Zernike矩的阶数
moments = Zernikmoment(edge_img, order);
% 亚像素检测边缘轮廓
subpixel_edge = subpixelext(edge_img, moments);
% 显示结果
figure;
subplot(1, 2, 1);
imshow(edge_img);
title('原始边缘图像');
subplot(1, 2, 2);
imshow(subpixel_edge);
title('亚像素检测边缘轮廓');
% Zernike矩计算函数
function [moments] = Zernikmoment(img, order)
[rows, cols] = size(img);
moments = zeros(order+1, order+1);
for p = 0:order
for q = 0:order
if mod(p-q, 2) == 0
R = zeros(rows, cols);
for x = 1:cols
for y = 1:rows
r = sqrt((x-cols/2)^2 + (y-rows/2)^2) / (cols/2);
if r <= 1
theta = atan2(y-rows/2, x-cols/2);
R(y, x) = ZernikeRadialPolynomial(p, q, r) * cos(q*theta);
end
end
end
moments(p+1, q+1) = sum(sum(img.*R)) * ((p+1)/(pi*(q+1)));
end
end
end
end
% Zernike径向多项式计算函数
function [R] = ZernikeRadialPolynomial(n, m, r)
R = zeros(size(r));
for s = 0:(n-abs(m))/2
c = (-1)^s * factorial(n-s) / (factorial(s) * factorial((n+abs(m))/2-s) * factorial((n-abs(m))/2-s));
R = R + c * r.^(n-2*s);
end
end
function [subpixel_edge] = subpixelext(edge_img, moments)
[rows, cols] = size(edge_img);
subpixel_edge = zeros(rows, cols);
for x = 2:(cols-1)
for y = 2:(rows-1)
if edge_img(y, x) == 1
dx = (moments(2, 1)*x + moments(2, 2)*y) / moments(1, 1);
dy = (moments(1, 2)*x + moments(2, 2)*y) / moments(1, 1);
% 亚像素插值
dx_floor = floor(dx);
dy_floor = floor(dy);
dx_frac = dx - dx_floor;
dy_frac = dy - dy_floor;
% 双线性插值
subpixel_edge(y, x) = (1-dx_frac)*(1-dy_frac)*edge_img(dy_floor, dx_floor) + ...
dx_frac*(1-dy_frac)*edge_img(dy_floor, dx_floor+1) + ...
(1-dx_frac)*dy_frac*edge_img(dy_floor+1, dx_floor) + ...
dx_frac*dy_frac*edge_img(dy_floor+1, dx_floor+1);
end
end
end
end
问题原因:
在上述代码中,亚像素插值部分没有对插值点是否在图像范围内进行判断,导致访问越界,结果图像出现全黑。
解决方法:
在进行双线性插值计算之前,添加对 dx_floor 和 dy_floor 的范围判断,确保插值点在图像范围内。
优化后的代码:
function [subpixel_edge] = subpixelext(edge_img, moments)
[rows, cols] = size(edge_img);
subpixel_edge = zeros(rows, cols);
for x = 2:(cols-1)
for y = 2:(rows-1)
if edge_img(y, x) == 1
dx = (moments(2, 1)*x + moments(2, 2)*y) / moments(1, 1);
dy = (moments(1, 2)*x + moments(2, 2)*y) / moments(1, 1);
% 亚像素插值
dx_floor = floor(dx);
dy_floor = floor(dy);
dx_frac = dx - dx_floor;
dy_frac = dy - dy_floor;
% 双线性插值
if dx_floor >= 1 && dx_floor+1 <= cols && dy_floor >= 1 && dy_floor+1 <= rows
subpixel_edge(y, x) = (1-dx_frac)*(1-dy_frac)*edge_img(dy_floor, dx_floor) + ...
dx_frac*(1-dy_frac)*edge_img(dy_floor, dx_floor+1) + ...
(1-dx_frac)*dy_frac*edge_img(dy_floor+1, dx_floor) + ...
dx_frac*dy_frac*edge_img(dy_floor+1, dx_floor+1);
else
subpixel_edge(y, x) = 0; % 超出范围,设为黑色
end
end
end
end
end
通过添加边界检查,可以避免插值点超出图像范围,从而解决亚像素边缘检测结果全黑的问题。
原文地址: https://www.cveoy.top/t/topic/fzNi 著作权归作者所有。请勿转载和采集!