仿射变换---随机在大图上面截取小图

本代码python opencv运行,用鼠标在原图上面依次左击点三个点,左上,左下,右下。然后设定固定窗口大小,比如384128大小。
就是把在原图上面点击的三个点映射到384
128大小图像上来。不管你原图选中多大面积的图像都会映射到我们设定的大小上面来。
这里就是仿射变换的原理映射。通过三对点映射关系求得仿射变换矩阵。然后通过矩阵来弄图像。
这里需要注意的是大图上面的点可以映射到截取的小图上面,同样的,小图上面的点也可以映射到大图上!
下面代码就是:

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键。

下图可以看到我们在原图上面设定的点可以正确映射到小图,反之也是可以。都能对应上。

posted @ 2022-05-01 17:35  无左无右  阅读(115)  评论(0编辑  收藏  举报