25

ここに2つのテスト画像があります。私の質問は、画像をトリミングせずに、最初の画像の正方形を2番目の画像の四角形にマッピングする方法です。

画像 1: 画像1

画像 2: 画像2

openCV warpPerspective 関数を使用した現在のコードを次に示します。

import cv2
import numpy as np

img1_square_corners = np.float32([[253,211], [563,211], [563,519],[253,519]])
img2_quad_corners = np.float32([[234,197], [520,169], [715,483], [81,472]])

h, mask = cv2.findHomography(img1_square_corners, img2_quad_corners)
im = cv2.imread("image1.png")
out = cv2.warpPerspective(im, h, (800,800))
cv2.imwrite("result.png", out)

結果: 結果

ご覧のとおり、warpPerspective 関数の dsize=(800,800) パラメータのため、画像 1 の全体像を取得できません。dsize を調整すると、正方形が適切にマッピングされません。画像 1 の全体像を取得できるように、出力画像のサイズを変更する方法はありますか?

4

3 に答える 3

49

私の解決策は、結果の画像サイズを計算してから変換することです。

def warpTwoImages(img1, img2, H):
    '''warp img2 to img1 with homograph H'''
    h1,w1 = img1.shape[:2]
    h2,w2 = img2.shape[:2]
    pts1 = float32([[0,0],[0,h1],[w1,h1],[w1,0]]).reshape(-1,1,2)
    pts2 = float32([[0,0],[0,h2],[w2,h2],[w2,0]]).reshape(-1,1,2)
    pts2_ = cv2.perspectiveTransform(pts2, H)
    pts = concatenate((pts1, pts2_), axis=0)
    [xmin, ymin] = int32(pts.min(axis=0).ravel() - 0.5)
    [xmax, ymax] = int32(pts.max(axis=0).ravel() + 0.5)
    t = [-xmin,-ymin]
    Ht = array([[1,0,t[0]],[0,1,t[1]],[0,0,1]]) # translate

    result = cv2.warpPerspective(img2, Ht.dot(H), (xmax-xmin, ymax-ymin))
    result[t[1]:h1+t[1],t[0]:w1+t[0]] = img1
    return result

dst_pts = float32([kp1[m.queryIdx].pt for m in good]).reshape(-1,1,2)
src_pts = float32([kp2[m.trainIdx].pt for m in good]).reshape(-1,1,2)
M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0)

result = warpTwoImages(img1_color, img2_color, M)

ここに画像の説明を入力

于 2013-12-03T15:46:56.543 に答える
9

はい。ただし、出力イメージが非常に大きくなる可能性があることに注意してください。私はすぐに次の Python コードを書きましたが、3000 x 3000 の画像でも出力に収まりませんでした。変換のために大きすぎます。これが私のコードですが、お役に立てば幸いです。

import cv2
import numpy as np
import cv           #the old cv interface

img1_square_corners = np.float32([[253,211], [563,211], [563,519],[253,519]])
img2_quad_corners = np.float32([[234,197], [520,169], [715,483], [81,472]])

h, mask = cv2.findHomography(img1_square_corners, img2_quad_corners)
im = cv2.imread("image1.png")

ここで出力イメージを作成します。例として (3000, 3000) を使用しました。

out_2 = cv.fromarray(np.zeros((3000,3000,3),np.uint8))

古いcvインターフェイスを使用して、出力に直接書き込んだので、トリミングされません。インターフェイスを使用してこれを試しましcv2たが、何らかの理由で機能しませんでした...誰かがそれに光を当てることができるでしょうか?

cv.WarpPerspective(cv.fromarray(im), out_2, cv.fromarray(h))
cv.ShowImage("test", out_2)
cv.SaveImage("result.png", out_2)
cv2.waitKey()

とにかく、これは非常に大きな画像を提供します。これには、元の画像 1 が歪んでいます。出力画像を十分な大きさに指定すると、画像全体が表示されます。(実際には非常に大きいかもしれません!)

このコードがお役に立てば幸いです。

于 2012-10-25T18:09:19.617 に答える
1

最初に、以前の解に従ってホモグラフィ行列を計算します。ホモグラフィ行列を取得したら、ホモグラフィ行列に対して画像をワープする必要があります。最後に、歪んだ画像をマージします。

ここでは、歪んだ画像をマージするために使用できる別のアイデアを共有します。(以前の回答では、インデックスの範囲をオーバーレイに使用しています。ここでは、ROI のマスキングを使用しています)

関心領域 (ROI) と画像を黒でマスクします。次に、ROI を含む画像を追加します。( OpenCV ビットマスク チュートリアルを参照)

def copyOver(source, destination):
    result_grey = cv2.cvtColor(source, cv2.COLOR_BGR2GRAY)
    ret, mask = cv2.threshold(result_grey, 10, 255, cv2.THRESH_BINARY)
    mask_inv = cv2.bitwise_not(mask)
    roi = cv2.bitwise_and(source, source, mask=mask)
    im2 = cv2.bitwise_and(destination, destination, mask=mask_inv)
    result = cv2.add(im2, roi)
    return result


warpedImageB = cv2.warpPerspective(imageB, H, (imageA.shape[1], imageA.shape[0]))
result = copyOver(imageA, warpedImageB)

最初の画像:

初め

2 番目の画像:

2番

ステッチ画像: ステッチ

于 2016-10-31T23:12:29.553 に答える