web-dev-qa-db-ja.com

2つの長方形はどのくらい重なりますか?

座標系の軸に平行な辺を持つ2つの長方形aとbがあります。座標はx1、y1、x2、y2としてあります。

私は、それらが重複するだけでなく、どのくらい重複するのかを判断しようとしていますか?それらが実際に同じ長方形であるかどうかを把握しようとしていますが、少しゆらゆらするスペースがあります。それで、彼らの面積は95%同じですか?

オーバーラップの割合を計算するのに役立ちますか?

43
Patrick Collins

交差点の面積を計算します。これも長方形です:

SI = Max(0, Min(XA2, XB2) - Max(XA1, XB1)) * Max(0, Min(YA2, YB2) - Max(YA1, YB1))

そこから、ユニオンの面積を計算します。

SU = SA + SB - SI

そして、あなたは比率を考慮することができます

SI / SU

(完全にオーバーラップする場合は100%、0%まで)。

64
Yves Daoust

交差の式は次のようになります

SI= Max(0, Min(XA2, XB2) - Max(XA1, XB1)) * Max(0, Min(YA2, YB2) - Max(YA1, YB1))

ユニオンはS=SA+SB-SI

そして最後に、比率はSI / S

18
user3025064

私も最近この問題に遭遇し、Yvesの答えを適用しましたが、どういうわけか間違った領域サイズにつながったので、書き直しました。

2つの長方形AとBを想定し、それらがどの程度重なり合っているかを調べ、もしそうであれば、領域サイズを返します。

IF A.right < B.left OR A.left > B.right
    OR A.bottom < B.top OR A.top > B.bottom THEN RETURN 0

width := IF A.right > B.right THEN B.right - A.left ELSE A.right - B.left
height := IF A.bottom > B.bottom THEN B.bottom - A.top ELSE A.bottom - B.top

RETURN width * height
9
Ja͢ck

受け入れられた答えは正しいものの、答えの理論的根拠が完全に明らかになるような方法でこの答えを探索する価値があると思います。これはあまりにも一般的なアルゴリズムであり、不完全な(または、さらに悪いことに、物議を醸す)答えを得ることができません。さらに、与えられた式を一目見ただけでは、アルゴリズムの美しさと拡張性、および行われている暗黙の決定を見逃す可能性があります。

最初に、2次元ボックスを定義する1つの方法を考えます:

  • 左上ポイントの(x、y)
  • (x、y)右下のポイント

これは次のようになります。

Example Rectangle

左上を三角形で、右下を円で示します。これは、この例の_x1, x2_のような不透明な構文を避けるためです。

2つの重なり合う長方形は次のようになります。

Two Rectangles

重複を見つけるために、オレンジと青が衝突する場所を探していることに注意してください。

Rectangle Overlap

これを認識すると、これらの2本の暗い線を見つけて乗算した結果、オーバーラップが明らかになります。

Defining Overlap

各線の長さは、円のポイントの最小値から、三角形のポイントの最大値を引いたものです。

ここでは、オレンジとブルーの両方のポイントが比較されることを示すために、ツートンカラーの形状を使用しています。ツートンカラーの形状の後の小さな文字は、三角形がその軸(xまたはy)に沿って比較されることを示します。

Finding Overlap

たとえば、濃い青の線の長さを見つけるには、オレンジと青の三角形を比較して、2つの間の最大値を探します。比較される属性はx属性です。オレンジと青の三角形の間の最大x値は210です。

同じことを別の言い方をすると:比較する両方の線に適合する新しい線の長さは、線の最も近い側の最も遠い点から線の最も長い側の最も近い点を引くことによって見つけられますライン。

Showing Overlap

これらの線を見つけると、重複する領域の完全な情報が得られます。

The Overlap

これができたら、オーバーラップの割合を見つけるのは簡単です。

Finding the percentage of overlap

しかし、オレンジ色の長方形が青い長方形と重ならない場合、問題が発生します。

A Breaking Example

この例では、重複する領域に対して-850が得られますが、これは正しくありません。さらに悪いことに、検出が(x軸でもy軸でも)どちらの次元とも重ならない場合、both次元は負です。これが、ソリューションの一部としてMax(0, ...) * Max(0, ...)を見る理由です。オーバーラップのいずれかが負の場合、関数から0が返されることが保証されます。

シンボル体系に沿った最終式:

The Formula

max(0, ...)関数を使用する必要はないかもしれないことに注意してください。すべてのディメンションではなく、ディメンションの1つに沿って何かが重複しているかどうかを知りたい場合があります。 maxを使用すると、その情報は消去されます。そのため、重複しない画像をどのように扱うかを検討してください。通常、max関数を使用しても問題ありませんが、何をしているのかを知っておく価値があります。

最後に、この比較は線形測定にのみ関係するため、任意の次元または任意の重複する四角形にスケーリングできることに注意してください。

要約する:

_intersecting_area = 
max(0, min(orange.circle.x, blue.circle.x) - max(orange.triangle.x, blue.triangle.x)) * max(0, min(orange.circle.y, blue.circle.y) - max(orange.triangle.y, blue.triangle.y))
_

percent_coverage = intersecting_area / (orange_area + blue_area - intersecting_area)

