任意⾓度旋转图⽚(python)
处理图⽚数据的时候遇到要旋转图⽚的需求,记录⼀下解决⽅案。
1. 利⽤PIL和ansforms.functional
这是⼀个常⽤的图像处理的⽅法,可以对图像进⾏裁剪旋转等等操作,对于⼤图⽚来说,得到的效果很好,具体的实现代码为:
from PIL import Image
ansforms.functional as TF
image = Image.fromarray(np.uint8(point_t))
image = TF.rotate(image,45)
pts = np.asarray(image)
输⼊图⽚矩阵,将其转换格式,旋转,再将格式转化为矩阵即可得到旋转后的图⽚矩阵。
2. ⼿写⼀个
⽅法1对于矩阵⽐较⼤的时候效果⽐较好,但当矩阵⽐较⼩的时候,旋转过后会有很多空⽩截断出现。举个例⼦:
我现在有⼀个10*10的斜线图⽚矩阵:
[[1.0.0.0.0.0.0.0.0.0.]
[0.1.0.0.0.0.0.0.0.0.]
[0.0.1.0.0.0.0.0.0.0.]
[0.0.0.1.0.0.0.0.0.0.]
[0.0.0.0.1.0.0.0.0.0.]
[0.0.0.0.0.1.0.0.0.0.]
[0.0.0.0.0.0.1.0.0.0.]
[0.0.0.0.0.0.0.1.0.0.]
[0.0.0.0.0.0.0.0.1.0.]
[0.0.0.0.0.0.0.0.0.1.]]
如果⽤⽅法1来解决的话,当我逆时针旋转45度,得到的结果为:
[[0000000000]
[0000000000]
[0000000000]
[0000000000]
[010*******]
[010*******]
[0000000000]
[0000000000]
[0000000000]
[0000000000]]
可以发现,由于旋转后的线应该位于4.5⾏(从0开始算),⽅法1间断地给4、5⾏赋值,当图⽚⽐较⼤的时候,这就能呈现出⼀个模糊的线的效果,然⽽当矩阵⽐较⼩的时候,就会变成间断的点。⽽在我的需求中,我对位置的精确度没有⾮常的敏感,但我希望每个被赋值的点都能尽可能的被投射到新的矩阵⾥,所以只能根据⾃⼰的需求⼿写⼀个:
def rotate_pic(pic, an):
''' pic: 2d array '''
pt0 =[(pic.shape[0]-1)/2,(pic.shape[1]-1)/2]
pic_rotate = np.zeros((pic.shape[0], pic.shape[1]))
for x in range(pic.shape[0]):
for y in range(pic.shape[1]):
if pic[x][y]>0:
srx =round((x - pt0[0])* s(an)-(y - pt0[1])* math.sin(an)+ pt0[0])
sry =round((x - pt0[0])* math.sin(an)+(y - pt0[1])* s(an)+ pt0[1])
if0<=srx<pic.shape[0]and0<=sry<pic.shape[1]:
pic_rotate[srx][sry]= pic[x][y]
return pic_rotate
这个旋转函数提供的是逆时针旋转,如果想顺时针的话,可以更改⼀下srx,sry的计算:
srx =(x - pt0[0])*s(an)+(y - pt0[1])*math.sin(an)+pt0[0]
sry =(y - pt0[1])*s(an)-(x - pt0[0])*math.sin(an)+pt0[1]
最后得到的结果为:
[[0.0.0.0.0.0.0.0.0.0.]
[0.0.0.0.0.0.0.0.0.0.]
[0.0.0.0.0.0.0.0.0.0.]
[0.0.0.0.0.0.0.0.0.0.]
[1.1.1.0.1.1.0.1.1.1.]
[0.0.0.0.0.0.0.0.0.0.]
[0.0.0.0.0.0.0.0.0.0.]
[0.0.0.0.0.0.0.0.0.0.]
[0.0.0.0.0.0.0.0.0.0.]
[0.0.0.0.0.0.0.0.0.0.]]
可以发现,由于使⽤了四舍五⼊,线上移了0.5⾏,但点尽可能多的被保留了下来,符合我的要求。