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.
163 lines
4.7 KiB
163 lines
4.7 KiB
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()
|