快速复制属于圆圈的像素

时间:2015-08-10 08:26:10

标签: matlab image-processing vectorization

我有img格式的初始灰度图像double,其中包含相同半径和圆矢量的圆圈,圆心坐标为xy。我需要将属于圆圈的所有像素复制到数组cpix。到目前为止,我只得到了使用for循环的最钝的解决方案。有没有办法对这段代码进行矢量化或只是让它更快地运行?

% x(:) - vector with a few circles center X coordinates
% y(:) - vector with a few circles center Y coordinates
d = 27;                  %diameter
r = floor(d/2);          %radius
cpix = double(zeros(d,d,size(x,1)));

for iCent = 1:size(x,1)  %for each circle
    for ix = 1:d
        for iy = 1:d
            if ((ix-r)^2 + (iy-r)^2) < r^2
                cpix(iy,ix,iCent) = img(iy+y(iCent)-r,ix+x(iCent)-r);
            end
        end
    end
end

3 个答案:

答案 0 :(得分:1)

考虑到你的图像是双倍的,并且有一层,对于圆的中心位于[cx,cy],你可以得到一个与主图像大小相同的矩阵,其逻辑值为1指定像素位于圆内(半径= r),否则为0

[X,Y] = meshgrid(1:size(img,1),1:size(img,2));
C = bsxfun(@le,(X-cx).^2+(Y-cy).^2 ,r);

最后,img(C)包含所有有效像素值。

单圈示例:

r = 5;
cx=100;
cy=100;
Id = im2double(imread('myimage.png'));
Id1 = Id(:,:,1);
[X,Y] = meshgrid(1:size(Id1,1),1:size(Id1,2));
C = bsxfun(@le,(X-cx).^2+(Y-cy).^2 ,r);

length(Id1(C))
ans = 
      21

有多个圈子,您需要有一个for循环

cx = [100,110,120];
cy = [150,170,190];

for ii = 1:length(cx);
    C = bsxfun(@le,(X-cx(ii)).^2+(Y-cy(ii)).^2 ,r);
end

代码的其他部分保持不变。

答案 1 :(得分:1)

只有一个循环(对于每个圆圈),您可以使用像磁盘一样的掩码从图像中选择适当的像素。 从您的初始代码开始。

% x(:) - vector with a few circles center X coordinates
% y(:) - vector with a few circles center Y coordinates
d = 27;                  %diameter
r = floor(d/2);          %radius
cpix = double(zeros(d,d,size(x,1)));

现在创建具有所需半径的蒙版。如果您拥有图像处理工具箱,则可以轻松完成。

h = fspecial('disk', r);
h = h > 0;

然后在循环中使用此蒙版来选择所需的区域。

for i = 1:size(x,1)
    cpix(:,:,i) = h .* img(x(i)-r:x(i)+r, y(i)-r:y(i)+r);
end

由于你只创建一次蒙版,它应该比为每个圆计算它更快。

如果您构建3D蒙版,可以一次性完成。如果a x b是图片的大小而n是圈数,那么掩码将为a x b x n。如果您将图片repmat改为大小为n的堆叠。然后,您可以使用.*乘法来获得最终结果。但是,结果将是一堆a x b图像,而不是您提到的d x d。 不确定它是否会更快,因为你无论如何都要在创建3D蒙版期间循环它。如果掩模只构建一次并用于很多图像,那么它可能是值得的。

答案 2 :(得分:0)

我有一个开源库pixelscan,它可以扫描各种空间模式(圆圈,环,蛇,网格,随机漫步)中的像素。还可以应用各种空间变换(例如,旋转,缩放,剪裁)。它是一个python库,但您可以将相关代码轻松移植到MATLAB。