2016-07-12 7 views
2

私は現在、opencv(CV2)とPython Pillow画像ライブラリを使用して任意の電話機の画像を取得し、その画像を新しい画像に置き換えています。私は画像を撮って電話の画面を確認してコーナーの座標をすべて取得できるようになったが、画像のその領域を新しい画像で置き換えるのは本当に苦労している。Pythonを使用してイメージ内の輪郭(矩形)を新しいイメージに置き換えるにはどうすればいいですか?

コード私がこれまで持っている:

import cv2 
from PIL import Image 

image = cv2.imread('mockup.png') 
edged_image = cv2.Canny(image, 30, 200) 

(contours, _) = cv2.findContours(edged_image.copy(), cv2.RETR_TREE,  cv2.CHAIN_APPROX_SIMPLE) 
contours = sorted(contours, key = cv2.contourArea, reverse = True)[:10] 
screenCnt = None 

for contour in contours: 
    peri = cv2.arcLength(contour, True) 
    approx = cv2.approxPolyDP(contour, 0.02 * peri, True) 

    # if our approximated contour has four points, then 
    # we can assume that we have found our screen 
    if len(approx) == 4: 
     screenCnt = approx 
     break 

cv2.drawContours(image, [screenCnt], -1, (0, 255, 0), 3) 
cv2.imshow("Screen Location", image) 
cv2.waitKey(0) 

これは私にこのような画像が得られます:enter image description here

私もこのコード行を使用して、画面の隅の座標を取得することができます:私は新しいイメージを取り、私が見つけた座標空間の形状とoverlにそれを拡張する方法を私の人生のために把握することはできませんしかし

screenCoords = [x[0].tolist() for x in screenCnt] 
// [[398, 139], [245, 258], [474, 487], [628, 358]] 

画像のオンタップ。

私の推測では、私はイメージが私がthis stackoverflow questionから適応この機能を使用して枕に変換を使用してこれを行うことができるということです。

def find_transform_coefficients(pa, pb): 
"""Return the coefficients required for a transform from start_points to end_points. 

    args: 
     start_points -> Tuple of 4 values for start coordinates 
     end_points --> Tuple of 4 values for end coordinates 
""" 
matrix = [] 
for p1, p2 in zip(pa, pb): 
    matrix.append([p1[0], p1[1], 1, 0, 0, 0, -p2[0]*p1[0], -p2[0]*p1[1]]) 
    matrix.append([0, 0, 0, p1[0], p1[1], 1, -p2[1]*p1[0], -p2[1]*p1[1]]) 

A = numpy.matrix(matrix, dtype=numpy.float) 
B = numpy.array(pb).reshape(8) 

res = numpy.dot(numpy.linalg.inv(A.T * A) * A.T, B) 
return numpy.array(res).reshape(8) 

私は私の頭の上で少しだし、私はできませんしかし、細部を正しく理解してください。誰かが私に助けてくれますか?

EDIT

OK]をクリックして、今、私がgetPerspectiveTransformとwarpPerspective機能を使用していますことを、私は、次の追加のコードを持っている:

screenCoords = numpy.asarray(
    [numpy.asarray(x[0], dtype=numpy.float32) for x in screenCnt], 
    dtype=numpy.float32 
) 

overlay_image = cv2.imread('123.png') 
overlay_height, overlay_width = image.shape[:2] 

input_coordinates = numpy.asarray(
    [ 
     numpy.asarray([0, 0], dtype=numpy.float32), 
     numpy.asarray([overlay_width, 0], dtype=numpy.float32), 
     numpy.asarray([overlay_width, overlay_height],  dtype=numpy.float32), 
     numpy.asarray([0, overlay_height], dtype=numpy.float32) 
    ], 
    dtype=numpy.float32, 
) 

transformation_matrix = cv2.getPerspectiveTransform(
    numpy.asarray(input_coordinates), 
    numpy.asarray(screenCoords), 
) 

