OpenCV的“画笔”功能

news2024/11/26 12:17:16

类似于画图软件的自由笔刷功能,当按住鼠标左键,在屏幕上画出连续的线条。

定义函数:

import cv2
import numpy as np

# 初始化参数
drawing = False  # 鼠标左键按下时为True
ix, iy = -1, -1  # 鼠标初始位置


# 鼠标回调函数
def mouse_paint(event, x, y, flags, param):
    global ix, iy, drawing

    # 左键按下事件
    if event == cv2.EVENT_LBUTTONDOWN:
        drawing = True
        ix, iy = x, y

    # 鼠标移动事件
    elif event == cv2.EVENT_MOUSEMOVE:
        if drawing:
            cv2.line(img, (ix, iy), (x, y), (0, 255, 0), 2)
            ix, iy = x, y
            cv2.imshow('image', img)
    # 左键松开事件
    elif event == cv2.EVENT_LBUTTONUP:
        drawing = False
        # cv2.line(img, (ix, iy), (x, y), (0, 255, 0), 2)

        # cv2.imshow('image', img)
        cv2.waitKey(0)


# 创建空白图像或读取现有图像
img = np.zeros((500, 500, 3), np.uint8)    # 创建空白图像
# img = cv2.imread('d:\\mask1\\3.png', cv2.IMREAD_COLOR)   # 读取现有图像

# 创建一个窗口并将回调函数与窗口绑定
cv2.namedWindow('image')
cv2.setMouseCallback('image', mouse_paint)

# 保存绘制轨迹后的图像
cv2.imshow('image', img)
cv2.waitKey(0)
cv2.imwrite('output_image.jpg', img)
cv2.destroyAllWindows()

 这里用到了OpenCV的鼠标回调函数cv2.setMouseCallback():

cv2.setMouseCallback() 是 OpenCV 库中用于设置鼠标事件回调函数的函数。该函数用于与图像窗口交互,通过在图像窗口中进行鼠标操作来获取像素点的坐标或执行一些特定操作。

函数原型为:

cv2.setMouseCallback(windowName, onMouse, param=None)
  • windowName 是要操作的图像窗口的名称。
  • onMouse 是回调函数,用于处理鼠标事件。该函数通常包含四个参数: event(事件类型,如 cv2.EVENT_MOUSEMOVEcv2.EVENT_LBUTTONDOWN 等)、x(鼠标点击的 x 坐标)、y(鼠标点击的 y 坐标)、flags(附加参数,如 cv2.EVENT_FLAG_CTRLKEYcv2.EVENT_FLAG_SHIFTKEY 等)。
  • param 是传递给回调函数的可选参数。

 封装为类:

import cv2
import numpy as np


class Painter:
    def __init__(self):
        self.drawing = False
        self.ix, self.iy = -1, -1
        self.img = np.zeros((500, 500, 3), np.uint8)

    def mouse_paint(self, event, x, y, flags, param):
        if event == cv2.EVENT_LBUTTONDOWN:
            self.drawing = True
            self.ix, self.iy = x, y
        elif event == cv2.EVENT_MOUSEMOVE:
            if self.drawing:
                cv2.line(self.img, (self.ix, self.iy), (x, y), (0, 255, 0), 1)
                self.ix, self.iy = x, y
                cv2.imshow('image', self.img)
        elif event == cv2.EVENT_LBUTTONUP:
            self.drawing = False
            cv2.waitKey(0)

    def run(self):

        cv2.setMouseCallback('image', self.mouse_paint)
        cv2.imshow('image', self.img)
        cv2.waitKey(0)
        cv2.imwrite('output_image.jpg', self.img)
        cv2.destroyAllWindows()


if __name__ == "__main__":
    cv2.namedWindow('image')
    painter = Painter()
    painter.run()

使用PySide6和OpenCV实现:

 目前阶段我的PySide6熟悉程度要强于OpenCV

import sys
from PySide6.QtWidgets import QApplication, QLabel, QVBoxLayout, QWidget, QPushButton
from PySide6.QtGui import QPainter, QPixmap, QMouseEvent, QColor, QPen, QImage
from PySide6.QtCore import Qt, QPoint
import cv2
import numpy as np


class PaintLabel(QLabel):
    def __init__(self, parent=None):
        super(PaintLabel, self).__init__(parent)
        self.image = QImage()
        self.drawing = False
        self.last_point = QPoint()

    def set_image(self, image_file):
        self.image = QImage(image_file)
        self.setPixmap(QPixmap.fromImage(self.image))

    def mousePressEvent(self, event: QMouseEvent):
        if event.button() == Qt.LeftButton:
            self.drawing = True
            self.last_point = event.position()

    def mouseMoveEvent(self, event: QMouseEvent):
        if event.buttons() & Qt.LeftButton and self.drawing:
            painter = QPainter(self.image)
            pen = QPen(QColor('red'))
            pen.setWidth(3)
            painter.setPen(pen)
            painter.drawLine(self.last_point, event.position())
            self.last_point = event.position()
            self.setPixmap(QPixmap.fromImage(self.image))

    def mouseReleaseEvent(self, event: QMouseEvent):
        if event.button() == Qt.LeftButton:
            self.drawing = False

    def save_image(self, file_path):
        self.image.save(file_path)


