python数字图像处理笔记10 图像旋转

图像旋转

在这里插入图片描述
旋转前
在这里插入图片描述
旋转后
在这里插入图片描述
矩阵表示
在这里插入图片描述

def rotate(img, angle):
    H, W, C = img.shape

    anglePi = angle * math.pi / 180.0
    cosA = math.cos(anglePi)
    sinA = math.sin(anglePi)

    out = np.zeros((H, W, C), dtype=np.uint8)  # 必须是8 不然显示不出图像
    for y in range(H):
        for x in range(W):
            x0 = int(x * cosA + y * sinA)
            y0 = int(y * cosA - x * sinA)
            if 0 < x0 < W and 0 < y0 < H:  # 计算结果是这一范围内的x0,y0才是原始图像的坐标。
                out[y0, x0] = img[y, x]

    return out

在这里插入图片描述
旋转后的图像有很多“蜂窝煤”。主要是点转换后要取整。导致原图中有些点映射到同一个点,而生成的图中有些点在原图中没有点映射到它。所以出现了很多“蜂窝煤”。

以图像的中心进行旋转

在这里插入图片描述
在矩阵中的坐标系通常是AB和AC方向的,而数学坐标系坐标系是DE和DF方向的。

令图像表示为M×N的矩阵,对于点A而言,两坐标系中的坐标分别是(0,0)和(-N/2,M/2)

矩阵中点(x’,y’)转换为笛卡尔坐标系(x,y)的转换关系为:
在这里插入图片描述
逆变换为
在这里插入图片描述
最后结果
1.首先将图像坐标系转换为数学坐标系。
2.使用旋转公式对坐标进行旋转。
3.将旋转后的数学坐标系转换为图像坐标系。
在这里插入图片描述
在这里插入图片描述

def rotate(img, angle):
    H, W, C = img.shape

    anglePi = angle * math.pi / 180.0
    cosA = math.cos(anglePi)
    sinA = math.sin(anglePi)

    out = np.zeros((H, W, C), dtype=np.uint8)  # 必须是8 不然显示不出图像

    for y in range(H):
        for x in range(W):

            x0 = int(cosA * x - sinA * y - 0.5 * W * cosA + 0.5 * H * sinA + 0.5 * W)
            y0 = int(sinA * x + cosA * y - 0.5 * W * sinA - 0.5 * H * cosA + 0.5 * H)
            if 0 < x0 < W and 0 < y0 < H:  # 计算结果是这一范围内的x0,y0才是原始图像的坐标。
                out[y0, x0] = img[y, x]

    return out

在这里插入图片描述

完整显示图片

图片旋转后图片可能变大
在这里插入图片描述
N’和M’对应于新图的宽和高
在这里插入图片描述
新图像的宽和高计算公式
在这里插入图片描述

def rotate(img, angle):
    H, W, C = img.shape

    anglePi = angle * math.pi / 180.0
    cosA = math.cos(anglePi)
    sinA = math.sin(anglePi)


    # 三角函数计算出来的结果会有小数,所以做了向上取整的操作。
    # size = (W + 1, H + 1)
    new_height = math.ceil(H * cosA + W * sinA)
    new_width = math.ceil(W * cosA + H * sinA)
    out = np.zeros((new_height+1, new_width+1, C), dtype=np.uint8)  # 必须是8 不然显示不出图像

    for y in range(H):
        for x in range(W):

            x0 = int(cosA * x - sinA * y - 0.5 * W * cosA + 0.5 * H * sinA + 0.5 * new_width)
            y0 = int(sinA * x + cosA * y - 0.5 * W * sinA - 0.5 * H * cosA + 0.5 * new_height)
            # if 0 < x0 <= new_width and 0 < y0 <= new_height:  # 计算结果是这一范围内的x0,y0才是原始图像的坐标。
            out[y0, x0] = img[y, x]

    return out

在这里插入图片描述

解决蜂窝煤

采用向后映射法,也可采用后向映射+双线性插值法
图像旋转的过程:1.将图像坐标转换为数学坐标。2.使用图像旋转的逆公式。3.将数学坐标转换为图像坐标。
在这里插入图片描述

在这里插入图片描述

def rotate(img, angle):
    H, W, C = img.shape

    anglePi = angle * math.pi / 180.0
    cosA = math.cos(anglePi)
    sinA = math.sin(anglePi)
    new_height = math.ceil(H * np.cos(anglePi) + W * np.sin(anglePi))
    new_width = math.ceil(W * np.cos(anglePi) + H * np.sin(anglePi))

    out = np.zeros((new_height+1, new_width+1, C), dtype=np.uint8)  # 必须是8 不然显示不出图像

    dx_back = 0.5 * W - 0.5 * new_width * cosA - 0.5 * new_height * sinA
    dy_back = 0.5 * H + 0.5 * new_width * sinA - 0.5 * new_height * cosA
    for y in range(new_height):
        for x in range(new_width):

            x0 =int( x * cosA + y * sinA + dx_back)
            y0 = int(y * cosA - x * sinA + dy_back)
            if 0 < x0 < W and 0 < y0 < H:  # 计算结果是这一范围内的x0,y0才是原始图像的坐标。
                out[y, x] = img[y0, x0]  #。

    return out

在这里插入图片描述
参考链接 https://www.cnblogs.com/xianglan/archive/2010/12/26/1917247.html
参考链接:https://www.cnblogs.com/liwill/p/13875745.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值