warped_image = cv2.warpPerspective(
    overlay_image, 
    transformation_matrix, 
    (background_width, background_height), 
) 
cv2.imshow("Overlay image", warped_image) 
cv2.waitKey(0) 

画像が(と思う)が正しく回転して斜めになっています画面と同じサイズではありません。その「短い」:

enter image description here

と私は垂直方向に私も「長い」である何かで終わる非常に背の高い別の画像を使用する場合:

enter image description here

を私は必要ですかイメージを拡大/縮小するための追加の変換を適用するには?ここで何が起こっているのか分かりませんが、私は、透視変換が画像を自動的に指定された座標にスケールアウトすると考えました。

答えて

0

あなたが必要な場合は、適切にアルファチャンネルで回転新しい画像を有することができる

import cv2 
A_img = cv2.imread("new_image.png") 
B_img = cv2.imread("larger_image.jpg") 
x_offset=y_offset=50 
B_img[y_offset:y_offset+A_img.shape[0], x_offset:x_offset+A_img.shape[1]] = A_img 

によって原画像上に(携帯電話の画面の向きに回転)、新たな画像をオーバーレイすることができます。

下のコメント(見出しの透視変換の下で)で述べたように、新しい画像を透視変換(歪め)する必要があります。透視変換がどのように歪んだ画像を直線に固定するかについては、下のリンクを参照してください(これとは逆です)。

http://docs.opencv.org/master/da/d6e/tutorial_py_geometric_transformations.html#gsc.tab=0 

変換のために元々歪んだスペース(pts1とpts2)には4ポイントを入力する必要があります。

元の画像の四隅を挿入する(pts1)ことができ、輪郭の角(pts2)が機能するはずです。

+0

私は、これは完全にかかわらず、問題を解決していけないと思います。私が見つけた画面は、通常、完全な矩形ではないので、画像を回転させるだけでは十分ではありません。また、私が見つけた輪郭と一致するように視点を変換する必要があります。それは理にかなっていますか? –

+0

逆透視変換を行うことができます – user3404344

+0

詳細を教えてください。私はopencv、画像処理、ベクトル数学の完全なnoobです –

1

解決方法を見つけるために画像データをダウンロードし、ローカルマシンで問題を再現しました。また電話画面の内側に収まるようにlenna.pngをダウンロードしました。

import cv2 
import numpy as np 

# Template image of iPhone 
img1 = cv2.imread("/Users/anmoluppal/Downloads/46F1U.jpg") 
# Sample image to be used for fitting into white cavity 
img2 = cv2.imread("/Users/anmoluppal/Downloads/Lenna.png") 

rows,cols,ch = img1.shape 

# Hard coded the 3 corner points of white cavity labelled with green rect. 
pts1 = np.float32([[201, 561], [455, 279], [742, 985]]) 
# Hard coded the same points on the reference image to be fitted. 
pts2 = np.float32([[0, 0], [512, 0], [0, 512]]) 

# Getting affine transformation form sample image to template. 
M = cv2.getAffineTransform(pts2,pts1) 

# Applying the transformation, mind the (cols,rows) passed, these define the final dimensions of output after Transformation. 
dst = cv2.warpAffine(img2,M,(cols,rows)) 

# Just for Debugging the output. 
final = cv2.addWeighted(dst, 0.5, img1, 0.5, 1) 
cv2.imwrite("./garbage.png", final) 

enter image description here

+0

これはあなたのために働いて驚いています。私はまったく同じコードを(ハードコードされた値なしで)試してみました。そして、私はミスケルした画像を取得し続けています。(私の質問の編集バージョンの写真を見てください)。私はそれがハードコーディングされた値なので、あなたのためだけに働いたと思います。 –

+0

Aaaah ....コードにバグがありました。あなたは正しい、私は間違っていた。すぐに完全なソリューションを投稿します。 –

+0

今後の訪問者には、これを回答としてマークすることができます。また、あなたの質問を編集して、それを小さくて正確にしてください。それがコミュニティを助けるかもしれないように。 – ZdaR

関連する問題