前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >图像变换-旋转问题来了

图像变换-旋转问题来了

作者头像
叶子陪你玩
发布2022-01-05 10:36:50
3820
发布2022-01-05 10:36:50
举报
文章被收录于专栏:叶子陪你玩编程

上次写了图像变换-旋转问题,试一试?,后面留了个问题,本来就是随便说说的,留给大家一个探索的机会,刚好碰到最近事情也有点多,没空弄。

不过随着和有点意思同学在后台的不断留言交流,发现留了好多坑了,赶紧抽个时间,先填上一个再说。

下面开始正文。

下面有一个矩3*3的矩阵(你也可以看做二维列表)。

代码语言:javascript
复制
[[1 2 3]
 [4 5 6]
 [7 8 9]]

问题1:顺时针旋转90度,得到以下矩阵。

代码语言:javascript
复制
[[7 4 1]
 [8 5 2]
 [9 6 3]]

参考:

代码语言:javascript
复制
import numpy as np
a = np.array(np.arange(1,10)).reshape(3,3)
print(a)
n = len(a)
b = a.copy()
for i in range(n):
     for j in range(n):
         b[i][j] = a[n-1-j][i] # 顺时针旋转90
         # b[i][j] = a[j][n - 1 - i] # 逆时针旋转90
print(b)

说明:这里的解法比较好理解,但是双重循环复杂度比较高,看了网上的解法,有四种,感兴趣的可以自己搜索。

问题2:对矩阵进行镜像操作

代码语言:javascript
复制
[[3 2 1]
 [6 5 4]
 [9 8 7]]

参考:

代码语言:javascript
复制
import numpy as np
a = np.array(np.arange(1,10)).reshape(3,3)
print(a)
b = a[:,::-1]
print(b)

问题3:上下翻转操作。

代码语言:javascript
复制
[[7 8 9]
 [4 5 6]
 [1 2 3]]

参考:

代码语言:javascript
复制
import numpy as np

a = np.array(np.arange(1,10)).reshape(3,3)
print(a)
b = a[::-1] # 上下翻转
print(b)

上面仅仅是以数字作为测试,真实图片,只需将a替换成图像矩阵即可,其余不变。

代码语言:javascript
复制
from PIL import Image
import numpy as np
img = Image.open("cat.png")
a = np.asarray(img)
...

上面的图像变换相对来说比较简单,主要就是像素的位置替换了一下。

不过除了上面的,还有一些其它的图像变换,比如图像缩放(放大、缩小),其它角度旋转、平移等各种操作;

这类几何变换,相对于前面提到的变换,尽管还是改同样变了原图像像素点在新图像中的空间位置,但是也引入了一些新的问题。

平移

代码语言:javascript
复制
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
# 平移
def move(image, delta_x,delta_y):
    rows,cols = image.shape[:2]
    empty_image = np.zeros(image.shape,dtype=np.uint8)
    transform=np.array([delta_x,delta_y])
    for row in range(rows):
        for col in range(cols):
            x1,y1 = np.array([row,col])+transform
            if x1<rows and x1>=0 and y1<cols and y1 >=0:
                empty_image[x1][y1]=image[row][col]
    return empty_image
    
img = Image.open("cat.png")
image = np.asarray(img)
image = move(image,50,250)
plt.imshow(image)
plt.show()

平移比较简单,主要就是矩阵的加法,超出部分删除。

旋转

代码语言:javascript
复制
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image

def rotate(image,angle):
    cos = np.math.cos(np.math.radians(angle))
    sin = np.math.sin(np.math.radians(angle))
    transform = np.array([[cos, -sin],
                  [sin, cos]])
    rows, cols = image.shape[:2]
    empty_image = np.zeros(image.shape, dtype=np.uint8)
    for row in range(rows):
        for col in range(cols):
             # 计算旋转后的坐标
             x1,y1 = transform.dot(np.array([row,col]))
             # 只计算范围之内的
             if x1 < rows and x1 >= 0 and y1 < cols and y1 >= 0:
                 # 通过原图像的坐标计算旋转之后的坐标,并将相应的灰度值传给旋转后的图像
                 empty_image[int(x1)][int(y1)] = image[row][col]

    return empty_image
    
img = Image.open("cat.png")
image = np.asarray(img)
image = rotate(image,-30)
plt.imshow(image)
plt.show()

旋转可以看做图片上的每个点旋转。

换算后得到下面的公式。

这里是以图片左上角旋转的,超出边界部分删除了。得到的结果出现了一些有规律的噪声,之所以出现这样的问题,是因为通过原图像的坐标计算旋转之后的坐标,并将相应的灰度值传给旋转后的图像。得到的坐标有些是小数,进行了取整操作,这样部分像素并没有对应的像素值。

要实现下面这种效果,首先需要以图像的中心作为中心点,然后采取后向映射的方法——即从旋转后的图像出发,找到对应的原图像的点,然后将原图像中的灰度值传递过来即可,这样旋转后的图像的每个像素肯定可以对应到原图像中的一个点。

具体实现方式可参考这两篇文章,都是一些数学运算,讲的比较清楚了:

https://blog.csdn.net/lkj345/article/details/50555870

https://www.jianshu.com/p/56a717173227

如果需要多次变换(缩放,旋转,平移),需要引入齐次坐标(在微信读书数字图像处理上看到的),通过齐次坐标,不管怎样变换,变换多少次,都可以表示成一连串的矩阵相乘了

例如先放大2倍,然后旋转45度,然后再缩小0.5倍。

而平移用的是矩阵加法,不通用,通过齐次坐标,下面两个结果是一样的,加法变成了乘法。

都是数学,线性代数当年觉得没啥用,现在发现真香,可惜没学好,详细的的为什么要引入齐次坐标,可以看下面这篇,通透:

https://blog.csdn.net/saltriver/article/details/79680364?spm=1001.2014.3001.5501

代码语言:javascript
复制
(全文完)
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-12-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 叶子陪你玩编程 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档