我想过使用光栅化来近似圆之间的重叠。这个想法是创建N
点来近似圆形路径,然后将它们传递给poly2mask
函数。这将返回一个在定义圆的位置填充的二进制掩码图像(该算法应以亚像素精度工作)。对所有圆对执行此操作,然后我们可以通过对两个掩码应用逻辑 AND 来计算交集,并计算结果中剩余的“on”像素的数量(或者更好地bwarea
用于稍微更好的估计)。同样,这只是一个近似值,因为我们使用的是离散的像素网格......
从好的方面来说,我们不必担心数学方程。事实上,这种方法适用于任何多边形形状,在这些多边形形状中,很难为交叉点提出封闭形式的解决方案。
不幸的是,这种蛮力方法被证明比我预期的要慢(没有@Floris的代码那么快),无论如何我都会发布我的尝试。我从另一个代码中借用了检查两个圆圈是否感兴趣的想法,如果您拥有的大多数圆圈相距甚远,这应该会大大减少时间。
只是为了好玩,我添加了一些代码来可视化这个过程!
ANIMATION = true;
% size of image we are working in
%sz = [180 360];
sz = [100 100];
% generated two sets of random circles (specified as columns [x;y;r])
% (I am just trying to create circles wholly visible within the box)
k1 = 100; k2 = 80;
M1 = bsxfun(@times, rand(3,k1), [sz(:)*0.6+sz(:)*0.2;0.1*min(sz)+0.1*min(sz)]);
M2 = bsxfun(@times, rand(3,k2), [sz(:)*0.6+sz(:)*0.2;0.1*min(sz)+0.1*min(sz)]);
% animation
if ANIMATION
clf
hImg = imshow(zeros(sz), 'InitialMag','fit');
hLine(1) = line(NaN, NaN, 'Color','r', 'LineWidth',2);
hLine(2) = line(NaN, NaN, 'Color','b', 'LineWidth',2);
axis on
end
% used to approximate circles
num = 50;
t = linspace(0, 2*pi, num);
ct = cos(t); st = sin(t);
% test to find which circles intersect
dist = pdist2(M1(1:2,:)', M2(1:2,:)');
sumr = bsxfun(@plus, M1(3,:)', M2(3,:));
skipIdx = (sumr < dist);
% compute overlap between all pairs
overlap = zeros(k1,k2);
for i=1:k1
for j=1:k2
% early skip if circles dont interset
if skipIdx(i,j), continue, end
% compute each circle points
x1 = M1(3,i)*ct + M1(1,i); y1 = M1(3,i)*st + M1(2,i);
x2 = M2(3,j)*ct + M2(1,j); y2 = M2(3,j)*st + M2(2,j);
% rasterize circles
BW1 = poly2mask(x1, y1, sz(1), sz(2));
BW2 = poly2mask(x2, y2, sz(1), sz(2));
% compute area of intersection of the two masks
%overlap(i,j) = sum(BW1(:)&BW2(:));
overlap(i,j) = bwarea(BW1&BW2);
if ANIMATION
% update animation
set(hImg, 'CData',BW1&BW2)
set(hLine(1), 'XData',x1, 'YData',y1)
set(hLine(2), 'XData',x2, 'YData',y2)
title(sprintf('%g',overlap(i,j)))
drawnow
end
end
end
为了了解近似值有多准确,我捕获了一个迭代,其中一个圆圈完全在另一个圆圈内。这样我们就可以将实际的相交区域与我们的近似值进行比较。
对于下面显示的图像,我们有:
K>> M1(:,i)
ans =
58.2106 % x
24.0996 % y
8.9387 % r
K>> pi*M1(3,i)^2
ans =
251.0122
K>> overlap(i,j)
ans =
252.5000
我认为这已经足够接近了 :) 使用更高分辨率的像素网格会提高近似值,但肯定会进一步减慢它的速度。
![路口](https://i.stack.imgur.com/UToBS.png)