• 《数字图像处理-OpenCV/Python》连载(41)图像的旋转


    《数字图像处理-OpenCV/Python》连载(41)图像的旋转


    本书京东优惠购书链接:https://item.jd.com/14098452.html
    本书CSDN独家连载专栏:https://blog.csdn.net/youcans/category_12418787.html

    在这里插入图片描述


    第 6 章 图像的几何变换


    几何变换分为等距变换、相似变换、仿射变换和投影变换,是指对图像的位置、大小、形状和投影进行变换,将图像从原始平面投影到新的视平面。OpenCV图像的几何变换,本质上是将一个多维数组通过映射关系转换为另一个多维数组。


    本章内容概要

    • 介绍仿射变换,学习使用仿射变换矩阵实现图像的仿射变换。
    • 学习使用函数实现图像的平移、缩放、旋转、翻转和斜切。
    • 介绍投影变换,学习使用投影变换矩阵实现图像的投影变换。
    • 介绍图像的重映射,学习使用映射函数实现图像的自定义变换和动态变换。

    6.1 图像的旋转

    旋转变换属于等距变换,变换后图像的长度和面积不变。
    图像以左上角(0,0)为旋转中心、以旋转角度 θ 顺时针旋转,可以构造旋转变换矩阵 MAR,通过函数 cv.warpAffine 计算旋转变换图像。

    [ x ~ y ~ 1 ] = M A R [ x y 1 ] , M A R = [ c o s θ − s i n θ 0 s i n θ c o s θ 0 0 0 1 ]

    [x~y~1]" role="presentation" style="position: relative;">[x~y~1]
    = M_{AR}
    [xy1]" role="presentation" style="position: relative;">[xy1]
    ,\hspace{1em} M_{AR} =
    [cosθsinθ0sinθcosθ0001]" role="presentation" style="position: relative;">[cosθsinθ0sinθcosθ0001]
    x~y~1 =MAR xy1 ,MAR= cosθsinθ0sinθcosθ0001

    图像以任意点(x,y)为旋转中心、以旋转角度 顺时针旋转,可以先将原点平移到旋转中心(x,y),再对原点进行旋转处理,最后反向平移回坐标原点。

    OpenCV中的函数cv.getRotationMatrix2D可以计算以任意点为中心的旋转变换矩阵。

    函数原型

    cv.getRotationMatrix2D(center, angle, scale) → M

    函数cv.getRotationMatrix2D能根据旋转中心和旋转角度计算旋转变换矩阵M:

    M = [ α β ( 1 − α ) x − β y − β α β x + ( 1 − α ) y ] M =

    [αβ(1α)xβyβαβx+(1α)y]" role="presentation" style="position: relative;">[αβ(1α)xβyβαβx+(1α)y]
    M=[αββα(1α)xβyβx+(1α)y]

    参数说明

    • center:旋转中心坐标,格式为元组(x,y)。
    • angle:旋转角度,角度制,以逆时针方向旋转。
    • scale:缩放系数,是浮点型数据。
    • M:旋转变换矩阵,是形状为(2,3)、类型为np.float32的Numpy数组。

    注意问题

    • (1)函数可以直接获取以任意点为中心的旋转变换矩阵,不需要额外进行平移变换。

    • (2) 如果旋转图像的尺寸与原始图像的尺寸相同,则四角的像素会被切除(见图6-3(2))。为了保留原始图像的内容,需要在旋转的同时对图像进行缩放,或将旋转图像的尺寸调整为:

    W r o t = w c o s θ + h s i n θ H r o t = h c o s θ + w s i n θ W_{rot} = w cos \theta+ h sin \theta \\ H_{rot} = h cos \theta+ w sin \theta Wrot=wcosθ+hsinθHrot=hcosθ+wsinθ
    式中,w、h分别为原始图像的宽度与高度; 、 分别为旋转图像的宽度与高度。

    • (3) 缩放系数scale在旋转的同时能进行缩放,但水平、垂直方向必须使用相同的缩放比例。

    函数cv.rotate用于直角旋转,旋转角度为90度、180度或270度。该方法通过矩阵转置实现,运行速度极快。

    函数原型

    cv.rotate(src, rotateCode[, dst]) → dst

    参数说明

    • src:输入图像,是Numpy数组。
    • dst:输出图像,类型与src相同,图像尺寸由旋转角度确定。
    • rotateCode:旋转标志符。
      • ROTATE_90_CLOCKWISE:顺时针旋转90度。
      • ROTATE_180:顺时针旋转180度。
      • ROTATE_90_COUNTERCLOCKWISE:顺时针旋转270度。

    注意问题

    旋转角度为180度时,输出图像的尺寸与输入图像的尺寸相同;旋转角度为90度或180度时,输出图像的高度和宽度分别等于输入图像的宽度和高度。


    【例程0603】图像的旋转

    本例程介绍以原点为旋转中心、以任意点为旋转中心旋转图像,以及图像的直角旋转。


    # 【0603】图像的旋转
    import cv2 as cv
    import numpy as np
    from matplotlib import pyplot as plt
    
    if __name__ == '__main__':
        img = cv.imread("../images/Fig0301.png")  # 读取彩色图像(BGR)
        height, width = img.shape[:2]  # 图像的高度和宽度
    
        # (1) 以原点为旋转中心
        x0, y0 = 0, 0  # 以左上角顶点 (0,0) 作为旋转中心
        theta, scale = 30, 1.0  # 逆时针旋转 30 度,缩放系数 1.0
        MAR0 = cv.getRotationMatrix2D((x0,y0), theta, scale)  # 旋转变换矩阵
        imgRot1 = cv.warpAffine(img, MAR0, (width, height))  
    
        # (2) 以任意点为旋转中心
        x0, y0 = width//2, height//2  # 以图像中心作为旋转中心
        angle = theta * np.pi/180  # 弧度->角度
        wRot = int(width * np.cos(angle) + height * np.sin(angle))  # 调整宽度
        hRot = int(height * np.cos(angle) + width * np.sin(angle))  # 调整高度
        scale = width/wRot  # 根据 wRot 调整缩放系数
        MAR1 = cv.getRotationMatrix2D((x0,y0), theta, 1.0)  # 逆时针旋转 30 度,缩放系数 1.0
        MAR2 = cv.getRotationMatrix2D((x0,y0), theta, scale)  # 逆时针旋转 30 度,缩放比例 scale
        imgRot2 = cv.warpAffine(img, MAR1, (height, width), borderValue=(255,255,255))  # 白色填充
        imgRot3 = cv.warpAffine(img, MAR2, (height, width))  # 调整缩放系数,以保留原始图像的内容
        print(img.shape, imgRot2.shape, imgRot3.shape, scale)
    
        # (3) 图像的直角旋转
        imgRot90 = cv.rotate(img, cv.ROTATE_90_CLOCKWISE)  # 顺时针旋转 90度
        imgRot180 = cv.rotate(img, cv.ROTATE_180)  # 顺时针旋转 180度
        imgRot270 = cv.rotate(img, cv.ROTATE_90_COUNTERCLOCKWISE)  # 顺时针旋转 270度
    
        plt.figure(figsize=(9, 6))
        plt.subplot(231), plt.title("1.Rotate around the origin"), plt.axis('off')
        plt.imshow(cv.cvtColor(imgRot1, cv.COLOR_BGR2RGB))
        plt.subplot(232), plt.title("2.Rotate around the center"), plt.axis('off')
        plt.imshow(cv.cvtColor(imgRot2, cv.COLOR_BGR2RGB))
        plt.subplot(233), plt.title("3.Rotate and resize"), plt.axis('off')
        plt.imshow(cv.cvtColor(imgRot3, cv.COLOR_BGR2RGB))
        plt.subplot(234), plt.title("4.Rotate 90 degrees"), plt.axis('off')
        plt.imshow(cv.cvtColor(imgRot90, cv.COLOR_BGR2RGB))
        plt.subplot(235), plt.title("5.Rotate 180 degrees"), plt.axis('off')
        plt.imshow(cv.cvtColor(imgRot180, cv.COLOR_BGR2RGB))
        plt.subplot(236), plt.title("6.Rotate 270 degrees"), plt.axis('off')
        plt.imshow(cv.cvtColor(imgRot270, cv.COLOR_BGR2RGB))
        plt.tight_layout()
        plt.show()
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    程序说明:
    运行结果,图像的旋转如图6-3所示。
    (1) 图6-3(1)~(3)用函数cv.getRotationMatrix2D计算旋转变换矩阵后,通过函数cv.warpAffine计算旋转变换图像。图6-3(1)以图像原点,即左上角为中心旋转,图6-3(2)和图6-3(3)围绕图像中心点旋转变换。
    (2) 图像尺寸不变,中心旋转后四角像素被切除(见图6-3(2))。在计算旋转变换矩阵时使用了缩放系数,使旋转图像保留了原始图像的内容(见图6-3(3))。
    (3) 图6-3(4)~(6)所示都是直角旋转,使用函数cv.rotate通过矩阵转置实现。


    在这里插入图片描述

    *图6-3 图像的旋转


    版权声明:
    youcans@xupt 原创作品,转载必须标注原文链接:(https://blog.csdn.net/youcans/article/details/134317103)
    Copyright 2023 youcans, XUPT
    Crated:2023-11-11

    欢迎关注本书CSDN独家连载专栏
    《数字图像处理-OpenCV/Python》连载: https://blog.csdn.net/youcans/category_12418787.html

  • 相关阅读:
    Jenkins教程-8-上下游关联自动化测试任务构建
    学生个人网页设计作品:旅游网页设计与实现——成都旅游网站4个页HTML+CSS web前端网页设计期末课程大作业 学生DW静态网页设计 学生个人网页设计作品
    Oracle第二篇:删除索引提示ORA-01408:索引不存在
    SMART 200 PLC S型速度曲线应用(梯形图算法优化)
    MySQL的SQL预编译及防SQL注入
    【一起来用C++】————(1)类的练习案例(多文件编写)
    rabbitmq安装部署和常用命令
    什么是hive的静态分区和动态分区,它们又有什么区别呢?hive动态分区详解
    python爬虫案例-爬取山东各城市近两年的天气情况(附带源码)
    直播回顾 | 论道原生:云原生大数据建设实践
  • 原文地址:https://blog.csdn.net/youcans/article/details/134317103