我有两个区域列表(regionsA
,regionsB
)定义了边界(大小为1024x1024的图像上的坐标)(.mat
文件available here)。我想计算这两个列表之间每个可能区域对的重叠。我预计它会很慢,但不会那么慢。
目前我正在使用下面的代码,50x60对象需要20到40秒才能完成:
intersect_matrix = zeros(length(regionsA), length(regionsB)); % for storing true/false
intersect_matrix_iou = zeros(size(intersect_matrix_iou)); % for storing IoU (intersect over union)
for i = 1:length(regionsA)
for j = 1:length(regionsB)
% get coordinates
x1 = regionsA{i}(:,1);
y1 = regionsA{i}(:,2);
x2 = regionsB{j}(:,1);
y2 = regionsB{j}(:,2);
% move coordinates to origin (start at zero)
% this is not necessary but reduces the size of the mask created by poly2mask(), hence reduces consumed memory is
minX = min([x1(:); x2(:)]);
minY = min([y1(:); y2(:)]);
x1 = x1 - minX;
x2 = x2 - minX;
y1 = y1 - minY;
y2 = y2 - minY;
% create object masks in n x m window
m = max([x1(:); x2(:)]);
n = max([y1(:); y2(:)]);
objMask1 = poly2mask(y1,x1,m,n);
objMask2 = poly2mask(y2,x2,m,n);
save('regionsAB','regionsA', 'regionsB');
intersection = objMask1 & objMask2;
union = objMask1 | objMask2;
% store info
intersect_matrix(i,j) = (bwarea(intersection) ~= 0); % store true/false
if (bwarea(intersection) ~= 0)
intersect_matrix_iou(i,j) = bwarea(intersection) / bwarea(union);
else
intersect_matrix_iou(i,j) = 0; % avoid division by zero
end
end; clear j;
end; clear i;
之前,我首先解决了多边形操作的问题。那仍然很慢(12秒)但更好。但是我必须将其更改为上面的代码,因为在某些情况下我得到NaN
个值,因为polybool
/ polyarea
/ ...有未连接区域的问题。使用像素掩模对这些问题很有用。这取代了for循环的内容:
% polygonal overlap
x1 = regionsA{i}(:,1);
y1 = regionsA{i}(:,2);
x2 = regionsB{j}(:,1);
y2 = regionsB{j}(:,2);
[x_i,y_i] = polybool('intersection',x1,y1,x2,y2);
[x_u,y_u] = polybool('union',x1,y1,x2,y2);
% store info
%intersect_matrix_geo{i, j} = [x_i,y_i];
intersect_matrix(i,j) = ~isempty([x_i,y_i]);
if ~isempty([x_i,y_i])
intersect_matrix_iou(i,j) = polyarea(x_i, y_i) / polyarea(x_u, y_u);
else
intersect_matrix_iou(i,j) = 0;
end
问题: 是否有更有效/更快的方法来实现这一点? (并且对于断开连接的交叉区域和此类事情仍然很健壮。 ..)
答案 0 :(得分:1)
大多数多边形根本不相交,因此大多数计算都是多余的。我使用rectint
来测试多边形的封闭矩形的交点,因此我将有一个先验,其中多边形可能相交。它给了我更少的计算,因此代码更快:
load regionsAB.mat
% get enclosing rectangle for each polygon
poly2rect = @(x) [min(x(:,1)),min(x(:,2)),...
1+max(x(:,1))-min(x(:,1)),1+max(x(:,2))-min(x(:,2))];
rectsA = cell2mat(cellfun(poly2rect,regionsA,'UniformOutput',0)');
rectsB = cell2mat(cellfun(poly2rect,regionsB,'UniformOutput',0)');
% compute rectangle intersections
ar = rectint(rectsA,rectsB);
[ii,jj] = find(ar > 0);
idx = numel(ii);
% test only for intersecting rectangles
intersect_matrix_iou = zeros(numel(rectsA),numel(rectsB)); % for storing IoU (intersect over union)
tic
for idx = 1:numel(ii)
i = ii(idx);
j = jj(idx);
x1 = regionsA{i}(:,1);
y1 = regionsA{i}(:,2);
x2 = regionsB{j}(:,1);
y2 = regionsB{j}(:,2);
% move coordinates to origin (start at zero)
% this is not necessary but reduces the size of the mask created by poly2mask(), hence reduces consumed memory is
minX = min([x1(:); x2(:)]);
minY = min([y1(:); y2(:)]);
% because set x1,y1 outside inner loop
x1 = x1 - minX;
y1 = y1 - minY;
x2 = x2 - minX;
y2 = y2 - minY;
% create object masks in n x m window
m = max([x1(:); x2(:)]);
n = max([y1(:); y2(:)]);
objMask1 = poly2mask(y1,x1,m,n);
objMask2 = poly2mask(y2,x2,m,n);
intersection = objMask1 & objMask2;
union = objMask1 | objMask2;
% store info
intersect_matrix_iou(i,j) = bwarea(intersection) / bwarea(union);
end
intersect_matrix = intersect_matrix_iou > 0;
toc