在OpenCV中使用鼠标移动缩放图片

实现目标

  在OpenCV中通过鼠标左键拖拽移动图片,通过鼠标滚轮前后旋转放大缩小图片。

实现背景

  在前一篇博客"在OpenCV中使用滚动条显示大图"中发现自己画滚动条移动大图略显繁琐,且缩放图片存在一定不足,故尝试利用鼠标拖拽来实现图片移动,同时完善使用鼠标滚轮缩放图片的程序。

实现方法

  利用OpenCV中的鼠标事件实现。当鼠标左键点击时保存初始坐标(x2, y2),按住鼠标左键并拖拽后记下拖拽坐标(x,y),二者相减得出相对移动坐标(move_w, move_h),最后以此计算窗口相对于大图的坐标(wx, wy),并根据窗口宽高显示截取的图片。
在这里插入图片描述

运行环境

  1. 在windows下已安装Python(必须的,我使用的是python3.7);
  2. 安装PyCharm(方便编程调试)
  3. 安装opencv-python(在python下安装配置OpenCV)

运行代码

import cv2


def mouse(event, x, y, flags, param):
    global flag, x1, y1, x2, y2, wx, wy, move_w, move_h, dst
    global zoom, zoom_w, zoom_h, img_zoom, flag_har, flag_var
    if event == cv2.EVENT_LBUTTONDOWN:  # 左键点击
        if flag == 0:
            flag = 1
            x1, y1, x2, y2 = x, y, wx, wy  # 使鼠标移动距离都是相对于初始点击位置,而不是相对于上一位置
    elif event == cv2.EVENT_MOUSEMOVE and (flags & cv2.EVENT_FLAG_LBUTTON):  # 按住左键拖曳
        if flag == 1:
            move_w, move_h = x1 - x, y1 - y  # 鼠标拖拽移动的宽高
            if flag_har and flag_var:  # 当窗口宽高大于图片宽高
                wx = x2 + move_w  # 窗口在大图的横坐标
                if wx < 0:  # 矫正位置
                    wx = 0
                elif wx + win_w > zoom_w:
                    wx = zoom_w - win_w
                wy = y2 + move_h  # 窗口在大图的总坐标
                if wy < 0:
                    wy = 0
                elif wy + win_h > zoom_h:
                    wy = zoom_h - win_h
                dst = img_zoom[wy:wy + win_h, wx: wx + win_w]  # 截取窗口显示区域
            elif flag_har and flag_var == 0:  # 当窗口宽度大于图片宽度
                wx = x2 + move_w
                if wx < 0:
                    wx = 0
                elif wx + win_w > zoom_w:
                    wx = zoom_w - win_w
                dst = img_zoom[0:zoom_h, wx: wx + win_w]
            elif flag_har == 0 and flag_var:  # 当窗口高度大于图片高度
                wy = y2 + move_h
                if wy < 0:
                    wy = 0
                elif wy + win_h > zoom_h:
                    wy = zoom_h - win_h
                dst = img_zoom[wy:wy + win_h, 0: zoom_w]
    elif event == cv2.EVENT_LBUTTONUP:  # 左键释放
        flag = 0
        x1, y1, x2, y2 = 0, 0, 0, 0
    elif event == cv2.EVENT_MOUSEWHEEL:  # 滚轮
        z = zoom
        if flags > 0:  # 滚轮上移
            zoom += wheel_step
            if zoom > 1 + wheel_step * 20:  # 缩放倍数调整
                zoom = 1 + wheel_step * 20
        else:  # 滚轮下移
            zoom -= wheel_step
            if zoom < wheel_step:  # 缩放倍数调整
                zoom = wheel_step
        zoom = round(zoom, 2)  # 取2位有效数字
        zoom_w, zoom_h = int(img_original_w * zoom), int(img_original_h * zoom)
        print(wx, wy)
        wx, wy = int((wx + x) * zoom / z - x), int((wy + y) * zoom / z - y)  # 缩放后鼠标在原图的坐标
        # print(z, zoom, x, y, wx, wy)
        if wx < 0:
            wx = 0
        elif wx + win_w > zoom_w:
            wx = zoom_w - win_w
        if wy < 0:
            wy = 0
        elif wy + win_h > zoom_h:
            wy = zoom_h - win_h
        img_zoom = cv2.resize(img_original, (zoom_w, zoom_h), interpolation=cv2.INTER_AREA)  # 图片缩放
        if zoom_w <= win_w and zoom_h <= win_h:  # 缩放后图片宽高小于窗口宽高
            flag_har, flag_var = 0, 0
            dst = img_zoom
            cv2.resizeWindow('img', zoom_w, zoom_h)
        elif zoom_w <= win_w and zoom_h > win_h:  # 缩放后图片宽度小于窗口宽度
            flag_har, flag_var = 0, 1
            dst = img_zoom[wy:wy + win_h, 0:zoom_w]
            cv2.resizeWindow('img', zoom_w, win_h)
        elif zoom_w > win_w and zoom_h <= win_h:  # 缩放后图片高度小于窗口高度
            flag_har, flag_var = 1, 0
            dst = img_zoom[0:zoom_h, wx:wx + win_w]
            cv2.resizeWindow('img', win_w, zoom_h)
        else:  # 缩放后图片宽高大于于窗口宽高
            flag_har, flag_var = 1, 1
            dst = img_zoom[wy:wy + win_h, wx:wx + win_w]
            cv2.resizeWindow('img', win_w, win_h)
    cv2.imshow("img", dst)
    cv2.waitKey(1)


img_original = cv2.imread("E:\\vs\\image\\2.png")  # 此处需换成大于img_w * img_h的图片
img_original_h, img_original_w = img_original.shape[0:2]  # 原图宽高
cv2.namedWindow('img', cv2.WINDOW_NORMAL)
cv2.moveWindow("img", 300, 100)
win_h, win_w = 600, 800  # 窗口宽高
wx, wy = 0, 0  # 窗口相对于原图的坐标
wheel_step, zoom = 0.05, 1  # 缩放系数, 缩放值
zoom_w, zoom_h = img_original_w, img_original_h  # 缩放图宽高
img_zoom = img_original.copy()  # 缩放图片
flag, flag_har, flag_var = 0, 0, 0  # 鼠标操作类型
move_w, move_h = 0, 0  # 鼠标移动坐标
x1, y1, x2, y2 = 0, 0, 0, 0  # 中间变量
cv2.resizeWindow("img", win_w, win_h)
dst = img_original[wy:wy + win_h, wx: wx + win_w]
cv2.setMouseCallback('img', mouse)
if img_original_w > win_w:
    flag_har = 1
if img_original_h > win_h:
    flag_var = 1
cv2.waitKey()
cv2.destroyAllWindows()



运行结果

  1. 原图
    在这里插入图片描述

  2. 水平移动图片(鼠标左键点击并向左拖拽):
    在这里插入图片描述

  3. 垂直移动图片(鼠标左键点击,向上拖拽):
    在这里插入图片描述

  4. 鼠标滚轮后转缩小图片
    在这里插入图片描述

  5. 鼠标滚轮前转放大图片
    在这里插入图片描述

上一篇: 在OpenCV中使用滚动条显示大图


学有余钱,支持一下!

猜你喜欢

转载自blog.csdn.net/qq_34801642/article/details/86598287