2012-02-08 72 views
7

Tôi đang cố gắng lấy một số mã sẽ thực hiện phép biến đổi phối cảnh (trong trường hợp này là xoay vòng 3D) trên hình ảnh.xoay 3D trên hình ảnh

import os.path 
import numpy as np 
import cv 

def rotation(angle, axis): 
    return np.eye(3) + np.sin(angle) * skew(axis) \ 
       + (1 - np.cos(angle)) * skew(axis).dot(skew(axis)) 

def skew(vec): 
    return np.array([[0, -vec[2], vec[1]], 
        [vec[2], 0, -vec[0]], 
        [-vec[1], vec[0], 0]]) 

def rotate_image(imgname_in, angle, axis, imgname_out=None): 
    if imgname_out is None: 
     base, ext = os.path.splitext(imgname_in) 
     imgname_out = base + '-out' + ext 
    img_in = cv.LoadImage(imgname_in) 
    img_size = cv.GetSize(img_in) 
    img_out = cv.CreateImage(img_size, img_in.depth, img_in.nChannels) 
    transform = rotation(angle, axis) 
    cv.WarpPerspective(img_in, img_out, cv.fromarray(transform)) 
    cv.SaveImage(imgname_out, img_out) 

Khi tôi xoay quanh trục z, mọi thứ hoạt động như mong đợi, nhưng xoay quanh trục x hoặc y có vẻ hoàn toàn tắt. Tôi cần phải xoay theo các góc nhỏ như pi/200 trước khi tôi bắt đầu nhận được kết quả có vẻ hợp lý. Bất cứ ý tưởng những gì có thể là sai?

Trả lời

21

Thứ nhất, xây dựng ma trận luân chuyển, có dạng

[cos(theta) -sin(theta) 0] 
R = [sin(theta) cos(theta) 0] 
    [0   0   1] 

Áp dụng điều này phối hợp chuyển đổi cung cấp cho bạn một vòng quay xung quanh gốc.

Nếu, thay vào đó, bạn muốn xoay quanh trung tâm hình ảnh, trước tiên bạn phải di chuyển trung tâm hình ảnh về nguồn gốc, sau đó áp dụng xoay và sau đó chuyển mọi thứ trở lại. Bạn có thể làm như vậy bằng một ma trận dịch:

[1 0 -image_width/2] 
T = [0 1 -image_height/2] 
    [0 0 1] 

Ma trận chuyển đổi để dịch, luân chuyển, và dịch ngược sau đó trở thành:

H = inv(T) * R * T 

tôi sẽ phải suy nghĩ một chút về làm thế nào để liên hệ ma trận nghiêng cho phép biến đổi 3D. Tôi hy vọng con đường dễ nhất là thiết lập ma trận chuyển đổi 4D, và sau đó chiếu dự án đó trở lại tọa độ đồng nhất 2D. Nhưng hiện nay, dạng tổng quát của ma trận nghiêng:

[x_scale 0  0] 
S = [0  y_scale 0] 
    [x_skew y_skew 1] 

Các x_skewy_skew giá trị thường nhỏ (1e-3 hoặc ít hơn).

Dưới đây là các mã:

from skimage import data, transform 
import numpy as np 
import matplotlib.pyplot as plt 

img = data.camera() 

theta = np.deg2rad(10) 
tx = 0 
ty = 0 

S, C = np.sin(theta), np.cos(theta) 

# Rotation matrix, angle theta, translation tx, ty 
H = np.array([[C, -S, tx], 
       [S, C, ty], 
       [0, 0, 1]]) 

# Translation matrix to shift the image center to the origin 
r, c = img.shape 
T = np.array([[1, 0, -c/2.], 
       [0, 1, -r/2.], 
       [0, 0, 1]]) 

# Skew, for perspective 
S = np.array([[1, 0, 0], 
       [0, 1.3, 0], 
       [0, 1e-3, 1]]) 

img_rot = transform.homography(img, H) 
img_rot_center_skew = transform.homography(img, S.dot(np.linalg.inv(T).dot(H).dot(T))) 

f, (ax0, ax1, ax2) = plt.subplots(1, 3) 
ax0.imshow(img, cmap=plt.cm.gray, interpolation='nearest') 
ax1.imshow(img_rot, cmap=plt.cm.gray, interpolation='nearest') 
ax2.imshow(img_rot_center_skew, cmap=plt.cm.gray, interpolation='nearest') 
plt.show() 

Và kết quả:

Rotations of cameraman around origin and center+skew

0

Tôi không nhận được cách bạn tạo ma trận xoay vòng của mình. Nó có vẻ khá phức tạp với tôi. Thông thường, nó sẽ được xây dựng bằng cách xây dựng một ma trận 0, đặt 1 trên các trục không cần thiết và phổ biến sin, cos, -cos, sin vào hai thứ nguyên được sử dụng. Sau đó nhân tất cả chúng lại với nhau.

Bạn đã nhận được cấu trúc nào từ số np.eye(3) + np.sin(angle) * skew(axis) + (1 - np.cos(angle)) * skew(axis).dot(skew(axis)) từ đâu?

Thử tạo ma trận chiếu từ các khối xây dựng cơ bản. Xây dựng một ma trận xoay là khá dễ dàng, và "rotationmatrix dot skewmatrix" nên hoạt động.

Mặc dù vậy, bạn có thể cần chú ý đến trung tâm xoay. Hình ảnh của bạn có thể được đặt ở vị trí ảo của 1 trên trục z, do đó, bằng cách xoay x hoặc y, nó di chuyển xung quanh một chút. Vì vậy, bạn cần sử dụng bản dịch để z trở thành 0, sau đó xoay, sau đó dịch ngược lại. (Ma trận dịch ở tọa độ affine là khá đơn giản, quá Xem wikipedia:. https://en.wikipedia.org/wiki/Transformation_matrix)