3

この質問は、2セットのポイント間の変換に関連しています。ただし、これはより適切に指定され、いくつかの仮定が追加されています。

要素画像といくつかのモデルがあります。

両方で輪郭を検出しました

contoursModel0, hierarchyModel = cv2.findContours(model.copy(), cv2.RETR_LIST,   
                                                  cv2.CHAIN_APPROX_SIMPLE);
contoursModel = [cv2.approxPolyDP(cnt, 2, True) for cnt in contoursModel0];    
contours0, hierarchy = cv2.findContours(canny.copy(), cv2.RETR_LIST,  
                                        cv2.CHAIN_APPROX_SIMPLE);
contours = [cv2.approxPolyDP(cnt, 2, True) for cnt in contours0];

次に、各輪郭を互いに一致させました

modelMassCenters = [];
imageMassCenters = [];
for cnt in contours:
for cntModel in contoursModel:
    result = cv2.matchShapes(cnt, cntModel, cv2.cv.CV_CONTOURS_MATCH_I1, 0);
    if(result != 0):
        if(result < 0.05):
           #Here are matched contours
           momentsModel = cv2.moments(cntModel);
           momentsImage = cv2.moments(cnt);
           massCenterModel = (momentsModel['m10']/momentsModel['m00'],  
                              momentsModel['m01']/momentsModel['m00']); 
           massCenterImage = (momentsImage['m10']/momentsImage['m00'], 
                              momentsImage['m01']/momentsImage['m00']); 
           modelMassCenters.append(massCenterModel);
           imageMassCenters.append(massCenterImage); 

一致する輪郭は、フィーチャのようなものです。

ここで、この2つのポイントセット間の変換を検出したいと思います。前提条件:要素は剛体であり、回転、変位、およびスケールの変更のみです。

一部の機能は、それらを排除する方法が検出されない可能性があります。私はかつて使用cv2.findHomographyしたことがあり、2つのベクトルを取り、いくつかのミスマッチがあってもそれらの間のホモグラフィを計算します。

cv2.getAffineTransformationたった3つのポイント(ミスマッチに対処できません)を取ります、そしてここで私は複数の機能を持っています。私の前の質問の答えは、この変換を計算する方法を示していますが、ミスマッチは取りません。また、アルゴリズムからある程度の品質レベルを返すことも可能だと思います(残りの部分からいくつかの変換を計算した後、不一致のポイントの数をチェックすることによって)

そして最後の質問:変換を計算するためにすべてのベクトル点を取るべきですか、それともこの形状の質量中心のみを特徴として扱うべきですか?

それを示すために、簡単な画像を追加しました。緑の機能は、赤の悪い一致の良い一致です。ここで、一致は3つの緑の機能から計算する必要があり、赤の不一致は一致の品質に影響を与えるはずです。

ここに画像の説明を入力してください

私は今のところ理解したソリューションの断片を追加しています(しかし、それははるかにうまくいく可能性があると思います):

for i in range(0, len(modelMassCenters) - 1):
for j in range(i + 1, len(modelMassCenters) - 1  ):
    x1, y1 = modelMassCenters[i];
    x2, y2 = modelMassCenters [j];
    modelVec = (x2 - x1, y2 - y1);
    x1, y1 = imageMassCenters[i];
    x2, y2 = imageMassCenters[j];
    imageVec = (x2 - x1, y2 - y1);
    rotation = angle(modelVec,imageVec);
    rotations.append((i, j, rotation)); 
    scale = length(modelVec)/length(imageVec);
    scales.append((i, j,  scale)); 

対応する線の各ペアによって与えられるスケールと回転を計算した後、中央値と回転の平均値を見つけます。これは、中央値とのデルタ以上の差はありません。スケールについても同じです。次に、これらの値を計算に使用するポイントを使用して、変位を計算します。

4

1 に答える 1

2

2 番目のステップ (ペアごとの形状比較を行うことで輪郭を互いに一致させる) は、フィーチャが類似の形状を持っている場合 (たとえば、いくつかの類似サイズの円形の輪郭がある場合)、エラーに対して非常に脆弱に思えます。しかし、1 つの象限のみに 5 つの円形フィーチャを持つ剛体がある場合、ボディとそのフィーチャを全体として考慮すると、アフィン変換の非常に堅牢な推定値を得ることができます。そのため、フィーチャを照合するときに、フィーチャの範囲や全身の中心からの方向などの情報を破棄しないでください。これらは、個々の輪郭のサイズや形状と少なくとも同じくらい重要です。

私は(テストされていない疑似コード)のようなものを試してみます:

"""
Convert from rectangular (x,y) to polar (r,w)
    r = sqrt(x^2 + y^2)
    w = arctan(y/x) = [-\pi,\pi]
"""
def polar(x, y):        # w in radians
    from math import hypot, atan2, pi
    return hypot(x, y), atan2(y, x)

model_features = []
model = params(model_body_contour)    # return tuple (center_x, center_y, area)
for contour in model_feature_contours:
    f = params(countour)
    range, angle = polar(f[0]-model[0], f[1]-model[1])
    model_features.append((angle, range, f[2]))

image_features = []
image = params(image_body_contour)
for contour in image_feature_contours:
    f = params(countour)
    range, angle = polar(f[0]-image[0], f[1]-image[1])
    image_features.append((angle, range, f[2]))

# sort image_features and model_features by angle, range
#
# correlate image_features against model_features across angle offsets
#    rotation = angle offset of max correlation
#    scale = average(model areas and ranges) / average(image areas and ranges)

6 つの等間隔に配置された同様のサイズのリングで、そのうちの 5 つが同じ形状で 1 つが異なる (例: 5 つの円と星) など、非常に難しい画像がある場合は、離心率や星などのパラメーターを追加できます。特徴パラメーターのリストにシャープネスを追加し、回転角度を検索するときにそれらを相関に含めます。

于 2012-09-24T21:16:35.280 に答える