import sys
import cv2
from PyQt5.QtGui import QImage, QPixmap
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QPushButton, QFileDialog, QSlider, QVBoxLayout, QHBoxLayout

class MainWindow(QWidget):
    def __init__(self):
        super().__init__()

        # 创建窗口控件
        self.image_label = QLabel(self)
        self.video_label = QLabel(self)
        self.open_image_button = QPushButton('打开图像', self)
        self.open_video_button = QPushButton('打开视频', self)
        self.canny_image_button = QPushButton('Canny检测图像', self)
        self.canny_video_button = QPushButton('Canny检测视频', self)
        self.threshold_label = QLabel('阈值:100', self)
        self.threshold_slider = QSlider(self)
        self.threshold_slider.setOrientation(1)
        self.threshold_slider.setMinimum(0)
        self.threshold_slider.setMaximum(255)
        self.threshold_slider.setValue(100)

        # 设置控件位置和大小
        self.image_label.setGeometry(10, 10, 400, 400)
        self.video_label.setGeometry(420, 10, 400, 400)
        self.open_image_button.setGeometry(10, 420, 100, 30)
        self.open_video_button.setGeometry(120, 420, 100, 30)
        self.canny_image_button.setGeometry(10, 460, 100, 30)
        self.canny_video_button.setGeometry(120, 460, 100, 30)
        self.threshold_label.setGeometry(10, 500, 100, 30)
        self.threshold_slider.setGeometry(10, 530, 30, 150)

        # 绑定按钮点击事件
        self.open_image_button.clicked.connect(self.open_image)
        self.open_video_button.clicked.connect(self.open_video)
        self.canny_image_button.clicked.connect(self.canny_image)
        self.canny_video_button.clicked.connect(self.canny_video)
        self.threshold_slider.valueChanged.connect(self.set_threshold)

        # 初始化图像和视频
        self.image = None
        self.cap = None
        self.threshold = 100

        # 设置布局
        vbox = QVBoxLayout()
        hbox1 = QHBoxLayout()
        hbox2 = QHBoxLayout()
        vbox.addWidget(self.image_label)
        vbox.addWidget(self.video_label)
        hbox1.addWidget(self.open_image_button)
        hbox1.addWidget(self.open_video_button)
        hbox1.addWidget(self.canny_image_button)
        hbox1.addWidget(self.canny_video_button)
        hbox2.addWidget(self.threshold_label)
        hbox2.addWidget(self.threshold_slider)
        vbox.addLayout(hbox1)
        vbox.addLayout(hbox2)
        self.setLayout(vbox)

    def open_image(self):
        # 打开图像文件
        file_name, _ = QFileDialog.getOpenFileName(self, '打开图像', '', 'Image Files(*.jpg *.png *.bmp)')

        if file_name:
            # 读取图像
            self.image = cv2.imread(file_name)

            # 将图像转换为QImage格式
            qimage = QImage(self.image.data, self.image.shape[1], self.image.shape[0], QImage.Format_RGB888).rgbSwapped()

            # 将QImage显示在界面上
            pixmap = QPixmap.fromImage(qimage)
            self.image_label.setPixmap(pixmap)

    def open_video(self):
        # 打开视频文件
        file_name, _ = QFileDialog.getOpenFileName(self, '打开视频', '', 'Video Files(*.mp4 *.avi)')

        if file_name:
            # 打开视频
            self.cap = cv2.VideoCapture(file_name)

            # 显示第一帧图像
            ret, frame = self.cap.read()
            if ret:
                # 将图像转换为QImage格式
                qimage = QImage(frame.data, frame.shape[1], frame.shape[0], QImage.Format_RGB888).rgbSwapped()

                # 将QImage显示在界面上
                pixmap = QPixmap.fromImage(qimage)
                self.video_label.setPixmap(pixmap)

    def canny_image(self):
        if self.image is not None:
            # Canny边缘检测
            edges = cv2.Canny(self.image, self.threshold, self.threshold * 2)

            # 将边缘图像转换为QImage格式
            qimage = QImage(edges.data, edges.shape[1], edges.shape[0], QImage.Format_Grayscale8)

            # 将QImage显示在界面上
            pixmap = QPixmap.fromImage(qimage)
            self.image_label.setPixmap(pixmap)

    def canny_video(self):
        if self.cap is not None:
            while True:
                # 读取视频帧
                ret, frame = self.cap.read()
                if not ret:
                    break

                # Canny边缘检测
                edges = cv2.Canny(frame, self.threshold, self.threshold * 2)

                # 将边缘图像转换为QImage格式
                qimage = QImage(edges.data, edges.shape[1], edges.shape[0], QImage.Format_Grayscale8)

                # 将QImage显示在界面上
                pixmap = QPixmap.fromImage(qimage)
                self.video_label.setPixmap(pixmap)

                # 等待100毫秒,等待界面更新
                cv2.waitKey(100)

    def set_threshold(self, value):
        self.threshold = value
        self.threshold_label.setText('阈值:{}'.format(value))

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

