Matlab 快速复制属于圆的像素的方法
我有一个初始灰度图像Matlab 快速复制属于圆的像素的方法,matlab,image-processing,vectorization,Matlab,Image Processing,Vectorization,我有一个初始灰度图像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;
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
%x(:)-以x坐标为中心有几个圆的向量
%y(:)-以y坐标为中心有几个圆的向量
d=27;%直径
r=地板(d/2);%半径
cpix=双精度(零(d,d,大小(x,1));
对于iCent=1:每个圆的尺寸(x,1)%
对于ix=1:d
对于iy=1:d
如果((ix-r)^2+(iy-r)^2)
考虑到您的图像是双层的,并且有一层,因为圆的中心位于[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
代码的其他部分保持不变。只有一个循环(对于每个圆),您可以使用类似磁盘的遮罩从图像中选择适当的像素。
从初始代码开始
% 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遮罩的过程中,无论如何都要循环它。如果蒙版只构建一次并在很多图像中使用,那么它可能是值得的。我有一个开源库,可以扫描各种空间模式(圆、环、蛇、网格、随机行走)中的像素。还可以应用各种空间变换(例如,旋转、缩放、剪裁)。这是一个python库,但是您可以轻松地将相关代码移植到MATLAB。圆是否可以靠近图像的边界?在这种情况下会发生什么呢?不,圆圈距离边界的半径大于一个半径,这是一种方法,但您可以扩展示例以处理中心
cx
和cy
数组。OP似乎有一些需要处理。谢谢你的建议,这是一个有趣的方法。但关键是要得到三维数组,其三维度等于圈数。完全矢量化在这里可能没有好处,因此我认为一个循环是合理的。干得好在执行建议的代码之后,我需要再次进行分段,以获得所需的数组,其中所有关于圆内磁盘区域的信息都将在第三维中进行索引。要处理350圈半径=15的样本图像966x966px,我的代码需要4.59秒,NKN提出的代码需要3.60秒(请记住,在执行后,我需要再次执行某种循环以获得所需的数组),那么有没有办法进行向量化操作以生成指定的数组?我无法提出基于网格的解决方案yetThanks!这是一个完美的解决方案,只需0.008290秒,而我的原始代码为4.594374秒。我唯一需要更改的是img索引-y和x被交换,因此该行看起来像cpix(:,:,I)=h.*img(y(I)-r:y(I)+r,x(I)-r:x(I)+r)代码>请通知某个地方,用户将需要图像处理工具箱来运行您的解决方案。如果以后的用户尝试此代码,并且在他们不知道原因的情况下失败,可能会减少挫折感。谢谢@hoki!我添加了图像处理工具箱说明。