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

运行截图:

相关推荐
@心都15 分钟前
机器学习数学基础:44.多元线性回归
人工智能·机器学习·线性回归
说私域15 分钟前
基于开源AI大模型的精准零售模式创新——融合AI智能名片与S2B2C商城小程序源码的“人工智能 + 线下零售”路径探索
人工智能·搜索引擎·小程序·开源·零售
熊文豪19 分钟前
Windows本地部署OpenManus并接入Mistral模型的实践记录
人工智能·llm·mistral·manus·openmanus·openmanus开源替代方案·本地llm部署实践
IT猿手20 分钟前
2025最新群智能优化算法:海市蜃楼搜索优化(Mirage Search Optimization, MSO)算法求解23个经典函数测试集,MATLAB
开发语言·人工智能·算法·机器学习·matlab·机器人
IT猿手2 小时前
2025最新群智能优化算法:山羊优化算法(Goat Optimization Algorithm, GOA)求解23个经典函数测试集,MATLAB
人工智能·python·算法·数学建模·matlab·智能优化算法
Jet45053 小时前
玩转ChatGPT:GPT 深入研究功能
人工智能·gpt·chatgpt·deep research·深入研究
毕加锁3 小时前
chatgpt完成python提取PDF简历指定内容的案例
人工智能·chatgpt
Wis4e5 小时前
基于PyTorch的深度学习3——基于autograd的反向传播
人工智能·pytorch·深度学习
西猫雷婶6 小时前
神经网络|(十四)|霍普菲尔德神经网络-Hebbian训练
人工智能·深度学习·神经网络
梦丶晓羽7 小时前
自然语言处理:文本分类
人工智能·python·自然语言处理·文本分类·朴素贝叶斯·逻辑斯谛回归