getAffineTransform通过确认源图像中不在同一直线的三个点对应的目标图像的位置,来获取对应仿射变换矩阵,从而用该仿射变换矩阵对图像进行统一的仿射变换。
retval = cv.getAffineTransform(src, dst)
本案例读入图像进行显示,然后通过在图像界面任选三个点圈定范围对应子图像,将子图像选定三个点分别对应图像左上角、左下角和右下角,然后通过三个点的坐标映射到结果图像的左上角、左下角和右下角三个点获取仿射变换矩阵,再进行变换,就将选定范围图像放大到整个图像窗口。
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')
选择的三个点对应三个红色标记圈的蓝色中心点,选择顺序要注意:左上、左下和右下三个点,选择后按ESC退出。
本部分介绍了OpenCV-Python的getAffineTransform函数,并通过在图像上任选三个点指定为结果图像的左上角、左下角、右下角,从而实现原图像三个点圈定范围的子图像通过仿射变换实现整体放大。
仿射变换涉及一些基础知识的理解如齐次坐标、变换矩阵,对于熟悉线性代数的人理解起来很容易,但对于未学过或者象老猿这种学过又还给老师的人来说则理解很困难,为此老猿花了40余天时间温习了部分线性代数知识,并查找各种资料,结合自己的理解写了如下仿射变换原理的博文:
这些仿射变换原理方面的博文浓缩了仿射变换相关的基础知识,可以使得完全不了解仿射变换的人员理解仿射变换的基本原理和具体应用矩阵的构建,不过相关知识发布在了付费专栏,感兴趣的同仁可以订阅后阅读。
更多图像处理的介绍请参考专栏《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》
如果阅读本文于您有所获,敬请点赞、评论、收藏,谢谢大家的支持!
参考资料:
前两个专栏都适合有一定Python基础但无相关知识的小白读者学习,第三个专栏请大家结合《https://blog.csdn.net/laoyuanpython/category_9979286.html OpenCV-Python图形图像处理 》的学习使用。
对于缺乏Python基础的同仁,可以通过老猿的免费专栏《https://blog.csdn.net/laoyuanpython/category_9831699.html 专栏:Python基础教程目录)从零开始学习Python。
如果有兴趣也愿意支持老猿的读者,欢迎购买付费专栏。