快速复制属于圆圈的像素的方法
Fast way to copy pixels belonging to the circles
我有一个 img
格式的初始灰度图像 double
,其中包含许多相同半径的圆和圆心坐标为 x
和 y
的列向量.我需要将属于圆圈的所有像素复制到数组 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
考虑到你的图像是双层的并且有 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
代码的其他部分保持不变。
只有一个循环(对于每个圆圈),您可以使用像磁盘一样的遮罩来 select 图像中的适当像素。
从您的初始代码开始。
% 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)));
现在创建具有所需半径的蒙版。如果您有 Image Processing Toolbox.
就可以轻松完成
h = fspecial('disk', r);
h = h > 0;
然后在循环中使用此掩码 select 所需区域。
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 蒙版期间您必须循环播放它。如果蒙版只构建一次并在很多图像中使用,它可能是值得的。
我有一个开源库pixelscan,它可以扫描各种空间模式(圆形、环形、蛇形、网格、随机游走)的像素。还可以应用各种空间变换(例如,旋转、缩放、裁剪)。它是一个 python 库,但您可以将相关代码简单地移植到 MATLAB。
我有一个 img
格式的初始灰度图像 double
,其中包含许多相同半径的圆和圆心坐标为 x
和 y
的列向量.我需要将属于圆圈的所有像素复制到数组 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
考虑到你的图像是双层的并且有 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
代码的其他部分保持不变。
只有一个循环(对于每个圆圈),您可以使用像磁盘一样的遮罩来 select 图像中的适当像素。 从您的初始代码开始。
% 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)));
现在创建具有所需半径的蒙版。如果您有 Image Processing Toolbox.
就可以轻松完成h = fspecial('disk', r);
h = h > 0;
然后在循环中使用此掩码 select 所需区域。
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 蒙版期间您必须循环播放它。如果蒙版只构建一次并在很多图像中使用,它可能是值得的。
我有一个开源库pixelscan,它可以扫描各种空间模式(圆形、环形、蛇形、网格、随机游走)的像素。还可以应用各种空间变换(例如,旋转、缩放、裁剪)。它是一个 python 库,但您可以将相关代码简单地移植到 MATLAB。