import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D import 透视变换 import cv2 def build_3d_rotation_matrix(elev, azim, roll): """生成基于elev/azim/roll的完整旋转矩阵""" elev_rad = np.radians(elev) azim_rad = np.radians(azim) roll_rad = np.radians(roll) # 绕x轴旋转(elevation) Rx = np.array([ [1, 0, 0], [0, np.cos(elev_rad), -np.sin(elev_rad)], [0, np.sin(elev_rad), np.cos(elev_rad)] ]) # 绕y轴旋转(azimuth) Ry = np.array([ [np.cos(azim_rad), 0, np.sin(azim_rad)], [0, 1, 0], [-np.sin(azim_rad), 0, np.cos(azim_rad)] ]) # 绕z轴旋转(roll) Rz = np.array([ [np.cos(roll_rad), -np.sin(roll_rad), 0], [np.sin(roll_rad), np.cos(roll_rad), 0], [0, 0, 1] ]) return Rz @ Ry @ Rx # 组合旋转顺序 if __name__ == '__main__': # 参数设置 elev, azim, roll = 34, 0,-35 rotation_3d = build_3d_rotation_matrix(elev, azim, roll) # 创建单位圆 theta = np.linspace(0, 2 * np.pi, 100) x = np.cos(theta) y = np.sin(theta) z = np.zeros_like(x) circle = np.vstack((x, y, z)) # 3xN circle_transformed = rotation_3d @ circle # 逆矩阵 inverse_matrix = np.linalg.inv(rotation_3d) # 画图 fig = plt.figure(figsize=(12, 6)) # 设置窗口透明度 fig.canvas.manager.window.attributes('-alpha', 0.6) # 设置窗口透明度为 0.6 ax1 = fig.add_subplot(121, projection='3d') ax2 = fig.add_subplot(122, projection='3d') # 标识圆心 ax1.scatter(0, 0, 0, color='red', s=20, label='Center') # 原始单位圆 ax1.plot(circle[0], circle[1], circle[2], label='Original Circle') # 原始单位圆 横轴和纵轴 ax1.plot(circle[0], np.zeros_like(theta), circle[2], label='z View', color='r') ax1.plot(np.zeros_like(theta), circle[1], circle[2], label='h View', color='b') ax1.set_title('Original Circle (elev=90°, roll=0°)') ax1.set_xlim([-1, 1]) ax1.set_ylim([-1, 1]) ax1.set_zlim([-1, 1]) ax1.set_box_aspect([1, 1, 1]) ax1.set_xlabel('X') ax1.set_ylabel('Y') ax1.set_zlabel('Z') ax1.view_init(elev=90, azim=90) # 从Z轴方向观察 保持opencv方向一致 x->左 y->下 # 变换后的单位圆 # 标识圆心 ax2.scatter(0, 0, 0, color='red', s=20, label='Center') ax2.plot(circle_transformed[0], circle_transformed[1], circle_transformed[2], color='r', label='Transformed Circle') ax2.set_title('Transformed (elev=52°, roll=-35°)') ax2.set_xlim([-1, 1]) ax2.set_ylim([-1, 1]) ax2.set_zlim([-1, 1]) ax2.set_xlabel('X') ax2.set_ylabel('Y') ax2.set_zlabel('Z') ax2.set_box_aspect([1, 1, 1]) ax2.view_init(elev=90, azim=90) # 从Z轴方向观察 plt.show() image_zhen= cv2.imread("images/trans/transformed_image.jpg") image_xie = cv2.imread("images/trans/subRawImg.jpg") # transformed_image_hy = cv2.warpPerspective(transformed_image, inverse_matrix, dsize=(image.shape[1], image.shape[0])) # # 执行变换(自动计算输出图像尺寸) # 裁剪像素值到 [0, 255] 范围 # 获取图像的大小 height, width = image_zhen.shape[:2] # 计算中心点坐标 center_x = width // 2 center_y = height // 2 # 构造一个平移矩阵,将原点移到中心 M_translate = np.float32([ [1, 0, -1*center_x], [0, 1, -1*center_y], [0, 0, 1] ]) image_xie_padding = cv2.warpPerspective(image_xie, M_translate, dsize=(image_xie.shape[1], image_xie.shape[0])) cv2.imshow("image_xie_padding", image_xie_padding) # 将平移矩阵与目标变换矩阵结合起来 # inverse_M_combined = np.dot(M_translate, inverse_matrix) inverse_matrix[2][2]=1.0 inverse_M_combined = np.dot(M_translate, inverse_matrix) print(f"斜矩阵={rotation_3d}") rotation_3d_int = np.clip(rotation_3d, 0, 255) print(f"斜矩阵_int={rotation_3d}") print(f"逆矩阵={inverse_M_combined}") inverse_M_combined_int = np.clip(inverse_M_combined, 0, 255) # print(f"逆矩阵_int={inverse_M_combined_int}") transformed_image_hy = cv2.warpPerspective(image_xie, inverse_M_combined_int, dsize=(image_xie.shape[1]*2, image_xie.shape[0]*2)) cv2.imshow("transformed_image_hy", transformed_image_hy) # transformed_image = cv2.warpPerspective(image_zhen, rotation_3d_int,dsize=(image_zhen.shape[1], image_zhen.shape[0])) # cv2.imshow("rotated_img", transformed_image) plt.show() cv2.waitKey(0) # cv2.destroyAllWindows()