一、实现目标

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

二、实现背景

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

三、实现方法

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

四、运行环境

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

五、运行代码

import cv2def mouse(event, x, y, flags, param):global flag, x1, y1, x2, y2, wx, wy, move_w, move_h, dstglobal zoom, zoom_w, zoom_h, img_zoom, flag_har, flag_varif event == cv2.EVENT_LBUTTONDOWN:  # 左键点击if flag == 0:flag = 1x1, 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 = 0elif wx + win_w > zoom_w:wx = zoom_w - win_wwy = y2 + move_h  # 窗口在大图的总坐标if wy < 0:wy = 0elif wy + win_h > zoom_h:wy = zoom_h - win_hdst = img_zoom[wy:wy + win_h, wx:wx + win_w]  # 截取窗口显示区域elif flag_har and flag_var == 0:  # 当窗口宽度大于图片宽度wx = x2 + move_wif wx < 0:wx = 0elif wx + win_w > zoom_w:wx = zoom_w - win_wdst = img_zoom[0:zoom_h, wx:wx + win_w]elif flag_har == 0 and flag_var:  # 当窗口高度大于图片高度wy = y2 + move_hif wy < 0:wy = 0elif wy + win_h > zoom_h:wy = zoom_h - win_hdst = img_zoom[wy:wy + win_h, 0:zoom_w]elif event == cv2.EVENT_LBUTTONUP:  # 左键释放flag = 0x1, y1, x2, y2 = 0, 0, 0, 0elif event == cv2.EVENT_MOUSEWHEEL:  # 滚轮z = zoomif flags > 0:  # 滚轮上移zoom += wheel_stepif zoom > 1 + wheel_step * 20:  # 缩放倍数调整zoom = 1 + wheel_step * 20else:  # 滚轮下移zoom -= wheel_stepif zoom < wheel_step:  # 缩放倍数调整zoom = wheel_stepzoom = 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 = 0elif wx + win_w > zoom_w:wx = zoom_w - win_wif wy < 0:wy = 0elif wy + win_h > zoom_h:wy = zoom_h - win_himg_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, 0dst = img_zoomcv2.resizeWindow('img', zoom_w, zoom_h)elif zoom_w <= win_w and zoom_h > win_h:  # 缩放后图片宽度小于窗口宽度flag_har, flag_var = 0, 1dst = 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, 0dst = img_zoom[0:zoom_h, wx:wx + win_w]cv2.resizeWindow('img', win_w, zoom_h)else:  # 缩放后图片宽高大于于窗口宽高flag_har, flag_var = 1, 1dst = img_zoom[wy:wy + win_h, wx:wx + win_w]cv2.resizeWindow('img', win_w, win_h)cv2.imshow("img", dst)cv2.waitKey(1)win_h, win_w = 600, 800  # 窗口宽高
wx, wy = 0, 0  # 窗口相对于原图的坐标
wheel_step, zoom = 0.05, 1  # 缩放系数, 缩放值
img_original = cv2.imread("E:/VSCode/git/my_program/ImageMoveZoom/1.jpg")  # 建议图片大于win_w*win_h(800*600)
img_original_h, img_original_w = img_original.shape[0:2]  # 原图宽高
cv2.namedWindow('img', cv2.WINDOW_NORMAL)
cv2.moveWindow("img", 300, 100)
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()

2020.06.02版本:缩减全局变量个数,将关联较少的功能(如矫正坐标,计算缩放倍数)单独定义成函数,精炼鼠标事件函数。

