处理图片数据的时候遇到要旋转图片的需求,记录一下解决方案。
- 利用PIL和torchvision.transforms.functional
这是一个常用的图像处理的方法,可以对图像进行裁剪旋转等等操作,对于大图片来说,得到的效果很好,具体的实现代码为:
from PIL import Image
import torchvision.transforms.functional as TF
image = Image.fromarray(np.uint8(point_set))
image = TF.rotate(image, 45)
pts = np.asarray(image)
输入图片矩阵,将其转换格式,旋转,再将格式转化为矩阵即可得到旋转后的图片矩阵。
- 手写一个
方法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度,得到的结果为:
[[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<pic.shape[0] and 0<=sry<pic.shape[1]:
pic_rotate[srx][sry] = pic[x][y]
return pic_rotate
这个旋转函数提供的是逆时针旋转,如果想顺时针的话,可以更改一下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行,但点尽可能多的被保留了下来,符合我的要求。