从opencv-python入门opencv--GUI功能之绘图鼠标与图像界面的交互

news2025/1/17 21:51:50

从opencv-python入门opencv--GUI功能之绘图和鼠标操作

  • 一、文章介绍
  • 二、opencv绘制直线、矩形、圆形
    • 1、cv.line()
    • 2、cv.circle()
    • 3、cv.rectangle()
    • 4、在图像上绘制直线、矩形和圆形
    • 5、cv.ellipse()(在空白画布上绘制椭圆)
      • (1)img = cv.ellipse( img, center, axes, angle, startAngle, endAngle, color[, thickness[, lineType[, shift]]] )
      • (2)img = cv.ellipse( img, box, color[, thickness[, lineType]]
    • 6、cv.putText()
  • 三、opencv鼠标回调功能
    • 1、基本用法
    • 3、注册回调函数
    • 4、鼠标事件类型
  • 四、案例:鼠标和键盘配合在图像中绘制图形。
    • 1、代码
    • 2、思路
  • 五、案例:鼠标点击显示图像当前位置的像素和坐标
    • 1、代码
    • 2、思路
  • 六、案例:删除上一次鼠标绘制及一次性清空所有鼠标绘制
    • 1、代码
    • 2、思路

一、文章介绍

1、本文主要介绍opencv的绘图功能以及鼠标与图像界面的交互功能。
2、包含直线、矩形、圆形的绘制。
3、opencv鼠标回调功能介绍。
4、案例:鼠标和键盘配合在图像中绘制图形。
效果展示:
在这里插入图片描述
5、案例:鼠标点击显示图像当前位置的像素和坐标。
效果展示:
在这里插入图片描述

6、案例:删除上一次鼠标绘制及一次性清空所有鼠标绘制。
效果展示:
在这里插入图片描述

二、opencv绘制直线、矩形、圆形

1、cv.line()

在这里插入图片描述
【1】img指要绘制的图形,可以是空白的图像,也可以是读取的图像
【2】pt1和pt2表示要绘制直线的两个端点的坐标,(横坐标,纵坐标)表示
【3】color表示颜色,(B,G,R),如果是灰度图,只需传一个标量值。
【4】thickness: 图形边界的厚度。如果传 -1 就是像圆这样的闭合图形,它将填充形状。 默认 thickness = 1
【5】lineType:线条类型,如 8 连接,抗锯齿线等。默认情况下,它是 8 连接。cv.LINE_AA 画出抗锯齿线,非常好看的曲线。
【6】shift表示坐标单位表示的像素的个数(2^shift),默认是0,坐标1表示1个像素,如果是1,表示1个坐标2两个像素,精度就是0.5。

2、cv.circle()

在这里插入图片描述

3、cv.rectangle()

在这里插入图片描述
pt1和pt2分别表示矩形的左上角和右下角

4、在图像上绘制直线、矩形和圆形

代码:


import cv2 as cv
img = cv.imread('data\gui\starry_night.jpg')
# 画一条 5px 宽的蓝色对角线
cv.line(img,(0,0),(200,300),(0,255,0),5)
cv.rectangle(img,(200,300),(300,500),(255,0,0),3)
cv.circle(img,(300,300), 50, (0,0,255), -1)
cv.imshow('img',img)
k=cv.waitKey(0)
if k == 27: # ESC 退出
    cv.destroyAllWindows()

效果:

5、cv.ellipse()(在空白画布上绘制椭圆)

在这里插入图片描述
在opencv-python中,有两种方式绘制椭圆

(1)img = cv.ellipse( img, center, axes, angle, startAngle, endAngle, color[, thickness[, lineType[, shift]]] )

center 是椭圆的中心点,axes 是长轴和短轴的长度,angle 是椭圆的旋转角度,startAngle 和 endAngle 定义了绘制的角度范围。startAngle和endAngle 为0和360时,绘制的才是完整的椭圆。
代码:

import cv2 as cv
import numpy as np

# 创建一个黑色图像
img = np.zeros((400, 400, 3), dtype=np.uint8)

# 定义椭圆的参数
center = (200, 200)  # 中心点
axes = (100, 50)     # 半轴长度 (长轴, 短轴)
angle = 30           # 旋转角度
startAngle = 0       # 起始角度
endAngle = 360       # 结束角度
color = (255, 0, 0)  # 颜色 (B, G, R)
thickness = 2        # 线条厚度

# 绘制椭圆
cv.ellipse(img, center, axes, angle, startAngle, endAngle, color, thickness)

# 显示图像
cv.imshow("Ellipse Example", img)
cv.waitKey(0)
cv.destroyAllWindows()

效果:
在这里插入图片描述
如果startAngle和endAngle 为0和90:
在这里插入图片描述
表明0度为横坐标方向,顺时针为角度增加。

(2)img = cv.ellipse( img, box, color[, thickness[, lineType]]

使用一个外接矩形的参数 box,box指的是旋转矩形,其中包含中心点的坐标、宽度和高度、旋转角度。
代码:

import cv2 as cv
import numpy as np

# 创建一个黑色图像
img = np.zeros((400, 400, 3), dtype=np.uint8)

# 定义 旋转矩阵RotatedRect 的参数
center = (200, 200)  # 中心点
size = (130, 80)     # (宽度, 高度)
angle = 30           # 旋转角度
# 创建 RotatedRect
rotated_rect = ((center[0], center[1]), (size[0], size[1]), angle)
color = (0, 255, 0)         # 颜色 (B, G, R)
thickness = 2               # 线条厚度

# 绘制椭圆
cv.ellipse(img, rotated_rect, color,thickness)

# 显示图像
cv.imshow("Ellipse Example", img)
cv.waitKey(0)
cv.destroyAllWindows()

效果:

6、cv.putText()

在这里插入图片描述
【1】img: 要在其上绘制文本的图像。
【2】text: 要绘制的文本字符串。
【3】org: 文本的左下角位置,格式为 (x, y)。
【4】fontFace: 字体类型,可以是以下常量之一:
cv.FONT_HERSHEY_SIMPLEX
cv.FONT_HERSHEY_PLAIN
cv.FONT_HERSHEY_DUPLEX
cv.FONT_HERSHEY_COMPLEX
cv.FONT_HERSHEY_TRIPLEX
cv.FONT_HERSHEY_COMPLEX_SMALL
cv.FONT_HERSHEY_SCRIPT_SIMPLEX
cv.FONT_HERSHEY_SCRIPT_COMPLEX
【5】fontScale: 字体大小的缩放因子。
【6】color: 文本颜色,格式为 (B, G, R)。
【7】thickness: 线条厚度(可选,默认为 1)。
【8】ineType: 线条类型(可选,默认为 LINE_8)。
【9】bottomLeftOrigin: 如果为 true,则文本的原点在左下角(可选,默认为 false)
代码:

import cv2 as cv
import numpy as np

# 创建一个黑色图像
img = np.zeros((400, 600, 3), dtype=np.uint8)

# 定义文本内容和属性
text = "Hello, OpenCV!"
org = (50, 200)  # 文本的左下角位置
fontFace = cv.FONT_HERSHEY_SIMPLEX
fontScale = 1
color = (255, 255, 255)  # 白色
thickness = 2

# 在图像上绘制文本
cv.putText(img, text, org, fontFace, fontScale, color, thickness)

# 显示图像
cv.imshow("Text Example", img)
cv.waitKey(0)
cv.destroyAllWindows()

效果:
在这里插入图片描述

三、opencv鼠标回调功能

OpenCV 的鼠标回调功能允许用户在图像窗口中处理鼠标事件,例如点击、移动、按下和释放鼠标键。这种功能在图形用户界面(GUI)开发和交互式应用程序中非常有用。

1、基本用法

(1)创建窗口:使用 cv2.namedWindow() 创建一个可用于接收鼠标事件的窗口。

(2)定义鼠标回调函数:创建一个回调函数,处理不同的鼠标事件。在这个函数中,可以获取鼠标的位置、按键状态等信息。

(3)注册回调函数:使用 cv2.setMouseCallback() 将定义的回调函数与窗口绑定。

(4)显示图像并等待事件:使用 cv2.imshow() 显示图像,然后使用 cv2.waitKey() 等待用户输入.

3、注册回调函数

在这里插入图片描述
其中,参数一是需要交互的窗口的名称,参数二是回调函数的名称,参数三是一个指向用户自定义数据的指针,可以用来在回调函数中传递额外的信息,可以将任何类型的数据传递给回调函数,以便在处理鼠标事件时使用,默认为 0(空指针),如果不需要传递额外数据,可以省略或传递 nullptr。

回调函数格式如下:
在这里插入图片描述
(1)event: 鼠标事件类型(如 EVENT_LBUTTONDOWN 表示左键按下)。
(2)x, y: 鼠标事件发生时的坐标。
(3)flags: 一些额外的标志(如 SHIFT、CTRL 键是否按下)。
(4)userdata: 传递给回调函数的用户数据。

4、鼠标事件类型

在 OpenCV 中,有多种鼠标事件可以使用,常用的包括:
cv2.EVENT_LBUTTONDOWN: 左键按下
cv2.EVENT_RBUTTONDOWN: 右键按下
cv2.EVENT_MOUSEMOVE: 鼠标移动
cv2.EVENT_LBUTTONUP: 左键释放
cv2.EVENT_RBUTTONUP: 右键释

四、案例:鼠标和键盘配合在图像中绘制图形。

1、代码


import numpy as np
import cv2 as cv
drawing = False # 如果 True 是鼠标按下
mode = True # 如果 True,画矩形,按下‘m’切换到画圆点
ix,iy = -1,-1
# 鼠标回调函数
def draw_circle(event,x,y,flags,param):
    global ix,iy,drawing,mode
    if event == cv.EVENT_LBUTTONDOWN:
        drawing = True
        ix,iy = x,y
    elif event == cv.EVENT_MOUSEMOVE:
        if drawing == True:
            if mode == True:
                cv.rectangle(img,(ix,iy),(x,y),(0,255,0),-1)
            else:
                cv.circle(img,(x,y),1,(0,0,255),-1)
    elif event == cv.EVENT_LBUTTONUP:
        drawing = False
        if mode == True:
            cv.rectangle(img,(ix,iy),(x,y),(0,255,0),-1)
        else:
            cv.circle(img,(x,y),10,(0,0,255),-1)


if __name__ == "__main__":
    img = np.zeros((512, 512, 3), np.uint8)
    cv.namedWindow('image')
    cv.setMouseCallback('image', draw_circle)
    while (1):
        cv.imshow('image', img)
        k = cv.waitKey(1) & 0xFF
        if k == ord('c'):
            mode = not mode
        elif k == 27:
            break

    cv.destroyAllWindows()


2、思路

代码中定义drawing变量判断鼠标是否按下。使用mode变量表示键盘’c’键是否按下。
按下鼠标左键,画一个绿色的点,移动鼠标绘制绿色的矩形。
按下‘c’键盘按键后,切换到画圆形。鼠标左键按下,绘制一个半径为5个像素点的圆形,鼠标滑动,连续绘制半径为1个像素点的圆形。

五、案例:鼠标点击显示图像当前位置的像素和坐标

1、代码



import numpy as np
import cv2 as cv
drawing = False # 如果 True 是鼠标按下
ix,iy = -1,-1
# 鼠标回调函数
def draw_circle(event,x,y,flags,param):
    global ix, iy, drawing
    if event == cv.EVENT_LBUTTONDOWN:
        drawing = True
        ix,iy = x,y
    elif event == cv.EVENT_LBUTTONUP:
        if drawing==True:
            cv.putText(img, f'Coordinates: ({x}, {y})', (x, y), cv.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
            cv.putText(img, f'value: ({img[y, x]})', (x, y + 25), cv.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
            cv.circle(img, (x, y), 2, (0, 0, 255), -1)
            drawing = False

if __name__ == "__main__":
    img = cv.imread('data\gui\starry_night.jpg')
    cv.namedWindow('image')
    cv.setMouseCallback('image', draw_circle)
    while (1):
        cv.imshow('image', img)
        k = cv.waitKey(1) & 0xFF
        if k == 27:
            break
    cv.destroyAllWindows()

2、思路

使用drawing标识是否绘制,鼠标左键按下时,表示需要绘制,鼠标左键松开时,绘制坐标点和像素点,然后将drawing置为False表示绘制完毕。

六、案例:删除上一次鼠标绘制及一次性清空所有鼠标绘制

1、代码

import cv2 as cv
import numpy as np

# 读取图像
img = cv.imread('data\gui\starry_night.jpg')
if img is None:
    print("Error: Could not read the image.")
    exit()

# 保存原始图像
original_img = img.copy()
drawing = False  # 标记是否正在绘制
history = []  # 用于存储历史图像状态

def mouse_callback(event, x, y, flags, param):
    global img, original_img, drawing, history

    if event == cv.EVENT_LBUTTONDOWN:  # 左键按下
        # 保存当前状态到历史记录
        history.append(img.copy())
        drawing = True


    elif event == cv.EVENT_LBUTTONUP:  # 左键抬起
        drawing = False
        cv.circle(img, (x, y), 20, (0, 255, 0), -1)  # 绘制绿色圆形

    elif event == cv.EVENT_RBUTTONDOWN:  # 右键按下
        img = original_img.copy()  # 清空图像,恢复为原始图像
        history.clear()  # 清空历史记录

# 创建窗口并设置鼠标回调
cv.namedWindow('image')
cv.setMouseCallback('image', mouse_callback)

while True:
    cv.imshow('image', img)

    key = cv.waitKey(1) & 0xFF
    if key == ord('q'):  # 按 'q' 键退出
        break
    elif key == ord('u'):  # 按 'u' 键撤销上一步
        if history:
            img = history.pop()  # 撤销上一步

cv.destroyAllWindows()

2、思路

将原始图像拷贝备份。每次绘制之前,将当前图片保存,如果按下’u’,则删除一张图像,如果右键按下,显示原始图像。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2214389.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux的Spark 环境部署

前言:需自行准备hadoop集群 1. Spark 是一款分布式内存计算引擎, 可以支撑海量数据的分布式计算。 Spark 在大数据体系是明星产品, 作为最新一代的综合计算引擎, 支持离线计算和实 时计算。 在大数据领域广泛应用, 是目前世界上使…

关于Java部署项目,文件上传路径问题 、Windows是\ linux是/

Windows是\ linux是/ ,踩坑。报错如下:

HyperWorks汽车B-柱网格变形

在这一节,将练习如何使用变形域,实现汽车 B-柱有限元模型的网格变形。 图 7-13 网格变形前后的 B 柱模型 Step01:读取并查看模型。 打开模型文件 Exercise_7c.hm。 Step02:创建变形域。 (1) 通过路径 HyperMorph > Morph…

SDV 峰会聚焦:下一代软件定义汽车的关键开源技术

10 月 17 - 18 日,由 GOSIM 开源创新汇主办、CSDN 承办的 GOSIM CHINA 2024 将在北京盛大启幕。作为 GOSIM 开源年度大会的第三届盛会,本次活动邀请了 60 多位国际开源专家,汇聚了来自全球百余家顶尖科技企业、知名高校及开源社区的技术大咖、…

量子计算机的原理与物理实现

量子计算机的原理与物理实现很复杂 指导性原则 首先思考制备一台量子计算机需要些什么? 需要量子比特——二能级量子系统。除了量子计算机需要满足一些物理特性,它还必须要把量子比特绘制到某种初态上,以及测量系统的输出态。 而实验上的挑战…

Vue检测获取最新资源 解决浏览器缓存问题

Vue检测获取最新资源 解决浏览器缓存问题 1、在public文件夹下创建version.json文件2、vue.config.js中,每次打包动态更新version.json内容3、App.vue中使用定时器去检测版本号和本地是否有差异 背景:由于浏览器缓存问题,vue2项目发布后&…

毕业设计选题:基于ssm+vue+uniapp的实习记录小程序

开发语言:Java框架:ssmuniappJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包:M…

数码准备记录

1.数据结构 常见的数据结构包括数组、链表、栈、队列、树(如二叉树、B树、B树)、图等 2.队列和栈的区别 队列是一种先入先出的数据结构,即最先加入的元素被最先移除; 栈是一种后进后出的数据结构,即最后加入的元素…

nbsaas vue3管理后台框架

nbsaas vue3管理后台框架 一、项目概述 Nbsaas Admin Vue 是一个基于 Vue.js 3.0 构建的轻量级后台管理系统,结合了现代前端技术栈的最佳实践,旨在帮助开发者快速构建具有高可扩展性和良好用户体验的后台管理系统。该项目拥有简洁的 UI 设计&#xff0…

计算机性能的指标

CPI——每条指令的时钟周期数(执行一条指令所需的时间周期)

基于SpringBoot+Vue+MySQL的社区医疗管理系统

系统展示 用户前台界面 管理员后台界面 系统背景 在当前医疗体系日益完善的背景下,社区医院作为基层医疗服务的重要一环,其管理效率和服务质量直接关系到居民的健康福祉。传统的社区医院管理模式存在效率低下、资源分配不均、患者就医体验差等问题。为了…

SpringBoot技术在人事管理中的应用:系统开发全解析

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统,它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等,非常适…

高德地图怎么定位自己的店铺位置?

在现代社会,像高德地图这样的导航软件已经成为我们日常生活中不可或缺的重要工具。无论是通勤出行,还是寻找周边商家,地图导航都发挥着关键作用。尤其是对于商家来说,地图导航的标注定位功能更是一个增加店铺曝光、获取客流量的有…

再给我两分钟,我能教会你使用 nvm 一键搞定node 和 npm

1. nvm简介 NVM(Node Version Manager)是Node.js的版本管理工具,它允许用户在同一台机器上安装和管理多个Node.js版本。这对于需要在不同项目之间切换Node.js版本的开发者来说非常有用,因为不同的项目可能依赖于不同版本的Node.js…

【Linux探索学习】第五弹——Linux用户管理:创建、删除与查看普通用户

前言: Linux下创建普通用户是我们以后经常要做的一件事,一个超级用户下可以有多个普通用户,这样我们就可以用这些普通用户去做不同的事情,所以学习如何创建并管理这些用户就显得尤为重要 提醒:本篇是在Ubuntu系统下进行…

brew install 无法从ghcr.io/v2/homebrew/core下载安装,兴奋解决

痛苦的经历 使用mac的同学都会经常使用brew 工具安装,我本来是需要安装一下ffmpeg来着,我就执行以下命令 brew install py3cairo ffmpeg> Downloading https://ghcr.io/v2/homebrew/core/openssl/3/blobs/sha256:32da4055066fca85ebd5057718d0ec5c80eb162f796 …

Java | Leetcode Java题解之第467题环绕字符串中唯一的子字符串

题目&#xff1a; 题解&#xff1a; class Solution {public int findSubstringInWraproundString(String p) {int[] dp new int[26];int k 0;for (int i 0; i < p.length(); i) {if (i > 0 && (p.charAt(i) - p.charAt(i - 1) 26) % 26 1) { // 字符之差为…

Java 多线程(一)—— 线程的创建与属性

线程的创建 方式一&#xff1a;继承 Thread 类&#xff0c;重写 run 方法 class MyThread extends Thread {Overridepublic void run() {System.out.println("hello Thread");} }方式二&#xff1a;实现 Runnnable 接口&#xff1a; class MyRunnable implements …

Spring Boot知识管理系统:敏捷开发实践

3系统分析 3.1可行性分析 通过对本知识管理系统实行的目的初步调查和分析&#xff0c;提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本知识管理系统采用JAVA作为开发语言&#xff0c;Spring Boot框…

通过OpenCV实现 Lucas-Kanade 算法

目录 简介 Lucas-Kanade 光流算法 实现步骤 1. 导入所需库 2. 视频捕捉与初始化 3. 设置特征点参数 4. 创建掩模 5. 光流估计循环 6. 释放资源 结论 简介 在计算机视觉领域&#xff0c;光流估计是一种追踪物体运动的技术。它通过比较连续帧之间的像素强度变化来估计图…