任意角度旋转图片(python)

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

  1. 利用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. 手写一个

方法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行,但点尽可能多的被保留了下来,符合我的要求。

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值