opencv图像旋转矩阵

在Python opencv中图像旋转矩阵可以用来旋转源图片到目标图片、旋转源坐标点到目标坐标点。根据图像旋转矩阵还可以逆向根据目标坐标点得到原始点的位置。

将常用的旋转函数汇总一下

1. 根据中心坐标点旋转图片

# 输入为三通道图片以及需要顺时针旋转的角度
def rotate_image(image, angle):
    (h, w) = image.shape[:2]
    (cX, cY) = (w // 2, h // 2)
    M = cv2.getRotationMatrix2D((cX, cY), angle, 1.0)
    cos = np.abs(M[0, 0])
    sin = np.abs(M[0, 1])
    nW = int((h * sin) + (w * cos))
    nH = int((h * cos) + (w * sin))
    M[0, 2] += (nW / 2) - cX
    M[1, 2] += (nH / 2) - cY
    # perform the actual rotation and return the image
    return cv2.warpAffine(image, M, (nW, nH)),M

下面是另一个类似的

def func1(image,degree):
    height, width = image.shape[:2]
    heightNew = int(width * fabs(sin(radians(degree))) + height * fabs(cos(radians(degree))))
    widthNew = int(height * fabs(sin(radians(degree))) + width * fabs(cos(radians(degree))))
    matRotation = cv2.getRotationMatrix2D((width / 2, height / 2), -degree, 1)
    matRotation[0, 2] += (widthNew - width) / 2
    matRotation[1, 2] += (heightNew - height) / 2
    imgRotation = cv2.warpAffine(image, matRotation, (widthNew, heightNew), borderValue=(255, 255, 255))
    return imgRotation, matRotation

2. 坐标点进行旋转操作

def rotate_boxes(boxes,angle,h,w):
    (cX, cY) = (w // 2, h // 2)
    M = cv2.getRotationMatrix2D((cX, cY), angle, 1.0)
    cos = np.abs(M[0, 0])
    sin = np.abs(M[0, 1])
    nW = int((h * sin) + (w * cos))
    nH = int((h * cos) + (w * sin))
    M[0, 2] += (nW / 2) - cX
    M[1, 2] += (nH / 2) - cY
    points = np.array(boxes).reshape((4,2))
    ones = np.ones(shape=(4, 1))
    points_ones = np.concatenate((points, ones), axis=1)

    transformed_pts = M.dot(points_ones.T).T
    return transformed_pts 

3. 根据目标坐标点得到源坐标点

小角度可以采用这样的方式,但是这个代码存在一个问题,这是根据矩阵的乘法逆推到的,当h1=0或者 (h2 * h4 - h1 * h5)=0的时候,结果会有问题。

def transformPTs_inverse(pts, H):
    H_inverse = np.linalg.pinv(H)
    pts = np.array(pts)
    num = pts.shape[0]
    newpts = []
    h1, h2, h3, h4, h5, h6 = H[0][0], H[0][1], H[0][2], H[1][0], H[1][1], H[1][2]
    for i in range(num):
        x1, y1 = pts[i]
        y0 = (x1 * h4 - y1 * h1 - h3 * h4 + h1 * h6) / (h2 * h4 - h1 * h5)
        x0 = (x1 - h3 - h2*y0)/h1
        newpts.append([int(x0), int(y0)])
    repts = np.array([newpts[3], newpts[0], newpts[1], newpts[2]])
    return rept

第二种方法:


def transformPTs_inverse_homography(pts, H):
    H_inverse = np.linalg.pinv(H)
    pts = np.array(pts)
    num = pts.shape[0]
    newpts = []
    for i in range(num):
        newpt = np.dot(H_inverse, pts[i].tolist() + [1])
        newpt = newpt/newpt[-1] # Homogeneous
        newpts.append(newpt[:-1])
    newpts = np.array(newpts)
    return newpts

对于大角度比如90,180,270度角,可以采用一种比较笨的方法

# 这里的输入pts是长度为8的数组,分别为左上角、右上角、左下角、右下角的顺序。
def stupid_inverse(pts, angle, H):
    pts = np.array(pts).reshape((4, 2))
    num = pts.shape[0]
    h1, h2, h3, h4, h5, h6 = H[0][0], H[0][1], H[0][2], H[1][0], H[1][1], H[1][2]
    newpts = []
    if angle == 90:
        for i in range(num):
            x1, y1 = pts[i]
            x0 = h6 - y1
            y0 = x1 - h3
            newpts.append([int(x0), int(y0)])
        repts = np.array([newpts[2], newpts[0], newpts[3], newpts[1]])
    elif angle == 180:
        for i in range(num):
            x1, y1 = pts[i]
            x0 = h3 - x1
            y0 = h6 - y1
            newpts.append([int(x0), int(y0)])
        repts = np.array([newpts[3], newpts[2], newpts[1], newpts[0]])
    elif angle == 270:
        for i in range(num):
            x1, y1 = pts[i]
            x0 = y1
            y0 = h3 - x1
            newpts.append([int(x0), int(y0)])
        repts = np.array([newpts[1], newpts[3], newpts[0], newpts[2]])

    else:
        repts = pts
    repts = repts.reshape(-1)
    return repts

自己常用的函数,怕忘了,所以记录一下。

你可能感兴趣的:(opencv图像旋转矩阵)