2017-02-20 993 views
0

我想按順序在多個角度旋轉圖像。我這樣做使用cv2.getRotationMatrix2Dcv2.warpAffine。有一個對像素座標[x,y],其中x = cols,y =行(在這種情況下)我想在旋轉的圖像中找到它們的新座標。在圖像[OpenCV/Python]中查找[x,y]旋轉座標位置

我用的http://www.pyimagesearch.com/2017/01/02/rotate-images-correctly-with-opencv-and-python/下面稍微改變代碼的禮貌和仿射變換的解釋,試圖點旋轉的圖像在地圖中:http://docs.opencv.org/2.4/doc/tutorials/imgproc/imgtrans/warp_affine/warp_affine.html

問題是我的映射或我的旋轉是錯誤的,因爲轉換後的計算座標是錯誤的。 (我試圖手動計算的角,簡單驗證)

CODE

def rotate_bound(image, angle): 
    # grab the dimensions of the image and then determine the 
    # center 
    (h, w) = image.shape[:2] 
    (cX, cY) = ((w-1) // 2.0, (h-1)// 2.0) 


# grab the rotation matrix (applying the negative of the 
# angle to rotate clockwise), then grab the sine and cosine 
# (i.e., the rotation components of the matrix) 
M = cv2.getRotationMatrix2D((cX, cY), -angle, 1.0) 
cos = np.abs(M[0, 0]) 
sin = np.abs(M[0, 1]) 

# compute the new bounding dimensions of the image 
nW = int((h * sin) + (w * cos)) 
nH = int((h * cos) + (w * sin)) 
print nW, nH 

# adjust the rotation matrix to take into account translation 
M[0, 2] += ((nW-1)/2.0) - cX 
M[1, 2] += ((nH-1)/2.0) - cY 

# perform the actual rotation and return the image 
return M, cv2.warpAffine(image, M, (nW, nH)) 

#function that calculates the updated locations of the coordinates 
#after rotation 
def rotated_coord(points,M): 
    points = np.array(points) 
    ones = np.ones(shape=(len(points),1)) 
    points_ones = np.concatenate((points,ones), axis=1) 
    transformed_pts = M.dot(points_ones.T).T 
    return transformed_pts 

#READ IMAGE & CALL FCT 
img = cv2.imread("Lenna.png") 
points = np.array([[511, 511]]) 
#rotate by 90 angle for example 
M, rotated = rotate_bound(img, 90) 
#find out the new locations 
transformed_pts = rotated_coord(points,M) 

如果我有例如座標[511,511]我將得到[-0.5, 511.50]([COL,行])當我期望獲得[0,511]

如果我使用w // 2 a 黑色邊框將被添加到圖像上,我的旋轉更新座標將再次關閉。

問題:我怎樣才能找到一個像素座標在一個旋轉的圖像(以一定的角度)使用Python的正確位置?

回答

0

對於這種圖像旋轉的情況,圖像大小在旋轉後以及參考點之後發生變化,必須修改變換矩陣。新用,並且可以使用下面的關係來計算高度:

new.width = H * \罪(\ THETA)+ W * \ COS(\ THETA)

new.height = H * \ COS (\ theta)+ w * \ sin(\ theta)

由於圖像大小發生變化,由於您可能會看到黑色邊框,所以旋轉點(圖像的中心)的座標也會發生變化。那麼它必須在轉換矩陣中考慮到。

我在我的博客解釋一個例子image rotation bounding box opencv

def rotate_box(bb, cx, cy, h, w): 
    new_bb = list(bb)                                     
    for i,coord in enumerate(bb): 
     # opencv calculates standard transformation matrix                            
     M = cv2.getRotationMatrix2D((cx, cy), theta, 1.0) 
     # Grab the rotation components of the matrix)                             
     cos = np.abs(M[0, 0]) 
     sin = np.abs(M[0, 1])                                   
     # compute the new bounding dimensions of the image                            
     nW = int((h * sin) + (w * cos)) 
     nH = int((h * cos) + (w * sin)) 
     # adjust the rotation matrix to take into account translation 
     M[0, 2] += (nW/2) - cx 
     M[1, 2] += (nH/2) - cy 
     # Prepare the vector to be transformed 
     v = [coord[0],coord[1],1] 
     # Perform the actual rotation and return the image 
     calculated = np.dot(M,v) 
     new_bb[i] = (calculated[0],calculated[1]) 
     return new_bb 


## Calculate the new bounding box coordinates 
new_bb = {} 
for i in bb1: 
new_bb[i] = rotate_box(bb1[i], cx, cy, heigth, width) 
0

@ cristianpb的上述Python代碼所對應的C++代碼,如果有人正在尋找一個C++代碼爲像我這樣的:

// send the original angle i.e. don't transform it in radian 
     cv::Point2f rotatePointUsingTransformationMat(const cv::Point2f& inPoint, const cv::Point2f& center, const double& rotAngle) 
     { 
      cv::Mat rot = cv::getRotationMatrix2D(center, rotAngle, 1.0); 
      float cos = rot.at<double>(0,0); 
      float sin = rot.at<double>(0,1); 
      int newWidth = int(((center.y*2)*sin) + ((center.x*2)*cos)); 
      int newHeight = int(((center.y*2)*cos) + ((center.x*2)*sin)); 

      rot.at<double>(0,2) += newWidth/2.0 - center.x; 
      rot.at<double>(1,2) += newHeight/2.0 - center.y; 

      int v[3] = {static_cast<int>(inPoint.x),static_cast<int>(inPoint.y),1}; 
      int mat3[2][1] = {{0},{0}}; 

      for(int i=0; i<rot.rows; i++) 
      { 
       for(int j=0; j<= 0; j++) 
       { 
        int sum=0; 
        for(int k=0; k<3; k++) 
        { 
         sum = sum + rot.at<double>(i,k) * v[k]; 
        } 
        mat3[i][j] = sum; 
       } 
      } 
      return Point2f(mat3[0][0],mat3[1][0]); 
     }