旋转的角度正数负数
/*
math coordinate, x right, y upper, clockwise angle < 0, anti-clockwise angle > 0(x->y)
image coordinate, x right, y down, clockwise angle > 0(x->y), anti-clockwise angle < 0
*/
/*
math coordinate, x right, y upper, clockwise angle < 0, anti-clockwise angle > 0(x->y)
ego coordinate, y right, z upper, clockwise angle < 0, anti-clockwise angle > 0(y->z)
*/
import **cv2** import **numpy** as **np** def **rotate_point**(): point = **np**.**array**([200, 100]) image = **np**.**zeros**((400, 400, 3), dtype = **np**.uint8) **cv2**.**circle**( image, point, 6, (0, 0, 255), thickness = 2 ) center = **np**.**array**([200, 200]) **cv2**.**circle**( image, center, 1, (0, 0, 255), thickness = 2 ) angle = -90 * **np**.pi / 180 mat = **np**.**array**( [[**np**.cos(angle), -**np**.sin(angle)], \ [**np**.sin(angle), **np**.cos(angle)]] ) pn = point **-** center pn = **np**.**reshape**(pn, (2, 1)) now = **np**.matmul(mat, pn) now = **np**.**asarray**(now, dtype=**np**.int32) now = now.**flatten**() **+** center **cv2**.**circle**( image, now.**tolist**(), 9, (255, 0, 0), thickness = 2 ) **cv2**.**imwrite**("/home/Desktop/stixel-world_summer_original/scripts/tmp.jpg", image) if __name__ == '__main__': **rotate_point**()OpenCV 二维点旋转问题解析
你现在遇到现象:数学上旋转矩阵角度为负,代表顺时针旋转;角度为正,才是逆时针旋转,这是很多人踩坑的关键点。
1. 数学坐标系 vs OpenCV图像坐标系
标准数学笛卡尔坐标系:x向右,y向上
θ>0\theta>0θ>0:逆时针旋转
θ<0\theta<0θ<0:顺时针旋转
OpenCV图像坐标系:x向右,y向下(y轴翻转)
同样一套旋转矩阵,行为会反过来!
数学旋转矩阵 [ cosθ, -sinθ ] [ sinθ, cosθ ]你的代码
angle = -90 * np.pi / 180 # -90° mat = np.array( [[np.cos(angle), -np.sin(angle)], [np.sin(angle), np.cos(angle)]] )在数学坐标系:
-90°= 顺时针转90度在图像(y向下)坐标系:
-90°实际表现为逆时针90°,+90°会变成顺时针90°。
重点:图像y轴向下,旋转方向和教科书数学定义是反过来的。
2. 完整修正代码,加上注释
import cv2 import numpy as np def rotate_point(): # 原始点 (x,y) point = np.array([200, 100]) image = np.zeros((400, 400, 3), dtype = np.uint8) # 画原始点:红色 cv2.circle( image, point, 6, (0, 0, 255), thickness = 2 ) # 旋转中心 center = np.array([200, 200]) cv2.circle( image, center, 1, (0, 0, 255), thickness = 2 ) # =========关键========= # 图像坐标系 y轴向下: # 想要【逆时针旋转90度】,angle 给 +90° 数学矩阵得到的是顺时针; # 想要图像画面上视觉逆时针90度,要填 angle = -90° angle_deg = -90 angle = angle_deg * np.pi / 180 # 标准2D旋转矩阵 rot_mat = np.array([ [np.cos(angle), -np.sin(angle)], [np.sin(angle), np.cos(angle)] ]) # 步骤1:平移,把原点挪到旋转中心 p_rel = point - center p_rel = p_rel.reshape(2,1) # 步骤2:矩阵旋转 p_rot_rel = rot_mat @ p_rel # 步骤3:平移回去 p_rot = (p_rot_rel.flatten() + center).astype(np.int32) # 画旋转后点:蓝色圆圈 cv2.circle( image, p_rot.tolist(), 9, (255, 0, 0), thickness = 2 ) cv2.imwrite("/home/Desktop/stixel-world_summer_original/scripts/tmp.jpg", image) if __name__ == '__main__': rotate_point()3. 如果你想统一逻辑:完全符合数学笛卡尔坐标系(y向上)
如果不想被图像y向下搞混淆,可以手动对y坐标取负:
# point (x,y_img) → math (x, -y_img) # 旋转后再还原 y4. OpenCV自带函数参考(cv2.getRotationMatrix2D)
cv2的旋转矩阵内部已经适配图像y向下,行为和手写矩阵一致。
# 注意!cv2.getRotationMatrix2D角度定义:正数=图像上逆时针 M = cv2.getRotationMatrix2D(center=(200,200), angle=-90, scale=1.0) dst = cv2.warpAffine(image, M, (400,400))⚠️注意:cv2.getRotationMatrix2D的角度定义:正数,图像视觉逆时针旋转,和手写纯数学矩阵符号是相反的。
对照表(图像坐标系 y向下)
| 想要画面视觉效果 | 手写数学矩阵 angle | cv2.getRotationMatrix2D angle |
|---|---|---|
| 逆时针90° | -90° * pi/180 | +90 |
| 顺时针90° | +90° * pi/180 | -90 |
你的现象解释
你代码里面写angle=-90,手写数学矩阵,输出画面上就是视觉逆时针旋转90度。
不是bug,根源就是图像y轴朝下,旋转方向反转。
如果你需要,我可以给你画一张坐标变换示意图代码,直观看到y轴翻转带来方向反转。