仿射变换---随机在大图上面截取小图
本代码python opencv运行,用鼠标在原图上面依次左击点三个点,左上,左下,右下。然后设定固定窗口大小,比如384128大小。
就是把在原图上面点击的三个点映射到384128大小图像上来。不管你原图选中多大面积的图像都会映射到我们设定的大小上面来。
这里就是仿射变换的原理映射。通过三对点映射关系求得仿射变换矩阵。然后通过矩阵来弄图像。
这里需要注意的是大图上面的点可以映射到截取的小图上面,同样的,小图上面的点也可以映射到大图上!
下面代码就是:
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_LBUTTONDOWN:
pos = (x,y)
print("---1 pos 》OnMouseEvent EVENT_LBUTTONDOWN:",pos)
n = len(pointList)
if True:
if len(pointList) <= 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))
def getPoint(imgfile):
global pos
global pointList
pointList = []
img = cv2.imread(imgfile)
cv2.putText(img, 'https://www.cnblogs.com/yanghailin/', (100, 120), fontFace=cv2.FONT_HERSHEY_SIMPLEX,fontScale=0.5, color=(255, 0, 0))
imgbak = np.array(img)
rows,cols = img.shape[:2]
rows = 128
cols = 384
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)
print("=========M===========")
print(M)
dst = cv2.warpAffine(imgbak, M, (cols, rows))
# b = np.array([cols/2,rows/2,1])
# b = np.array([rows / 2, cols / 2, 1])
b = np.array([1760 / 2 + 100, 540 / 2 + 40, 1])
a = np.matmul(M,b) #a = M * b img384 = M * img1760 --->大图映射到小图
cv2.circle(imgbak, (int(b[0]), int(b[1])), 8, (0, 255, 255), -1)
cv2.circle(dst, (int(a[0]), int(a[1])), 4, (0, 255, 255), -1)
# M_i = []
M_i = cv2.invertAffineTransform(M)
b = np.array([384 / 2 + 0, 128 / 2 + 0, 1])
a = np.matmul(M_i, b) # a = M * b img1760 = M * img384 --->小图映射到大图
cv2.circle(dst,(int(b[0]),int(b[1])),8,(255,0,0),-1)
cv2.circle(imgbak, (int(a[0]),int(a[1])), 12, (255, 0, 0), -1)
cv2.imshow(winName, dst)
cv2.imshow("src", imgbak)
ch = cv2.waitKey(0)
else:
print("没有选择足够的点")
getPoint("/data_1/1.jpeg")
鼠标左击分别点左上,左下,右下。然后按esc键。
下图可以看到我们在原图上面设定的点可以正确映射到小图,反之也是可以。都能对应上。
好记性不如烂键盘---点滴、积累、进步!