openCV仿射变换:getAffineTransform的案例

☞ ░ 老猿Python博文目录:https://blog.csdn.net/LaoYuanPython

仿射变换博文传送门(带星号的为付费专栏文章):
  1. *图像仿射变换原理1:齐次坐标来龙去脉详解
  2. *图像仿射变换原理2:矩阵变换、线性变换和图像线性变换矩阵
  3. *图像仿射变换原理3:仿射变换类型及变换矩阵详解
  4. *图像仿射变换原理4:组合变换及对应变换矩阵
  5. *图像仿射变换原理5:组合变换矩阵的OpenCV-Python实现
  6. OpenCV-Python图像处理:仿射变换详解及案例
  7. OpenCV-Python仿射变换开发中遇到的坑
  8. openCV仿射变换:getAffineTransform的案例
  9. 为什么称图像旋转、错切、缩放变换是线性变换?
  10. 图像仿射变换:绕点旋转和指定直线依赖轴shear错切变换矩阵
  11. 图像仿射变换shear怎么翻译?剪切、错切、推移哪个译词好?
  12. 仿射变换原理和其OpenCV-Python实现知识汇总
openCV仿射变换:getAffineTransform的案例

一、getAffineTransform函数

getAffineTransform通过确认源图像中不在同一直线的三个点对应的目标图像的位置,来获取对应仿射变换矩阵,从而用该仿射变换矩阵对图像进行统一的仿射变换。

调用语法

retval = cv.getAffineTransform(src, dst)

语法说明
  • src:源图像中三角形顶点的坐标,也就是在源图像中任找不在同一直线上的三个点,将三个点的坐标作为三个元素放到src对应列表中
  • dst:目标图像中相应三角形顶点的坐标,也就是三个点在变换后图像中的坐标列表,要求与源图像三个点一一对应
  • 返回值:从三对对应的点计算出来的仿射变换矩阵

二、案例:任选三个点放大选定区域

2.1、案例说明

本案例读入图像进行显示,然后通过在图像界面任选三个点圈定范围对应子图像,将子图像选定三个点分别对应图像左上角、左下角和右下角,然后通过三个点的坐标映射到结果图像的左上角、左下角和右下角三个点获取仿射变换矩阵,再进行变换,就将选定范围图像放大到整个图像窗口。

2.2、示例代码

import cv2
import numpy as np

def OnMouseEvent( event, x, y, flags, param):
    global lbtDownPos
    global pos
    global pointList
    img = param
    ignoreEvent = [cv2.EVENT_MBUTTONDOWN, cv2.EVENT_MBUTTONUP, cv2.EVENT_MBUTTONDBLCLK, cv2.EVENT_MOUSEWHEEL,
                        cv2.EVENT_MOUSEHWHEEL,cv2.EVENT_MOUSEMOVE,cv2.EVENT_LBUTTONDBLCLK, cv2.EVENT_RBUTTONDBLCLK, cv2.EVENT_RBUTTONDOWN, cv2.EVENT_RBUTTONUP]  # 需要忽略的鼠标事件
    needRecordEvent = [ cv2.EVENT_LBUTTONDOWN, cv2.EVENT_LBUTTONUP]  # 需要记录当前信息的鼠标事件

    if event == cv2.EVENT_LBUTTONUP:
        pos = (x,y)
        print("OnMouseEvent EVENT_LBUTTONUP:",pos)
        n = len(pointList)
        if pos==lbtDownPos:



            n += 1
            if n <= 3:
                pointList.append(pos)
                cv2.putText(img, '.', (x - 10, y), fontFace=cv2.FONT_HERSHEY_SIMPLEX, fontScale=3, color=(255, 0, 0))
                cv2.putText(img, f'select point{n}:({x},{y})', (x + 20, y), fontFace=cv2.FONT_HERSHEY_SIMPLEX, fontScale=0.3, color=(255, 0, 0))

        lbtDownPos = None

    elif event == cv2.EVENT_LBUTTONDOWN:
        lbtDownPos = (x,y)
        print("OnMouseEvent EVENT_LBUTTONDOWN:", lbtDownPos)

    else:lbtDownPos = None


def getPoint(imgfile):
    global pos
    global pointList

    pointList = []
    img = cv2.imread(imgfile)
    cv2.putText(img, 'https://blog.csdn.net/LaoYuanPython', (100, 120), fontFace=cv2.FONT_HERSHEY_SIMPLEX,fontScale=0.5, color=(255, 0, 0))
    imgbak = np.array(img)
    rows,cols = img.shape[:2]
    winName = 'select three point'
    cv2.namedWindow(winName)
    cv2.setMouseCallback(winName, OnMouseEvent, img)
    print("请将要单独放大的部分从其左上角、左下角、右下角分别鼠标左键点击选择三个点,选择后在图像上有提示信息,选择完成后按ESC退出")


    while True:#通过鼠标左键点击选择三个点,分别代表要映射到左上、左下和右下三个点
        cv2.imshow(winName, img)
        ch = cv2.waitKey(100)
        if ch == 27: break

    destPoint = [(0,0),(0,rows),(cols,rows)]
    if len(pointList)==3:
        pts1 = np.float32(pointList)
        pts2 = np.float32(destPoint)
        M = cv2.getAffineTransform(pts1, pts2)
        dst = cv2.warpAffine(imgbak, M, (cols, rows))
        cv2.imshow(winName, dst)
        ch = cv2.waitKey(0)
    else:
        print("没有选择足够的点")




