import cv2 import numpy as np from math import cos, sin, radians def get_rotation_matrix(angle_x, angle_y, angle_z): """生成3D旋转矩阵""" # 转换为弧度 rx = radians(angle_x) ry = radians(angle_y) rz = radians(angle_z) # X轴旋转矩阵 mat_x = np.array([ [1, 0, 0], [0, cos(rx), -sin(rx)], [0, sin(rx), cos(rx)] ]) # Y轴旋转矩阵 mat_y = np.array([ [cos(ry), 0, sin(ry)], [0, 1, 0], [-sin(ry), 0, cos(ry)] ]) # Z轴旋转矩阵 mat_z = np.array([ [cos(rz), -sin(rz), 0], [sin(rz), cos(rz), 0], [0, 0, 1] ]) # 组合旋转矩阵 rotation_matrix = np.dot(np.dot(mat_x, mat_y), mat_z) return rotation_matrix def perspective_transform(image, angle_x=0, angle_y=0, angle_z=0, scale=1.0): """应用透视变换""" h, w = image.shape[:2] # 获取旋转矩阵 rotation_matrix = get_rotation_matrix(angle_x, angle_y, angle_z) # 创建3D点到2D点的映射 # 将2D图像视为3D空间中Z=0平面上的物体 points_3d = np.array([ [0, 0, 0], # 左上 [w, 0, 0], # 右上 [w, h, 0], # 右下 [0, h, 0] # 左下 ], dtype=np.float32) # 应用旋转 points_3d_rotated = np.dot(points_3d, rotation_matrix.T) # 添加透视效果 - 这里简单地将Z坐标作为深度 # 可以调整这个值来改变透视强度 points_2d_homo = points_3d_rotated[:, :2] / (scale - points_3d_rotated[:, 2:3] * 0.001) # 计算变换矩阵 src_points = np.array([[0, 0], [w, 0], [w, h], [0, h]], dtype=np.float32) dst_points = points_2d_homo.astype(np.float32) # 计算中心偏移 min_xy = dst_points.min(axis=0) max_xy = dst_points.max(axis=0) dst_points -= min_xy # 计算新图像大小 new_w = int(max_xy[0] - min_xy[0]) new_h = int(max_xy[1] - min_xy[1]) # 获取透视变换矩阵 M = cv2.getPerspectiveTransform(src_points, dst_points) # 应用变换 transformed = cv2.warpPerspective(image, M, (new_w, new_h)) return transformed def combined_perspective_transform(image, angle_x1, angle_y1, angle_z1, angle_y2, scale1=1.0, scale2=1.0): """合并两次变换:第一次任意旋转,第二次Y轴旋转""" h, w = image.shape[:2] # 第一次旋转矩阵 rot1 = get_rotation_matrix(angle_x1, angle_y1, angle_z1) # 第二次旋转矩阵 (Y轴旋转) rot2 = get_rotation_matrix(0, angle_y2, 0) # 合并旋转矩阵 combined_rot = np.dot(rot2, rot1) # 创建3D点到2D点的映射 points_3d = np.array([ [0, 0, 0], # 左上 [w, 0, 0], # 右上 [w, h, 0], # 右下 [0, h, 0] # 左下 ], dtype=np.float32) # 应用合并后的旋转 points_3d_rotated = np.dot(points_3d, combined_rot.T) # 添加透视效果 points_2d_homo = points_3d_rotated[:, :2] / ((scale1 * scale2) - points_3d_rotated[:, 2:3] * 0.001) # 计算变换矩阵 src_points = np.array([[0, 0], [w, 0], [w, h], [0, h]], dtype=np.float32) dst_points = points_2d_homo.astype(np.float32) # 计算中心偏移 min_xy = dst_points.min(axis=0) max_xy = dst_points.max(axis=0) dst_points -= min_xy # 计算新图像大小 new_w = int(max_xy[0] - min_xy[0]) new_h = int(max_xy[1] - min_xy[1]) # 获取透视变换矩阵 M = cv2.getPerspectiveTransform(src_points, dst_points) # 应用变换 transformed = cv2.warpPerspective(image, M, (new_w, new_h)) return transformed def show_transformed(): image = cv2.imread('images/trans/transformed_image.jpg') # 应用透视变换 # 参数说明:angle_x, angle_y, angle_z 分别为绕X,Y,Z轴的旋转角度 # scale 控制透视效果的强度 transformed = perspective_transform(image, angle_x=34, angle_y=43, angle_z=-35, scale=1) # 显示结果 cv2.imshow('Original', image) cv2.imshow('Transformed', transformed) cv2.waitKey(0) cv2.destroyAllWindows() def show_transformed_combined(): image = cv2.imread('images/trans/transformed_image.jpg') if image is None: print("请替换为您的图片路径") else: # 第一次变换:任意角度 # 第二次变换:Y轴旋转90度 final_result = combined_perspective_transform( image, angle_x1=34, angle_y1=0, angle_z1=-35, # 第一次旋转参数 angle_y2=43, # 第二次Y轴旋转90度 scale1=1.2, scale2=1.0 # 透视参数 ) cv2.imshow('Original', image) cv2.imshow('Final Result', final_result) cv2.waitKey(0) cv2.destroyAllWindows() if __name__ == '__main__': show_transformed_combined()