功能介绍

该程序提供以下功能:

  1. 打开图像:选择本地图像文件并显示在界面上。
  2. 打开视频:选择本地视频文件并显示在界面上。
  3. Canny 检测图像:对已打开的图像进行 Canny 边缘检测。
  4. Canny 检测视频:对已打开的视频进行 Canny 边缘检测。
  5. 阈值调节:使用进度条控制 Canny 边缘检测的阈值,使您可以根据需要调整边缘检测效果。

使用方法

  1. 运行程序。
  2. 点击 “打开图像” 按钮选择要处理的图像文件。
  3. 点击 “Canny 检测图像” 按钮进行边缘检测。
  4. 使用阈值进度条调节阈值,观察边缘检测效果的变化。
  5. 点击 “打开视频” 按钮选择要处理的视频文件。
  6. 点击 “Canny 检测视频” 按钮进行边缘检测。

应用场景

该程序适用于图像和视频处理领域,例如:

  • 图像特征提取:从图像中提取边缘信息,用于识别和分析。
  • 目标检测:利用边缘信息识别图像中的目标物体。
  • 视频分析:对视频内容进行分析,提取运动信息和边缘特征。

代码分析

1. 导入库

import sys
import cv2
from PyQt5.QtGui import QImage, QPixmap
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QPushButton, QFileDialog, QSlider, QVBoxLayout, QHBoxLayout
  • sys:用于系统操作,例如退出程序。
  • cv2:OpenCV 库,用于图像和视频处理。
  • QImage, QPixmap:PyQt5 库中的图像类,用于显示图像。
  • QApplication, QWidget, QLabel, QPushButton, QFileDialog, QSlider, QVBoxLayout, QHBoxLayout:PyQt5 库中的界面元素类,用于创建界面和布局。

2. 定义 MainWindow 类

class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
  • MainWindow 是主窗口类,继承自 QWidget 类。
  • __init__ 方法是构造函数,用于初始化窗口。

3. 创建窗口控件

        self.image_label = QLabel(self)
        self.video_label = QLabel(self)
        self.open_image_button = QPushButton('打开图像', self)
        self.open_video_button = QPushButton('打开视频', self)
        self.canny_image_button = QPushButton('Canny检测图像', self)
        self.canny_video_button = QPushButton('Canny检测视频', self)
        self.threshold_label = QLabel('阈值:100', self)
        self.threshold_slider = QSlider(self)
        self.threshold_slider.setOrientation(1)
        self.threshold_slider.setMinimum(0)
        self.threshold_slider.setMaximum(255)
        self.threshold_slider.setValue(100)
  • 创建各个控件,包括图像显示标签 (image_label, video_label),按钮 (open_image_button, open_video_button, canny_image_button, canny_video_button),阈值标签 (threshold_label) 和 阈值进度条 (threshold_slider)。
  • 设置进度条的方向为垂直 (setOrientation(1)),最小值为 0,最大值为 255,初始值为 100。

4. 设置控件位置和大小

        self.image_label.setGeometry(10, 10, 400, 400)
        self.video_label.setGeometry(420, 10, 400, 400)
        self.open_image_button.setGeometry(10, 420, 100, 30)
        self.open_video_button.setGeometry(120, 420, 100, 30)
        self.canny_image_button.setGeometry(10, 460, 100, 30)
        self.canny_video_button.setGeometry(120, 460, 100, 30)
        self.threshold_label.setGeometry(10, 500, 100, 30)
        self.threshold_slider.setGeometry(10, 530, 30, 150)
  • 设置各个控件的位置和大小,使用 setGeometry 方法。

5. 绑定按钮点击事件

        self.open_image_button.clicked.connect(self.open_image)
        self.open_video_button.clicked.connect(self.open_video)
        self.canny_image_button.clicked.connect(self.canny_image)
        self.canny_video_button.clicked.connect(self.canny_video)
        self.threshold_slider.valueChanged.connect(self.set_threshold)
  • 使用 clicked.connect 方法将按钮的点击事件绑定到对应的处理函数:
    • open_image:打开图像文件。
    • open_video:打开视频文件。
    • canny_image:对图像进行 Canny 边缘检测。
    • canny_video:对视频进行 Canny 边缘检测。
  • 使用 valueChanged.connect 方法将进度条的值改变事件绑定到 set_threshold 函数,用于更新阈值。

6. 初始化图像和视频

        self.image = None
        self.cap = None
        self.threshold = 100
  • 初始化图像 (image) 和视频捕捉对象 (cap) 为 None,表示还没有打开任何文件。
  • 初始化阈值为 100。

