【问题标题】:neighborhood radius in an image图像中的邻域半径
【发布时间】:2012-08-05 01:43:07
【问题描述】:

我有一张图像 (200x200),想在具有预定义半径的特定点中查找邻域位置。例如,半径为 5,我在一个点周围有 25 个点。 MATLAB能做到吗?问题在于图像的边缘并不总是 25 个点,程序应该只找到该半径内的点。这些点可以从 1(角)到 25(图像中心)变化

【问题讨论】:

标签: matlab image-processing


【解决方案1】:

这是一个例子:

%# sample grayscale image
img = imread('cameraman.tif');
[imgH,imgW,~] = size(img);

%# circle params
t = linspace(0, 2*pi, 50);   %# approximate circle with 50 points
r = 80;                      %# radius
c = [100 130];               %# center

%# get circular mask
BW = poly2mask(r*cos(t)+c(1), r*sin(t)+c(2), imgH, imgW);

%# show cropped image
imshow( immultiply(img,BW) )
axis on

这将很好地处理边缘情况。使用 POLY2MASK 的优点是它以亚像素精度计算掩码(请阅读函数文档中的算法部分),前提是您使用了足够多的点来逼近圆。

【讨论】:

  • 如果您无法访问图像处理工具箱,您可以使用 MESHGRID/NDGRID 执行类似操作
  • 非常感谢 Amro。只有两个问题:1)我怎样才能把圆形变成方形,2)如果我有一个 3D 矩阵,那我该怎么办?
  • @Sam: 1) 方形遮罩很简单:mask = false(imgH,imgW); mask(100:200,100:200) = true; 2) 如果您有 RGB 图像,您可以简单地沿第三维复制遮罩 repmat(mask,[1 1 3])(假设所有通道都被遮罩相同,否则分别处理每个 R、G、B 通道,然后与 cat(3,R,G,B) 组合回来
  • @Amro:实际上我有一个 3D 矩阵(100x100x50),我想找到该矩阵上一个点的邻域的位置(或索引)。例如,如果我将立方视为所需的邻域,那么在中心我可以说我的邻域是 (i-size_of_cubic/2:i+size_of_cubic,j-size_of_cubic/2:j+size_of_cubic,k-size_of_cubic/2 :k+size_of_cubic)。我需要一个可以为我做的函数,就像你的圆函数可以遇到角落(在角落里我只有四分之一立方。谢谢你的帮助
  • @Sam:由于问题被标记为图像处理,我假设您正在处理图像。 “半径”也让我认为您想要一个圆形社区,但现在我明白这不是您的意思(插图会有所帮助)......无论如何,请查看以下两个答案,我认为它们应该有所帮助(一个用于 2D 情况,另一个用于 3D 情况):MATLAB moving a point in the XY plane3 dimensional matrices
【解决方案2】:

根据 cmets 中的讨论,我正在添加另一个解决方案。对于给定的点,我们计算指定步数内的相邻点(半径,如果你愿意的话)。这在 2D 和 3D 情况下均显示。

二维矩阵

siz = [10 15];                         %# matrix size
p = [5 10];                            %# 2D point location

%# neighboring points
k = 2;                                 %# radius size
[sx,sy] = ndgrid(-k:k,-k:k);           %# steps to get to neighbors
xy = bsxfun(@plus, p, [sx(:) sy(:)]);  %# add shift
xy = bsxfun(@min, max(xy,1), siz);     %# clamp coordinates within range
xy = unique(xy,'rows');                %# remove duplicates
xy(ismember(xy,p,'rows'),:) = [];      %# remove point itself

%# show solution
figure
line(p(1), p(2), 'Color','r', ...
    'LineStyle','none', 'Marker','.', 'MarkerSize',50)
line(xy(:,1), xy(:,2), 'Color','b', ...
    'LineStyle','none', 'Marker','.', 'MarkerSize',20)
grid on, box on, axis equal
axis([1 siz(1) 1 siz(2)])
xlabel x, ylabel y


3D 矩阵

siz = [10 15 8];                              %# matrix size
p = [5 10 4];                                 %# 3D point location

%# neighboring points
k = 2;                                        %# radius size
[sx,sy,sz] = ndgrid(-k:k,-k:k,-k:k);          %# steps to get to neighbors
xyz = bsxfun(@plus, p, [sx(:) sy(:) sz(:)]);  %# add shift
xyz = bsxfun(@min, max(xyz,1), siz);          %# clamp coordinates within range
xyz = unique(xyz,'rows');                     %# remove duplicates
xyz(ismember(xyz,p,'rows'),:) = [];           %# remove point itself

%# show solution
figure
line(p(1), p(2), p(3), 'Color','r', ...
    'LineStyle','none', 'Marker','.', 'MarkerSize',50)
line(xyz(:,1), xyz(:,2), xyz(:,3), 'Color','b', ...
    'LineStyle','none', 'Marker','.', 'MarkerSize',20)
view(3), grid on, box on, axis equal
axis([1 siz(1) 1 siz(2) 1 siz(3)])
xlabel x, ylabel y, zlabel z

HTH

【讨论】:

  • 非常感谢 Amro :) 的大力帮助。
  • @Amro,感谢您的代码 Amro!我正在尝试优化一个需要花费大量时间来计算的函数,它基于循环邻域。更准确地说,我有不同的圆形邻域,并且在每个邻域内部,我想计算它们下面的像素值的平均值、标准差和中值。这是在 DoG 比例表示的上下文中完成的。圆形过滤器的大小由与特定比例关联的半径给出 (scalespace_radii):pastebin.com/WkS5ShMf 欢迎任何关于如何改进计算的建议!
  • @Tin:我看了看,但在我看来,代码中的三重循环是不可避免的!尝试对这些 for 循环进行矢量化只会导致创建巨大的中间矩阵(例如,通过在矢量化调用中一次计算所有像素的 distance)。我在这里和那里进行了一些细微的更改以提高性能(例如更好的预分配、添加提前退出测试以及将一些计算移到循环之外)。如果你先创建一个新的问题页面,显示我的版本会更容易:)
  • @Tin:最后,这种计算的计算量很大,我能想到的真正提高性能的唯一方法是编写一个 MEX 函数(用 C/C++ 语言实现)。 .
猜你喜欢
  • 2014-05-09
  • 1970-01-01
  • 2023-04-01
  • 2018-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-31
  • 2012-11-10
相关资源
最近更新 更多