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())

运行截图:

相关推荐
skywalk816310 分钟前
我现在手里有comate、dumate、 workbuddy和trae四个agent,你看这四个任务怎么分合适?
人工智能·deepseek
用户06177085449512 分钟前
Agent 办事失败兜底技术实现方案:从失败模型到生产级容错体系
人工智能
是大乔家的15 分钟前
网文分销商必备神器:用知漫剧快速将授权小说转化为连载视频引流
人工智能
ITmaster073121 分钟前
面试官坏笑:“你用 AI 编程一年了,怎么保证 Claude Code 写出来的代码是对的?”我:“直接上 Claude Fable 5 啊!”
人工智能
英雄62722 分钟前
给 DeepSeek Harness Web 写了一个美化插件
人工智能
dogstarhuang34 分钟前
OpenAI GPT-5.6 降价后如何重算 API 账单?多模型路由与成本治理实战
服务器·网络·人工智能·大模型·api·ai应用开发·接口管理
CRMEB定制开发35 分钟前
2026年最值得推荐的10大开源商城系统盘点
开发语言·人工智能·开源·商城系统·小程序商城
MobotStone1 小时前
AI让一个人像一家公司,但没让普通人突然变成老板
人工智能
Pika1 小时前
DeepSeek Harness 架构拆解
人工智能
智购科技自动售卖机厂家1 小时前
2026自动售货机OTA升级系统设计:从全量升级到差分升级的带宽优化工程实践~YH
大数据·人工智能·numpy·pyqt·fastapi