class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.label = PaintLabel()

        # Load an image (you can change the file path)
        img = np.zeros((500, 500, 3), np.uint8)  # 创建空白图像
        q_img = cv2side(img)


        self.label.set_image(q_img)

        save_button = QPushButton('Save Image')
        save_button.clicked.connect(self.save_image)

        layout = QVBoxLayout()
        layout.addWidget(self.label)
        layout.addWidget(save_button)
        self.setLayout(layout)

    def save_image(self):
        self.label.save_image('output_image.png')


# 将OpenCV格式的图像转换为PySide格式
def cv2side(img):
    img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)  # 转换 BGR 到 RGB

    # 转换图像到QT的QImage格式
    height, width, channels = img_rgb.shape  # 获取形状
    bytes_per_line = channels * width  # 每行字节数
    q_img = QImage(img_rgb.data, width, height, bytes_per_line, QImage.Format_RGB888)  # 转换成QImage格
    return q_img


if __name__ == "__main__":
    app = QApplication(sys.argv)
    main_window = MainWindow()
    main_window.show()
    sys.exit(app.exec())

运行截图:

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

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

相关文章

秀肌肉-海外短剧系统的案例展示

多语种可以选择,分销功能,多种海外支付方式,多种登录模式可供选择,总之你想到的我们都做了,你没想到的我们也都做了

Activity->Activity中动态添加Fragment->Fragment回退栈BackStack

Fragment回退栈 Fragment回退栈用于管理Fragment的导航历史(添加、删除、替换)。每个Activity都有一个包含其所有Fragment的FragmentManager,调用其addToBackStack方法时,这个事务就会被添加到FragmentManager的回退栈中当用户按下返回键时,…

kotlin 调用java的get方法Use of getter method instead of property access syntax

