You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
126 lines
4.6 KiB
126 lines
4.6 KiB
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()
|