getPoint(r'f:\pic\oldhouse.JPG')

2.3、运行效果

输入图像:

在这里插入图片描述

选择后图像:

在这里插入图片描述

选择的三个点对应三个红色标记圈的蓝色中心点,选择顺序要注意:左上、左下和右下三个点,选择后按ESC退出。

结果图像:

在这里插入图片描述

三、小结

本部分介绍了OpenCV-Python的getAffineTransform函数,并通过在图像上任选三个点指定为结果图像的左上角、左下角、右下角,从而实现原图像三个点圈定范围的子图像通过仿射变换实现整体放大。

后记

仿射变换涉及一些基础知识的理解如齐次坐标、变换矩阵,对于熟悉线性代数的人理解起来很容易,但对于未学过或者象老猿这种学过又还给老师的人来说则理解很困难,为此老猿花了40余天时间温习了部分线性代数知识,并查找各种资料,结合自己的理解写了如下仿射变换原理的博文:

  1. https://blog.csdn.net/LaoYuanPython/article/details/113743213 图像仿射变换原理1:齐次坐标来龙去脉详解
  2. https://blog.csdn.net/LaoYuanPython/article/details/113804210 图像仿射变换原理2:矩阵变换、线性变换和图像线性变换矩阵
  3. https://blog.csdn.net/LaoYuanPython/article/details/113788380 图像仿射变换原理3:仿射变换类型及变换矩阵详解
  4. https://blog.csdn.net/LaoYuanPython/article/details/113841635 图像仿射变换原理4:组合变换及对应变换矩阵
  5. https://blog.csdn.net/LaoYuanPython/article/details/113879385 图像仿射变换原理5:组合变换矩阵的OpenCV-Python实现

这些仿射变换原理方面的博文浓缩了仿射变换相关的基础知识,可以使得完全不了解仿射变换的人员理解仿射变换的基本原理和具体应用矩阵的构建,不过相关知识发布在了付费专栏,感兴趣的同仁可以订阅后阅读。

更多图像处理的介绍请参考专栏《OpenCV-Python图形图像处理 https://blog.csdn.net/laoyuanpython/category_9979286.html》和《https://blog.csdn.net/laoyuanpython/category_10581071.html OpenCV-Python初学者疑难问题集》相关文章。

更多图像处理的数学基础知识请参考专栏《人工智能数学基础 https://blog.csdn.net/laoyuanpython/category_10382948.html

写博不易,敬请支持:

如果阅读本文于您有所获,敬请点赞、评论、收藏,谢谢大家的支持!

参考资料

  1. [Python图像处理] 六.图像缩放、图像旋转、图像翻转与图像平移

关于老猿的付费专栏

  1. 付费专栏《https://blog.csdn.net/laoyuanpython/category_9607725.html 使用PyQt开发图形界面Python应用》专门介绍基于Python的PyQt图形界面开发基础教程,对应文章目录为《 https://blog.csdn.net/LaoYuanPython/article/details/107580932 使用PyQt开发图形界面Python应用专栏目录》;
  2. 付费专栏《https://blog.csdn.net/laoyuanpython/category_10232926.html moviepy音视频开发专栏 )详细介绍moviepy音视频剪辑合成处理的类相关方法及使用相关方法进行相关剪辑合成场景的处理,对应文章目录为《https://blog.csdn.net/LaoYuanPython/article/details/107574583 moviepy音视频开发专栏文章目录》;
  3. 付费专栏《https://blog.csdn.net/laoyuanpython/category_10581071.html OpenCV-Python初学者疑难问题集》为《https://blog.csdn.net/laoyuanpython/category_9979286.html OpenCV-Python图形图像处理 》的伴生专栏,是笔者对OpenCV-Python图形图像处理学习中遇到的一些问题个人感悟的整合,相关资料基本上都是老猿反复研究的成果,有助于OpenCV-Python初学者比较深入地理解OpenCV,对应文章目录为《https://blog.csdn.net/LaoYuanPython/article/details/109713407 OpenCV-Python初学者疑难问题集专栏目录
  4. 付费专栏《https://blog.csdn.net/laoyuanpython/category_10762553.html Python爬虫入门 》站在一个互联网前端开发小白的角度介绍爬虫开发应知应会内容,包括爬虫入门的基础知识,以及爬取CSDN文章信息、博主信息、给文章点赞、评论等实战内容。

前两个专栏都适合有一定Python基础但无相关知识的小白读者学习,第三个专栏请大家结合《https://blog.csdn.net/laoyuanpython/category_9979286.html OpenCV-Python图形图像处理 》的学习使用。

对于缺乏Python基础的同仁,可以通过老猿的免费专栏《https://blog.csdn.net/laoyuanpython/category_9831699.html 专栏:Python基础教程目录)从零开始学习Python。

如果有兴趣也愿意支持老猿的读者,欢迎购买付费专栏。

跟老猿学Python!

☞ ░ 前往老猿Python博文目录 https://blog.csdn.net/LaoYuanPython

猜你喜欢

转载自blog.csdn.net/LaoYuanPython/article/details/113924512