DIP 数字图像处理1:图像的旋转


使用库函数实现旋转,仿射变换

import cv2  # 3.4.2 py37
import matplotlib.pyplot as plt

img = cv2.imread('D:\\Chapter2_1.pgm')
rows, cols, channel = img.shape
degree = 15

M = cv2.getRotationMatrix2D((int(cols / 2), int(rows / 2)), -degree, 1)  # 仿射矩阵
dst = cv2.warpAffine(img, M, (cols, rows), flags=cv2.INTER_NEAREST)  # 仿射变换

plt.imshow(dst)
plt.show()

在这里插入图片描述

自己写函数实现旋转

# coding:utf-8
# py37
# 2019年4月21日14:29:18
# 自己写的图像旋转函数,最近邻插值和双线性插值,旋转矩阵形状是(3,3),OpenCV调库的仿射矩阵是(2,3)的,省略了最后一行的 [0, 0, 1]
# 核心思想是将原始图像上的点的值赋值给旋转后的图像。即找到每一个旋转后的点在原图像上的值(最近邻值,或者双线性插值等)
import cv2  # 3.4.2
import numpy as np
import math
import matplotlib.pyplot as plt


def rgetRotationMatrix(img, centerPoint, angle=0):
    """
    :param img:  图像的矩阵
    :param centerPoint: 旋转的中心点
    :param angle: 顺时针旋转的角度
    :return: 仿射矩阵(左乘原始矩阵可以得到仿射变换后的矩阵)
    """
    CX, CY = centerPoint[0], centerPoint[1]
    height, width, channel = img.shape

    angle *= math.pi / 180  # 单位转换

    # A0 将图片中心移动到原点的矩阵
    A0 = np.array([[1, 0, -CX],
                   [0, 1, -CY],
                   [0, 0, 1]])
    # A1旋转图片的矩阵
    A1 = np.array([[math.cos(angle), -math.sin(angle), 0],
                   [math.sin(angle), math.cos(angle), 0],
                   [0, 0, 1]])
    # A2 将图片中心 移回
    A2 = np.array([[1, 0, CX],
                   [0, 1, CY],
                   [0, 0, 1]])

    A = A2.dot(A1).dot(A0)  # 连乘求仿射矩阵
    return A


def rotate(img, A, flag=0):
    """
    :param img:  待旋转矩阵
    :param A: 仿射变换矩阵
    :param flag: 插值法 0为最近邻插值,1为双线性插值
    :return: 旋转后的矩阵
    """

    height, width, channel = img.shape
    newImg = np.zeros((height, width, channel), dtype=int)

    A_ = np.linalg.inv(A)  # 求逆矩阵

    for new_r in range(height):  # 遍历新图片,在原图片上找对应的点(最近邻)
        for new_c in range(width):
            old_c = A_.dot(np.array([[new_c], [new_r], [1]]))[0]  # 当前点对应的原图中的坐标
            old_r = A_.dot(np.array([[new_c], [new_r], [1]]))[1]

            if flag == 0:  # 最近邻法
                # 四舍五入后取整 相当于找最近的点
                old_c = int(old_c.round())
                old_r = int(old_r.round())

                if old_r >= 0 and old_r < height and old_c >= 0 and old_c < width:

                    for ch in range(channel):
                        newImg[new_r][new_c][ch] = img[old_r][old_c][ch]


            elif flag == 1:  # 双线性插值法
                # 在原图中周围四个点的坐标
                x0 = int(old_c)
                y0 = int(old_r)
                x1 = int(old_c) + 1
                y1 = int(old_r) + 1

                a = old_c - int(old_c)  # 将偏差距离作为权重
                b = old_r - int(old_r)

                # 线性插值取值公式:
                if y1 >= 0 and y1 < height - 1 and x1 >= 0 and x1 < width - 1:
                    for ch in range(channel):
                        val = a * b * (int(img[y0][x0][ch]) + int(img[y1][x1][ch]) - int(img[y1][x0][ch]) - int(
                            img[y0][x1][ch])) \
                              + a * (int(img[y1][x0][ch]) - int(img[y0][x0][ch])) + b * (
                                      int(img[y0][x1][ch]) - int(img[y0][x0][ch])) \
                              + int(img[y0][x0][ch])  # 这里计算的时候需要将所有的数据转成是 整型之后再加减 否者会相见后的数字会特别大,图片就会有大量的白点??为什么不懂

                        newImg[new_r][new_c][ch] = int(val)
                        # if val > 250 or val < 0:
                        #     print(val)
    return newImg


if __name__ == "__main__":
    print(cv2.__version__)  # 3.4.2
    img = cv2.imread('D:\\Chapter2_1.pgm')
    for c in range(img.shape[2]):
        img[50:100, 50:100, c] = 255
    height, width, channel = img.shape

    CX = int((height + 1) / 2)
    CY = int((width + 1) / 2)
    for f in range(2):
        M = rgetRotationMatrix(img, [0, 0], angle=15)  # 顺时针旋转15度的仿射矩阵
        # M_ = rgetRotationMatrix(img, [0, 0], angle=-15)  # 逆时针旋转15度的仿射矩阵
        M_ = np.linalg.inv(M)  # 逆时针旋转15度的仿射矩阵
        newImg1 = rotate(img, M, flag=f)  # 顺时针旋转15度
        newImg1_ = rotate(newImg1, M_, flag=f)  # 旋转回去15度

        # 作图并显示
        plt.subplot(221), plt.imshow(img), plt.title('Input')
        plt.subplot(222), plt.imshow(newImg1), plt.title('newImg1')
        plt.subplot(223), plt.imshow(newImg1_), plt.title('newImg1_')
        plt.subplot(224), plt.imshow(img - newImg1_), plt.title('img - newImg1_')
        plt.show()

在这里插入图片描述
END

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值