import cv2# 全局变量
g_window_name = "img"  # 窗口名
g_window_wh = [800, 600]  # 窗口宽高g_location_win = [0, 0]  # 相对于大图,窗口在图片中的位置
location_win = [0, 0]  # 鼠标左键点击时,暂存g_location_win
g_location_click, g_location_release = [0, 0], [0, 0]  # 相对于窗口,鼠标左键点击和释放的位置g_zoom, g_step = 1, 0.1  # 图片缩放比例和缩放系数
g_image_original = cv2.imread("E:/VSCode/git/my_program/ImageMoveZoom/1.jpg")  # 原始图片,建议大于窗口宽高(800*600)
g_image_zoom = g_image_original.copy()  # 缩放后的图片
g_image_show = g_image_original[g_location_win[1]:g_location_win[1] + g_window_wh[1], g_location_win[0]:g_location_win[0] + g_window_wh[0]]  # 实际显示的图片# 矫正窗口在图片中的位置
# img_wh:图片的宽高, win_wh:窗口的宽高, win_xy:窗口在图片的位置
def check_location(img_wh, win_wh, win_xy):for i in range(2):if win_xy[i] < 0:win_xy[i] = 0elif win_xy[i] + win_wh[i] > img_wh[i] and img_wh[i] > win_wh[i]:win_xy[i] = img_wh[i] - win_wh[i]elif win_xy[i] + win_wh[i] > img_wh[i] and img_wh[i] < win_wh[i]:win_xy[i] = 0# print(img_wh, win_wh, win_xy)# 计算缩放倍数
# flag:鼠标滚轮上移或下移的标识, step:缩放系数,滚轮每步缩放0.1, zoom:缩放倍数
def count_zoom(flag, step, zoom):if flag > 0:  # 滚轮上移zoom += stepif zoom > 1 + step * 20:  # 最多只能放大到3倍zoom = 1 + step * 20else:  # 滚轮下移zoom -= stepif zoom < step:  # 最多只能缩小到0.1倍zoom = stepzoom = round(zoom, 2)  # 取2位有效数字return zoom# OpenCV鼠标事件
def mouse(event, x, y, flags, param):global g_location_click, g_location_release, g_image_show, g_image_zoom, g_location_win, location_win, g_zoomif event == cv2.EVENT_LBUTTONDOWN:  # 左键点击g_location_click = [x, y]  # 左键点击时,鼠标相对于窗口的坐标location_win = [g_location_win[0], g_location_win[1]]  # 窗口相对于图片的坐标,不能写成location_win = g_location_winelif event == cv2.EVENT_MOUSEMOVE and (flags & cv2.EVENT_FLAG_LBUTTON):  # 按住左键拖曳g_location_release = [x, y]  # 左键拖曳时,鼠标相对于窗口的坐标h1, w1 = g_image_zoom.shape[0:2]  # 缩放图片的宽高w2, h2 = g_window_wh  # 窗口的宽高show_wh = [0, 0]  # 实际显示图片的宽高if w1 < w2 and h1 < h2:  # 图片的宽高小于窗口宽高,无法移动show_wh = [w1, h1]g_location_win = [0, 0]elif w1 >= w2 and h1 < h2:  # 图片的宽度大于窗口的宽度,可左右移动show_wh = [w2, h1]g_location_win[0] = location_win[0] + g_location_click[0] - g_location_release[0]elif w1 < w2 and h1 >= h2:  # 图片的高度大于窗口的高度,可上下移动show_wh = [w1, h2]g_location_win[1] = location_win[1] + g_location_click[1] - g_location_release[1]else:  # 图片的宽高大于窗口宽高,可左右上下移动show_wh = [w2, h2]g_location_win[0] = location_win[0] + g_location_click[0] - g_location_release[0]g_location_win[1] = location_win[1] + g_location_click[1] - g_location_release[1]check_location([w1, h1], [w2, h2], g_location_win)  # 矫正窗口在图片中的位置g_image_show = g_image_zoom[g_location_win[1]:g_location_win[1] + show_wh[1], g_location_win[0]:g_location_win[0] + show_wh[0]]  # 实际显示的图片elif event == cv2.EVENT_MOUSEWHEEL:  # 滚轮z = g_zoom  # 缩放前的缩放倍数,用于计算缩放后窗口在图片中的位置g_zoom = count_zoom(flags, g_step, g_zoom)  # 计算缩放倍数w1, h1 = [int(g_image_original.shape[1] * g_zoom), int(g_image_original.shape[0] * g_zoom)]  # 缩放图片的宽高w2, h2 = g_window_wh  # 窗口的宽高g_image_zoom = cv2.resize(g_image_original, (w1, h1), interpolation=cv2.INTER_AREA)  # 图片缩放show_wh = [0, 0]  # 实际显示图片的宽高if w1 < w2 and h1 < h2:  # 缩放后,图片宽高小于窗口宽高show_wh = [w1, h1]cv2.resizeWindow(g_window_name, w1, h1)elif w1 >= w2 and h1 < h2:  # 缩放后,图片高度小于窗口高度show_wh = [w2, h1]cv2.resizeWindow(g_window_name, w2, h1)elif w1 < w2 and h1 >= h2:  # 缩放后,图片宽度小于窗口宽度show_wh = [w1, h2]cv2.resizeWindow(g_window_name, w1, h2)else:  # 缩放后,图片宽高大于窗口宽高show_wh = [w2, h2]cv2.resizeWindow(g_window_name, w2, h2)g_location_win = [int((g_location_win[0] + x) * g_zoom / z - x), int((g_location_win[1] + y) * g_zoom / z - y)]  # 缩放后,窗口在图片的位置check_location([w1, h1], [w2, h2], g_location_win)  # 矫正窗口在图片中的位置# print(g_location_win, show_wh)g_image_show = g_image_zoom[g_location_win[1]:g_location_win[1] + show_wh[1], g_location_win[0]:g_location_win[0] + show_wh[0]]  # 实际的显示图片cv2.imshow(g_window_name, g_image_show)# 主函数
if __name__ == "__main__":# 设置窗口cv2.namedWindow(g_window_name, cv2.WINDOW_NORMAL)# 设置窗口大小,只有当图片大于窗口时才能移动图片cv2.resizeWindow(g_window_name, g_window_wh[0], g_window_wh[1])cv2.moveWindow(g_window_name, 700, 100)  # 设置窗口在电脑屏幕中的位置# 鼠标事件的回调函数cv2.setMouseCallback(g_window_name, mouse)cv2.waitKey()  # 不可缺少,用于刷新图片,等待鼠标操作cv2.destroyAllWindows()

