如何在 MATLAB 中对图像的边缘进行重采样?
How to resample an edge of an image in MATLAB?
我试图减少检测到的图像边缘的点数,但没有获得好的结果。我希望结果恰好包含 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
你可以做的是使用 bwboundaries
来追踪对象/边缘的边界,然后从这些点数组中采样以减少边缘点的数量。跟踪是按顺时针顺序进行的,因此您可以确定,当您从此数组中进行子采样时,您会得到一种表面上的顺序。但是,bwboundaries
也 returns outer 和 inner 等高线边界,所以你只需要一定量的痕迹输出。这个以后再说。
bwboundaries
适用于多个对象,因此您所要做的就是遍历每个对象,对边缘点进行采样并将其写入输出结果。请注意,使用 bwboundaries
甚至不需要找到边...只要对象是干净的就没有必要。但是,我不确定你这样做的目的,所以让我们只对边缘检测结果进行操作。
假设我们有以下示例:
>> A = false(256, 256);
>> A(100:170,100:170) = true;
>> A(3:40,3:40) = true;
>> A(190:220,200:230) = true;
>> imshow(A)
我们得到这张图片:
如果我们执行边缘检测:
>> B = edge(A, 'canny');
>> imshow(B);
我们会得到这个:
现在,如果你想进行子采样,你可以这样调用 bwboundaries
:
[bound,L,N] = bwboundaries(B);
bwboundaries
returns 边界元胞数组 bound
,其中每个元胞都是定义边界的空间坐标 N x 2
数组。第一列是行位置,第二列是边界点的列位置。 L
是一个标签矩阵,告诉你每个边界属于哪个点。我们不需要这个用于您的目的,但我不妨谈谈它。 N
是最重要的参数。这定义了有多少 object 边界。这也告诉您 bound
的前 N
个单元格告诉您那些属于外部对象边界。
因此,假设您的边缘图像存储在 B
中,您可以执行以下操作对边缘点进行子采样并将它们放入新矩阵中。此外,您声明您希望每条边有 200 个点。让我们将该参数定义为 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
out
将包含二次采样的边缘图像。为了说明我们做对了,让我们创建一个新的 RGB 图像,其中我们的边缘和二次采样边缘点彼此重叠,其中二次采样边缘为红色:
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);
这就是我们得到的 (zoomed-in):
如您所见,顶部和底部矩形显示了完整的边缘点,因为边缘点少于 200 个。然而,中间的那个是稀疏采样的,因为有 200 多个边缘点,但现在我们只显示其中的 200 个。
如果您想要一个功能来帮助您实现这一点,您可以使用以下内容。我基本上复制了上面的所有代码,输入是带边缘的二值图像,输出是带子采样边缘的二值图像:
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
如果要调用此函数,只需执行以下操作:
out = subsample_edge(B);
我试图减少检测到的图像边缘的点数,但没有获得好的结果。我希望结果恰好包含 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
你可以做的是使用 bwboundaries
来追踪对象/边缘的边界,然后从这些点数组中采样以减少边缘点的数量。跟踪是按顺时针顺序进行的,因此您可以确定,当您从此数组中进行子采样时,您会得到一种表面上的顺序。但是,bwboundaries
也 returns outer 和 inner 等高线边界,所以你只需要一定量的痕迹输出。这个以后再说。
bwboundaries
适用于多个对象,因此您所要做的就是遍历每个对象,对边缘点进行采样并将其写入输出结果。请注意,使用 bwboundaries
甚至不需要找到边...只要对象是干净的就没有必要。但是,我不确定你这样做的目的,所以让我们只对边缘检测结果进行操作。
假设我们有以下示例:
>> A = false(256, 256);
>> A(100:170,100:170) = true;
>> A(3:40,3:40) = true;
>> A(190:220,200:230) = true;
>> imshow(A)
我们得到这张图片:
如果我们执行边缘检测:
>> B = edge(A, 'canny');
>> imshow(B);
我们会得到这个:
现在,如果你想进行子采样,你可以这样调用 bwboundaries
:
[bound,L,N] = bwboundaries(B);
bwboundaries
returns 边界元胞数组 bound
,其中每个元胞都是定义边界的空间坐标 N x 2
数组。第一列是行位置,第二列是边界点的列位置。 L
是一个标签矩阵,告诉你每个边界属于哪个点。我们不需要这个用于您的目的,但我不妨谈谈它。 N
是最重要的参数。这定义了有多少 object 边界。这也告诉您 bound
的前 N
个单元格告诉您那些属于外部对象边界。
因此,假设您的边缘图像存储在 B
中,您可以执行以下操作对边缘点进行子采样并将它们放入新矩阵中。此外,您声明您希望每条边有 200 个点。让我们将该参数定义为 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
out
将包含二次采样的边缘图像。为了说明我们做对了,让我们创建一个新的 RGB 图像,其中我们的边缘和二次采样边缘点彼此重叠,其中二次采样边缘为红色:
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);
这就是我们得到的 (zoomed-in):
如您所见,顶部和底部矩形显示了完整的边缘点,因为边缘点少于 200 个。然而,中间的那个是稀疏采样的,因为有 200 多个边缘点,但现在我们只显示其中的 200 个。
如果您想要一个功能来帮助您实现这一点,您可以使用以下内容。我基本上复制了上面的所有代码,输入是带边缘的二值图像,输出是带子采样边缘的二值图像:
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
如果要调用此函数,只需执行以下操作:
out = subsample_edge(B);