OpenCV的“画笔”功能

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

定义函数:

python 复制代码
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 是传递给回调函数的可选参数。

封装为类:

python 复制代码
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

python 复制代码
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())

运行截图:

相关推荐
乾元几秒前
Network-as-Code:把 HCIE / CCIE 实验脚本转为企业级 CI 工程化流程
运维·网络·人工智能·安全·web安全·ai·架构
skywalk81633 分钟前
Vibe Kanban:一个专门为 ‌AI编程助手(AI coding agents)‌ 设计的开源可视化项目管理工具
人工智能·ai编程
数据分析能量站10 分钟前
2025-个人总结
人工智能
Aaron158816 分钟前
三种主流接收机架构(超外差、零中频、射频直采)对比及发展趋势浅析
c语言·人工智能·算法·fpga开发·架构·硬件架构·信号处理
Coder_Boy_16 分钟前
基于SpringAI企业级智能教学考试平台核心模块协同总结与最佳实践方案
java·大数据·人工智能
IT_陈寒17 分钟前
JavaScript性能优化:7个被低估的V8引擎技巧让你的代码提速50%
前端·人工智能·后端
数字化顾问20 分钟前
(103页PPT)产业园区智能化规划设计方案(附下载方式)
大数据·人工智能
愚公搬代码20 分钟前
【愚公系列】《扣子开发 AI Agent 智能体应用》029-实战案例:自动生成 PPT的智能办公助手
人工智能·powerpoint
LS_learner23 分钟前
如何跟上当今AI高速发展的步伐
人工智能
不错就是对27 分钟前
【Agent-lightning】 - 1_环境搭建
人工智能·pytorch·深度学习·机器学习·chatgpt·transformer·vllm