在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
自己常用的函数,怕忘了,所以记录一下。