7. 设置布局

        vbox = QVBoxLayout()
        hbox1 = QHBoxLayout()
        hbox2 = QHBoxLayout()
        vbox.addWidget(self.image_label)
        vbox.addWidget(self.video_label)
        hbox1.addWidget(self.open_image_button)
        hbox1.addWidget(self.open_video_button)
        hbox1.addWidget(self.canny_image_button)
        hbox1.addWidget(self.canny_video_button)
        hbox2.addWidget(self.threshold_label)
        hbox2.addWidget(self.threshold_slider)
        vbox.addLayout(hbox1)
        vbox.addLayout(hbox2)
        self.setLayout(vbox)
  • 使用 QVBoxLayout, QHBoxLayout 创建垂直和水平布局,并添加控件。
  • 将布局设置到主窗口。

8. 定义处理函数

    def open_image(self):
        # 打开图像文件
        file_name, _ = QFileDialog.getOpenFileName(self, '打开图像', '', 'Image Files(*.jpg *.png *.bmp)')

        if file_name:
            # 读取图像
            self.image = cv2.imread(file_name)

            # 将图像转换为QImage格式
            qimage = QImage(self.image.data, self.image.shape[1], self.image.shape[0], QImage.Format_RGB888).rgbSwapped()

            # 将QImage显示在界面上
            pixmap = QPixmap.fromImage(qimage)
            self.image_label.setPixmap(pixmap)

    def open_video(self):
        # 打开视频文件
        file_name, _ = QFileDialog.getOpenFileName(self, '打开视频', '', 'Video Files(*.mp4 *.avi)')

        if file_name:
            # 打开视频
            self.cap = cv2.VideoCapture(file_name)

            # 显示第一帧图像
            ret, frame = self.cap.read()
            if ret:
                # 将图像转换为QImage格式
                qimage = QImage(frame.data, frame.shape[1], frame.shape[0], QImage.Format_RGB888).rgbSwapped()

                # 将QImage显示在界面上
                pixmap = QPixmap.fromImage(qimage)
                self.video_label.setPixmap(pixmap)

    def canny_image(self):
        if self.image is not None:
            # Canny边缘检测
            edges = cv2.Canny(self.image, self.threshold, self.threshold * 2)

            # 将边缘图像转换为QImage格式
            qimage = QImage(edges.data, edges.shape[1], edges.shape[0], QImage.Format_Grayscale8)

            # 将QImage显示在界面上
            pixmap = QPixmap.fromImage(qimage)
            self.image_label.setPixmap(pixmap)

    def canny_video(self):
        if self.cap is not None:
            while True:
                # 读取视频帧
                ret, frame = self.cap.read()
                if not ret:
                    break

                # Canny边缘检测
                edges = cv2.Canny(frame, self.threshold, self.threshold * 2)

                # 将边缘图像转换为QImage格式
                qimage = QImage(edges.data, edges.shape[1], edges.shape[0], QImage.Format_Grayscale8)

                # 将QImage显示在界面上
                pixmap = QPixmap.fromImage(qimage)
                self.video_label.setPixmap(pixmap)

                # 等待100毫秒,等待界面更新
                cv2.waitKey(100)

    def set_threshold(self, value):
        self.threshold = value
        self.threshold_label.setText('阈值:{}'.format(value))

  • open_image 函数
    • 使用 QFileDialog.getOpenFileName 打开图像文件选择对话框。
    • 读取图像文件并将其转换为 QImage 格式。
    • QImage 显示在 image_label 上。
  • open_video 函数
    • 使用 QFileDialog.getOpenFileName 打开视频文件选择对话框。
    • 打开视频文件,并显示第一帧图像。
  • canny_image 函数
    • 使用 cv2.Canny 对图像进行 Canny 边缘检测,使用 thresholdthreshold * 2 作为阈值。
    • 将边缘图像转换为 QImage 格式,并显示在 image_label 上。
  • canny_video 函数
    • 从视频文件读取帧,并对每一帧进行 Canny 边缘检测。
    • 将边缘图像转换为 QImage 格式,并显示在 video_label 上。
    • 使用 cv2.waitKey(100) 等待 100 毫秒,以便界面更新。
  • set_threshold 函数
    • 更新 threshold 的值,并更新阈值标签的文本。

9. 运行程序

if __name__ == '__main__':
    app = QApplication(sys.argv)
    main_window = MainWindow()
    main_window.show()
    sys.exit(app.exec_())
  • 创建 QApplication 对象,启动 PyQt5 应用。
  • 创建 MainWindow 对象,并显示窗口。
  • 进入事件循环,等待用户操作。

总结

这段代码展示了使用 PyQt5 和 OpenCV 进行 Canny 边缘检测的简单示例,并提供了阈值调节功能,使您可以灵活地控制边缘检测效果。该程序可以作为基础框架,用于开发更复杂的功能,例如:

  • 添加更多图像和视频处理功能。
  • 使用更高级的 UI 控件和布局。
  • 实现更复杂的图像分析和识别算法。

希望这篇文档能够帮助您了解使用 PyQt5 和 OpenCV 进行 Canny 边缘检测的基本原理,并为您开发更复杂的图像和视频处理应用提供参考。

基于 PyQt5 的 Canny 边缘检测工具 - 图像与视频处理

原文地址: https://www.cveoy.top/t/topic/ntBu 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录