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_floordy_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

通过添加边界检查,可以避免插值点超出图像范围,从而解决亚像素边缘检测结果全黑的问题。

Matlab亚像素边缘检测结果全黑问题解决

原文地址: https://www.cveoy.top/t/topic/fzNi 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录