如何在MATLAB中重新采样图像的边缘?

问题描述 投票:0回答:1

我试图减少图像的检测边缘的点数,但未获得良好的结果。我希望结果精确包含200个像素的边缘,但是必须精心选择这些点,以使形状保持非常清晰。我该怎么办?

这是我正在使用的示例图像:

以下是我编写的代码收到的一些结果:

已写代码

function y = echantillonnage(x)
contour_image = x;
[lignes,colonnes]=size(x);
n = nombre/200;
contour_image_200px = contour_image;
ok=0;
for i=1:lignes
    for j=1:colonnes
        if (contour_image_200px(i,j)>0 )
                ok=ok+1;
                if ( mod(ok,round(n))>0 )
                   contour_image_200px(i,j)=0;
                end                 
         end      
    end
end
figure,imshow(contour_image_200px);
%résultat
y = contour_image_200px;
end
image matlab image-processing edge-detection
1个回答
1
投票

您可以做的是使用bwboundaries跟踪对象/边缘的边界,然后从这些点数组中采样以减少边缘点的数量。跟踪是按顺时针顺序进行的,因此您可以确保在从该数组中进行子采样时,将获得相似的顺序。但是,bwboundaries还返回outerinner轮廓边界,因此您只需要从输出中获取一定量的迹线即可。我们稍后再讨论。

bwboundaries适用于多个对象,因此您要做的就是遍历每个对象,对边缘点进行采样并将其写入输出结果。请注意,使用bwboundaries甚至不需要找到边缘...只要对象是干净的,则没有必要。但是,我不确定您要做什么,因此,让我们仅对边缘检测到的结果进行操作即可。

假设我们有以下示例:

bwboundaries

我们得到这张图片:

<< img src =“ https://image.soinside.com/eyJ1cmwiOiAiaHR0cHM6Ly9pLnN0YWNrLmltZ3VyLmNvbS9EbllRUy5wbmcifQ==” alt =“在此处输入图像描述”>

如果执行边缘检测:

>> A = false(256, 256);
>> A(100:170,100:170) = true;
>> A(3:40,3:40) = true;
>> A(190:220,200:230) = true;
>> imshow(A)

我们会得到这个:

<< img src =“ https://image.soinside.com/eyJ1cmwiOiAiaHR0cHM6Ly9pLnN0YWNrLmltZ3VyLmNvbS9JNU5tZy5wbmcifQ==” alt =“在此处输入图像描述”>

现在,如果要进行二次采样,可以通过以下方式调用>> B = edge(A, 'canny'); >> imshow(B);

bwboundaries

[bound,L,N] = bwboundaries(B); 返回边界的单元格数组bwboundaries,其中每个单元格是定义边界的空间坐标的bound数组。第一列是行位置,第二列是边界点的列位置。 N x 2是一个标签矩阵,告诉您每个边界属于哪个点。我们不需要这个来满足您的目的,但是我不妨谈一谈。 L是最重要的参数。这定义了有多少object个边界。这也告诉您N的前N个单元格告诉您它们属于外部对象边界。

因此,假设边缘图像存储在bound中,您可以执行以下操作对边缘点进行二次采样并将其放入新矩阵中。另外,您还说过您希望每个边缘有200个点。让我们将该参数定义为B。但是,如果您的边缘小于此数量,则我将假定您只想选择所有边缘点。num_edge_points

out = false(size(B)); %// Initialize output image
num_edge_points = 200; %// Define number of edge points

%// For each object boundary
for idx = 1 : N
    boundary = bound{idx}; %// Get boundary

    %// Determine how many points we have
    num_pts = size(boundary,1);

    %// Generate indices for sampling the boundary
    %// If there are less than the minimum, just choose this amount
    if num_pts < num_edge_points
        ind = 1:num_pts;
    else
        ind = floor(linspace(1,num_pts,num_edge_points));
    end

    %// Subsample the edge points
    pts = boundary(ind,:);

    %// Mark points in output
    out(sub2ind(size(B), pts(:,1), pts(:,2))) = true;
end
将包含对边缘图像进行二次采样。为了说明我们做对了,让我们创建一个新的RGB图像,其中边缘和子采样边缘点彼此重叠,子采样边缘为红色:

out

这就是我们得到的(放大):

<< img src =“ https://image.soinside.com/eyJ1cmwiOiAiaHR0cHM6Ly9pLnN0YWNrLmltZ3VyLmNvbS80SWdJdi5wbmcifQ==” alt =“在此处输入图像描述”>

如您所见,顶部和底部矩形的完整边缘点显示为少于200个边缘点。但是,由于其中有200多个边缘点,因此中间的一个样本很少被采样,但是现在我们只显示其中200个。


如果您希望使用某个功能来帮助您实现此目的,可以使用以下内容。我基本上已经复制了上面的所有代码,并且输入是带有边缘的二进制图像,而输出是带有欠采样边缘的二进制图像:

out_red = 255*uint8(B); out_greenblue = out_red; out_greenblue(out) = 0; out_rgb = cat(3, out_red, out_greenblue, out_greenblue); imshow(out_rgb);

如果要调用此函数,只需执行:

function [out] = subsample_edge(B) %// Obtain boundaries for edge image [bound,L,N] = bwboundaries(B); out = false(size(B)); %// Initialize output image num_edge_points = 200; %// Define number of edge points %// For each object boundary for idx = 1 : N boundary = bound{idx}; %// Get boundary %// Determine how many points we have num_pts = size(boundary,1); %// Generate indices for sampling the boundary %// If there are less than the minimum, just choose this amount if num_pts < num_edge_points ind = 1:num_pts; else ind = floor(linspace(1,num_pts,num_edge_points)); end %// Subsample the edge points pts = boundary(ind,:); %// Mark points in output out(sub2ind(size(B), pts(:,1), pts(:,2))) = true; end end

© www.soinside.com 2019 - 2024. All rights reserved.