2017-05-10 1 views
0

私は、領域(regionsA,regionsB)の境界を境界として定義された2つのリスト(サイズ1024x1024の画像上の座標)(.matファイルavailable here)を持っています。私はこれらの2つのリストの間の領域の可能な各ペアの重なりを計算したいと思います。そして私はそれが遅いと思ったが、それは遅くはなかった。matlabのいくつかの境界間のオーバーラップを計算する効率的な方法はありますか?

現在、私は、コードの下に使用していますし、それが20取る - 私のために50x60のオブジェクトのための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秒)しかしずっと良かった。しかし、私はの値を持っている場合があるので、上記のコードに変更する必要がありました。polybool/polyarea/...未接続領域に問題があります。ピクセルマスクを使用することは、これらの問題に対して堅牢です。

% 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 

質問はこれを実装するために、より効率的/高速化の方法があります。これは、forループの内容を置き換え?(しかも、交差した領域やそのようなものに対しては依然として堅牢です)

+0

これらの領域は凸ですか?残念ながら、 – user2999345

+0

@ user2999345凸オブジェクトとそこで作業する前に 'polybool' /' polyarea'を使った実装はうまくいきましたが、今はより一般的なものが必要です。 – Honeybear

答えて

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 
+0

私はすでに境界ボックスを持っているので、素晴らしいアイデアと非常に適しています。それは〜1秒にそれをもたらしました!私は組み込みの関数 'bboxOverlapRatio(bboxA、bboxB)'を使用して終了しました。これは 'rectint(bboxA、bboxB)'と基本的に同じ働きをします。どちらも同じように速く見える。 – Honeybear

関連する問題