在图像[OpenCV/Python]中查找[x,y]旋转坐标位置

问题描述:

我想按顺序在多个角度旋转图像。我这样做使用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的正确位置?

对于这种图像旋转的情况,图像大小在旋转后以及参考点之后发生变化,必须修改变换矩阵。新用,并且可以使用下面的关系来计算高度:

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) 

@ 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]); 
     }