调用警告 Person.class public class Person {private String name;Person(String name) {this.name name.trim();}public String getName() {return name;}public void setName(String name) {this.name name;}public String getFullName() {return name " Wang&quo…

ChatTTS+Python编程搞定语音报时小程序

文字转语音神器Python编程搞定语音报时小程序 今天一个好哥们发了一个文字转语音的AI神器的短视频。这个神器的网站是[ChatTTS - Text-to-Speech for Conversational Scenarios][https://chattts.com/],如下图所示: 这个开源项目可以从github.com上下载…

VisualStudio2022离线包安装后无法进行版本升级(Visual Studio installer 卡在正在下载进度条0%)

目录 一、问题现象二、问题分析三、解决办法恢复正常 一、问题现象 表现1(未安装时,安装) 表现2(已安装,升级) 二、问题分析 原因:无法访问 aka.ms 测试方法:在浏览器中输入: https://aka.ms/vs/16/rele…

[笔试训练](三十四)100:[NOIP2008]ISBN号码101:kotori和迷宫102:矩阵最长递增路径

目录 100:[NOIP2008]ISBN号码 101:kotori和迷宫 102:矩阵最长递增路径 100:[NOIP2008]ISBN号码 题目链接:[NOIP2008]ISBN号码_牛客题霸_牛客网 (nowcoder.com) 题目&#xff1a; 题解: 简单模拟 #include <iostream> #include<string> using namespace std; str…

文件上传题目练习

[HNCTF 2022 Week1]easy_upload 先尝试上传一个php文件&#xff0c;发现直接就成功了 用蚁剑测试连接成功 找到flag [NISACTF 2022]bingdundun~ 白名单上传 这里因为尝试了很多绕过方式都不成功&#xff0c;去搜索了一下wp&#xff0c;发现要用到Phar://伪协议 补充&#xff…

【多模态】36、ShareGPT4V | 借助 GPT4V 的能够来生成更丰富的 caption 用于提升 LMM 模型的能力

文章目录 一、背景二、方法2.1 ShareGPT4V 数据集构建2.2 ShareGPT4V-PT 数据生成2.3 ShareGPT4V-7B Model 三、效果3.1 benchmark3.2 定量分析3.3 多模态对话 四、一些例子 论文&#xff1a;ShareGPT4V: Improving Large Multi-Modal Models with Better Captions 代码&#…

Python logging 模块详解

Python 的 logging 模块提供了一个强大而灵活的日志系统。它是 Python 标准库的一部分&#xff0c;因此可以在任何 Python 程序中使用。logging 模块提供了许多有用的功能&#xff0c;包括日志消息的级别设置、日志消息的格式设置、将日志消息输出到不同的目标&#xff0c;以及…

【机器学习】GLM4-9B-Chat大模型/GLM-4V-9B多模态大模型概述、原理及推理实战

​​​​​​​ 目录 一、引言 二、模型简介 2.1 GLM4-9B 模型概述 2.2 GLM4-9B 模型架构 三、模型推理 3.1 GLM4-9B-Chat 语言模型 3.1.1 model.generate 3.1.2 model.chat 3.2 GLM-4V-9B 多模态模型 3.2.1 多模态模型概述 3.2.2 多模态模型实践 四、总结 一、引言…

《精通ChatGPT:从入门到大师的Prompt指南》大纲目录

第一部分&#xff1a;入门指南 第1章&#xff1a;认识ChatGPT 1.1 ChatGPT是什么 1.2 ChatGPT的应用领域 1.3 为什么需要了解Prompt 第2章&#xff1a;Prompt的基本概念 2.1 什么是Prompt 2.2 好Prompt的特征 2.3 常见的Prompt类型 第二部分&#xff1a;Prompt设计技巧 第…

SOA的发展历史

1.SOA的发展历程 回顾SOA发展历程&#xff0c;我们把其大致分为了三个阶段&#xff0c;下面将分别介绍每个阶段的重要标准和规范。 1.1.萌芽阶段 这一阶段以XML技术为标志&#xff0c;时间大致从20世纪90年代末到21世纪初。XML系W3C所建&#xff0c;源自流行的标准通用标记语…

多表连接查询和子查询

一、连接查询 连接查询是SQL语言最强大的功能之一&#xff0c;它可以执行查询时动态的将表连接起来&#xff0c;然后从中查询数据。 1.1、连接两表的方法 在SQL中连接两表可以有两种方法&#xff0c;一种是无连接规则连接&#xff0c;另一种是有连接规则连接。 无连接规则连…

多卡聚合智能融合通信设备在无人机无线视频传输应用

无人驾驶飞机简称“无人机”&#xff0c;是利用(无线电)遥控设备和自备的程序控制装置操纵的不载人飞行器&#xff0c;现今无人机在航拍、农业、快递运输、测绘、新闻报道多个领域中都有深度的应用。 无人机无线视频传输保证地面人员利用承载的高灵敏度照相机可以进行不间断的画…

Accelerate 笔记:保存与加载文件

保存和加载模型、优化器、随机数生成器和 GradScaler 使用 save_state() 将上述所有内容保存到一个文件夹位置使用 load_state() 加载之前通过 save_state() 保存的状态通过使用 register_for_checkpointing()&#xff0c;可以注册自定义对象以便自动从前两个函数中存储或加载 …

【推荐】用scss循环zoom缩放比例,解决可视化大屏在不同分辨率屏幕下的适配问题

方法1&#xff1a; 指定几种常规屏幕宽度&#xff08;用这种方式就必须要强制用户全屏查看页面&#xff0c;在固定的宽度下才能达到比较不错的显示效果&#xff09; // 适配不同分辨率的页面---------------------------------------- html {overflow: hidden;width: 1920px;…

AR眼镜定制开发_在AR眼镜中实现ChatGPT功能

AR眼镜定制方案中&#xff0c;需要考虑到强大的算力、轻巧的设计和更长的续航时间等基本要求。然而&#xff0c;AR眼镜的设计方案不仅仅需要在硬件和显示技术方面取得突破&#xff0c;还要在用户体验方面有所进展。 过去&#xff0c;由于造价较高&#xff0c;AR眼镜的普及和商业…

搜维尔科技:「案例」Faceware电影中面部动画的演变历程

面部动画是电影中角色表演的一个重要方面&#xff0c;尤其是在严重依赖电子动画、化妆效果和动作捕捉系统的奇幻电影中。在《龙与地下城&#xff1a;盗贼荣誉》电影中&#xff0c;龙裔角色的面部动画是一个复杂的系统&#xff0c;使该生物在大屏幕上栩栩如生。该系统依赖于一种…

逻辑回归及python实现

概述 logistic回归是一种广义线性回归&#xff08;generalized linear model&#xff09;&#xff0c;因此与多重线性回归分析有很多相同之处。它们的模型形式基本上相同&#xff0c;都具有 w‘xb&#xff0c;其中w和b是待求参数&#xff0c;其区别在于他们的因变量不同&#x…

zeppelin 未授权任意命令执行漏洞复现

一、命令执行复现 访问http://ip:8080&#xff0c;打开zeppelin页面&#xff0c;&#xff08;zeppelin默认监听端口在8080&#xff09; 点击Notebook->create new note创建新笔记 在创建笔记的时候选择Default Interpreter为sh&#xff0c;即可执行sh命令 如下图&#x…