六、运行结果

原图:

水平移动图片(鼠标左键点击并向左拖拽):

垂直移动图片(鼠标左键点击,向上拖拽):

鼠标滚轮后转缩小图片:

鼠标滚轮前转放大图片:

七、参考资料

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

Python OpenCV:利用鼠标移动缩放图片相关推荐

  1. Python OpenCV实现鼠标画框

    Python OpenCV实现鼠标画框 使用Python+OpenCV实现鼠标画框的代码: # -*-coding: utf-8 -*- """@Project: Int ...

  2. 鼠标滚动缩放图片效果

    前段时间本人在做项目时,做了一个鼠标滚动缩放图片效果,图片支持多个,多个图片循环缩放,花了点时间整理了下,把它贴出来,与大家分享下,在ie6.0,ie7.0,firefox都测试过,没有问题. < ...

  3. 【Axure视频教程】鼠标滚动缩放图片

    今天教大家制作鼠标滚动缩小放大图片的原型模板,包括向下滚动放大.向上滚动缩小.拖动图片移动到指定位置的效果.该教程从材料准备到完成交互,手把手的教学. [视频教程--试看版] [Axure视频教程]鼠 ...

  4. Python + opencv对拍照得到的图片进行背景去除的实现方法

    这篇文章主要介绍了Python + opencv对拍照得到的图片进行背景去除的实现方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下 有时候我们 ...

  5. Python爬虫——利用Scrapy批量下载图片

    Python爬虫--利用Scrapy批量下载图片 Scrapy下载图片项目介绍 使用Scrapy下载图片 项目创建 项目预览 创建爬虫文件 项目组件介绍 Scrapy爬虫流程介绍 页面结构分析 定义I ...

  6. python图片识别-Python+Opencv识别两张相似图片

    在网上看到python做图像识别的相关文章后,真心感觉python的功能实在太强大,因此将这些文章总结一下,建立一下自己的知识体系. 当然了,图像识别这个话题作为计算机科学的一个分支,不可能就在本文简 ...

  7. Python+Opencv识别两张相似图片

    在网上看到python做图像识别的相关文章后,真心感觉python的功能实在太强大,因此将这些文章总结一下,建立一下自己的知识体系. 当然了,图像识别这个话题作为计算机科学的一个分支,不可能就在本文简 ...

  8. php 比对两张图片,Python+Opencv识别两张相似图片

    在网上看到python做图像识别的相关文章后,真心感觉python的功能实在太强大,因此将这些文章总结一下,建立一下自己的知识体系. 当然了,图像识别这个话题作为计算机科学的一个分支,不可能就在本文简 ...

  9. OpenCV利用鼠标操作测量角度

    前言 本文介绍一种在OpenCV中定义鼠标事件来进行对两条直线之间夹角的计算以及输出. 一.本文内容 利用OpenCV设置鼠标操作来进行测量角度,基本思路是通过定义鼠标事件得到三角形的三个点的坐标位置 ...

最新文章

  1. 用PS制作APP的界面图片
  2. 前端开发中好用的 chrome 插件
  3. 中国民航局:2019年春运中国民航旅客运输量将创历史新高
  4. java商城pom,使用maven创建Java购物商城系统的common工程
  5. 雅虎成立特别委员会评估新战略选项
  6. [转]海量查询的数据优化
  7. leetcode算法题--数组中重复的数字
  8. 100_框架对象事件
  9. 安裝 CentOS 7 後必做的七件事
  10. Android 8.0 AutoFill自动填写框架实践
  11. Exchange Server 2016 独立部署/共存部署 (六)—— 创建数据库副本
  12. String.Format用法
  13. H5页面--Android滑动屏幕图片误触
  14. 不再支持Postman集合v1格式,无法直接导入
  15. [LeetCode][easy]Roman to Integer
  16. Vuejs vm对象详解
  17. 红米开发版刷机教程_红米K20开发版刷机包(官方系统最新完整固件升级包V20.1.9MIUI开发版)...
  18. 很详细的讲解什么以及为什么是卷积(Convolution)!
  19. JS逆向解析案例-巨潮证券市场数据库(python)
  20. html单页模板wap,单页模板html

热门文章

  1. 【Golang 面试算法二叉树 手动建树】
  2. 服务器安全狗远程桌面无法连接,服务器安全狗服务器安全策略设置教程详解
  3. 动态规划:和组成的问题
  4. 实例解析:融合深度链接和携带参数安装,实现App高效推广运营
  5. 鸟笼山剿匪记--观后感之灭蟑螂
  6. 从算筹算盘到计算机教案,三年级数学下册 从算筹、算盘到计算器教案 沪教版...
  7. 变压器油温预测文本数据集(12w多条数据,时间间隔15min)
  8. shell实现毫秒级时钟
  9. Python 微信机器人
  10. 信号处理之一阶RC低通滤波器宏指令实现(繁易触摸屏)