图片旋转后像素情况分析

本文研究图片种某个区域被旋转后,其值变换情况

模拟生成一张 11x11 的图片,在中心点为 (5,5)、宽高为 (3,5)、旋转角为 45 的位置有一个旋转矩形,我们的目标将旋转矩形取出来,存储为 3x5 的标准图片,便于后续对旋转框内目标分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 模拟待处理图片,每个交点是一个像素,里面的值模拟为像素值
import numpy as np
img = np.zeros((11, 11),np.uint8)
i=0
for row in range(11):
for col in range(11):
img[row,col] = i*2
i+=1

# 模拟旋转框
center = (5, 5) # 中心点坐标
size = (3, 5) # 宽度和高度
angle = 45 # 旋转角度

# 设置中心点为255
img[center]=255

# 计算旋转框的四个顶点
rect = cv2.boxPoints(((center[0], center[1]), size, angle))
# rect = np.int0(rect)
rect = np.round(rect)

show_images([img],lines=rect)

图片旋转后像素情况分析-20250201161552

本研究从旋转框内取子图的过程,并且实现以下两种方式取值

  • 大图先旋转,将旋转框摆正后,再取子区域
  • 先从大图取出子区域的外接矩形,摆正这个子区域再取子区域

大图先旋转

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# 求一个点绕另一个点旋转后的位置
def rotate_point(cx, cy, x, y, angle_deg):
# 将角度从度转换为弧度
angle_rad = math.radians(angle_deg)

# 创建旋转矩阵
# 注意:OpenCV的旋转矩阵是逆时针的,这里我们也是逆时针
rotation_matrix = np.array([[math.cos(angle_rad), -math.sin(angle_rad)],
[math.sin(angle_rad), math.cos(angle_rad)]])

# 平移点(x, y)到原点
point_shifted = np.array([x - cx, y - cy])

# 应用旋转矩阵
rotated_point_shifted = np.dot(rotation_matrix, point_shifted)

# 将旋转后的点平移回(cx, cy)
rotated_x = rotated_point_shifted[0] + cx
rotated_y = rotated_point_shifted[1] + cy

return int(rotated_x), int(rotated_y)

# 将大图旋转为0度
w,h=11,11
M = cv2.getRotationMatrix2D((w/2, h/2), angle, 1) # 逆时针角度为正,顺时针角度为负
rotated_image = cv2.warpAffine(img, M, (w, h))

cx, cy = center[0], center[1] # 旋转中心
angle_deg = 45 # 旋转角度(度)
# 所有要旋转的点
now_rect = [rotate_point(cx, cy, rx, ry, -angle_deg) for rx,ry in rect ]

show_images([rotated_image],lines=now_rect)

# 取旋转框内的值
# X=[rx for rx,ry in now_rect]
# Y=[ry for rx,ry in now_rect]
# sub_img1=rotated_image[min(X):max(X),min(Y):max(Y)]

sub_img1 = cv2.getRectSubPix(rotated_image,(size[1],size[0]),center)
print(sub_img1)

图片旋转后像素情况分析-20250201161552-1

实际取出来的像素值是:

1
2
3
[[ 68 85 103 119 136] 
[ 82 110 169 133 151]
[ 97 123 183 148 164]]

先从大图取出小图

首先从大图取出目标区域的最小外接矩形

1
2
3
4
5
6
7
8
9
10
# 获取旋转框的边界
x, y, w, h = cv2.boundingRect(rect)

# 从原图中切出子图
sub_image = img[y:y+h, x:x+w]

# 求出旋转框在子图的位置
new_rect=rect-np.array([[x,y]]).repeat(4,axis=0)

show_images([sub_image],lines=new_rect)

图片旋转后像素情况分析-20250201161552-2

然后旋转以上图片,并取出旋转矩形区域,得到以下结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 将子图旋转为0度
M = cv2.getRotationMatrix2D((w/2, h/2), angle, 1) # 逆时针角度为正,顺时针角度为负
rotated_sub_image = cv2.warpAffine(sub_image, M, (w, h))

cx, cy = center[0]-x, center[1]-y # 旋转中心
angle_deg = 45 # 旋转角度(度)
# 所有要旋转的点
now_rect = [rotate_point(cx, cy, rx, ry, -angle_deg) for rx,ry in new_rect ]

show_images([rotated_sub_image],lines=now_rect)

# 取旋转框内的值
# X=[rx for rx,ry in now_rect]
# Y=[ry for rx,ry in now_rect]
# sub_img2=rotated_sub_image[min(X):max(X),min(Y):max(Y)]

sub_img2 = cv2.getRectSubPix(rotated_sub_image,(size[1],size[0]),(cx, cy))
print(sub_img2)

图片旋转后像素情况分析-20250201161553

实际取出来的像素值是:

1
2
3
[[ 69 85 103 119 136] 
[ 82 110 169 133 151]
[ 97 123 183 148 164]]

可以看出两种方法,除了左上角位置差 1 个像素,其他位置保持一致。但是都可以看出经过旋转后的图片像素,相比较原始图片的像素值,都发生变化

也就是说,通过旋转目标检测找到的目标,如果要在其后使用其他检测,注意像素值已经变化