日常小技巧|任意角度旋转图片(python)

处理图片数据的时候遇到要旋转图片的需求,记录一下解决方案。

  1. 利用PIL和torchvision.transforms.functional
这是一个常用的图像处理的方法,可以对图像进行裁剪旋转等等操作,对于大图片来说,得到的效果很好,具体的实现代码为:
from PIL import Image import torchvision.transforms.functional as TFimage = Image.fromarray(np.uint8(point_set)) image = TF.rotate(image, 45) pts = np.asarray(image)

输入图片矩阵,将其转换格式,旋转,再将格式转化为矩阵即可得到旋转后的图片矩阵。
  1. 手写一个
方法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.]]

【日常小技巧|任意角度旋转图片(python)】如果用方法1来解决的话,当我逆时针旋转45度,得到的结果为:
[[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 1 0 0 0 1 0 0 1 0] [0 1 0 0 0 1 0 0 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]]

可以发现,由于旋转后的线应该位于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]) * math.cos(an) - (y - pt0[1]) * math.sin(an) + pt0[0]) sry = round((x - pt0[0]) * math.sin(an) + (y - pt0[1]) * math.cos(an) + pt0[1]) if 0<=srx

这个旋转函数提供的是逆时针旋转,如果想顺时针的话,可以更改一下srx,sry的计算:
srx = (x - pt0[0])*math.cos(an) + (y - pt0[1])*math.sin(an)+pt0[0]sry = (y - pt0[1])*math.cos(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行,但点尽可能多的被保留了下来,符合我的要求。

    推荐阅读