9
Connor

前の回答を修正して、比率が0〜1になるようにします(Pythonを使用)。

    # (x1,y1) top-left coord, (x2,y2) bottom-right coord, (w,h) size
    A = {'x1': 0, 'y1': 0, 'x2': 99, 'y2': 99, 'w': 100, 'h': 100}
    B = {'x1': 0, 'y1': 0, 'x2': 49, 'y2': 49, 'w':  50, 'h':  50}

    # overlap between A and B
    SA = A['w']*A['h']
    SB = B['w']*B['h']
    SI = np.max([ 0, 1 + np.min([A['x2'],B['x2']]) - np.max([A['x1'],B['x1']]) ]) * np.max([ 0, 1 + np.min([A['y2'],B['y2']]) - np.max([A['y1'],B['y1']]) ])
    SU = SA + SB - SI
    overlap_AB = float(SI) / float(SU)
    print 'overlap between A and B: %f' % overlap_AB

    # overlap between A and A
    B = A
    SB = B['w']*B['h']
    SI = np.max([ 0, 1 + np.min([A['x2'],B['x2']]) - np.max([A['x1'],B['x1']]) ]) * np.max([ 0, 1 + np.min([A['y2'],B['y2']]) - np.max([A['y1'],B['y1']]) ])
    SU = SA + SB - SI
    overlap_AA = float(SI) / float(SU)
    print 'overlap between A and A: %f' % overlap_AA

出力は次のようになります。

    overlap between A and B: 0.250000
    overlap between A and A: 1.000000
5
Alessio B

長方形がxおよびy軸に平行でなければならないと仮定すると、それは前のコメントと回答からの状況のようです。

まだコメントを投稿することはできませんが、前の回答の両方が、一方の長方形がもう一方の長方形の側面内に完全に収まっている場合を無視しているように見えることを指摘したいと思います。私が間違っている場合は修正してください。

ケースを考える

a: (1,1), (4,4)
b: (2,2), (5,3)

この場合、交差点の高さはbTop - bBottomでなければならないことがわかります。これは、bの垂直部分がaに完全に含まれているためです。

次のように、さらにケースを追加する必要があります:(上下を左右と同じものとして扱う場合、コードを短絡することができるため、条件付きチャンクを2回複製する必要はありませんが、そうする必要があります。)

if aRight <= bLeft or bRight <= aLeft or aTop <= bBottom or bTop <= aBottom:
    # There is no intersection in these cases
    return 0
else:
    # There is some intersection

    if aRight >= bRight and aLeft <= bLeft:
        # From x axis point of view, b is wholly contained in a
        width = bRight - bLeft
    Elif bRight >= aRight and bLeft <= aLeft:
        # From x axis point of view, a is wholly contained in b
        width = aRight - aLeft
    Elif aRight >= bRight:
        width = bRight - aLeft
    else:
        width = aRight - bLeft

    if aTop >= bTop and aBottom <= bBottom:
        # From y axis point of view, b is wholly contained in a
        height = bTop - bBottom
    Elif bTop >= aTop and bBottom <= aBottom:
        # From y axis point of view, a is wholly contained in b
        height = aTop - aBottom
    Elif aTop >= bTop:
        height = bTop - aBottom
    else:
        height = aTop - bBottom

return width * height
4
Shar

@ User3025064は正しいものであり、最も簡単なソリューションですが、交差していない長方形については、まず排他性を確認する必要があります(例:長方形AとB(Visual Basicの場合)):

If A.Top =< B.Bottom or A.Bottom => B.Top or A.Right =< B.Left or A.Left => B.Right then
    Exit sub   'No intersection
else
    width = ABS(Min(XA2, XB2) - Max(XA1, XB1))
    height = ABS(Min(YA2, YB2) - Max(YA1, YB1))
    Area = width * height      'Total intersection area.
End if
2
user3476611
[ymin_a, xmin_a, ymax_a, xmax_a] = list(bbox_a)
[ymin_b, xmin_b, ymax_b, xmax_b] = list(bbox_b)

x_intersection = min(xmax_a, xmax_b) - max(xmin_a, xmin_b) + 1
y_intersection = min(ymax_a, ymax_b) - max(ymin_a, ymin_b) + 1

if x_intersection <= 0 or y_intersection <= 0:
    return 0
else:
    return x_intersection * y_intersection
2
Felix

@ user3025064の答えは正しい答えです。受け入れられた回答は、内部のMAXおよびMIN呼び出しを誤って反転させます。また、ABS(x)ではなく、提示された式MAX(0、x)を使用する場合、それらが交差するかどうかを最初にチェックする必要はありません。それらが交差しない場合、MAX(0、x)はゼロを返し、交差領域を0にします(つまり、分離します)。

@Yves Daoustが答えを修正することをお勧めします。なぜなら、それはその問題を検索するすべての人にポップアップするものであるからです。繰り返しになりますが、これが交差の正しい式です。

SI = Max(0, Min(XA2, XB2) - Max(XA1, XB1)) * Max(0, Min(YA2, YB2) - Max(YA1, YB1))

いつものように残り。連合:

SU = SA + SB - SI

および比率:

SI/SU

1
Hazem