Canny 边缘检测工具 - 实时显示原图像和边缘检测结果

本工具使用 Python 和 PyQt5 开发,可以打开图像、视频或摄像头,并实时显示原图像和 Canny 边缘检测结果。用户可以通过调整阈值参数来控制边缘检测效果。

功能

  • 打开图像文件
  • 打开视频文件
  • 打开摄像头
  • 实时显示原图像
  • 实时显示 Canny 边缘检测结果
  • 调整 Canny 边缘检测的阈值参数

代码

#导入模块
import sys
import cv2
import threading
from PyQt5.QtGui import QImage, QPixmap
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QPushButton, QFileDialog, QSlider, QVBoxLayout, QHBoxLayout

class MainWindow(QWidget):   #定义了一个MainWindow类,继承自QWidget类
    def __init__(self):      #构造函数,初始化窗口控件,设置控件位置和大小,绑定按钮点击事件,初始化图像和视频,设置布局
        super().__init__()

        # 创建窗口控件
        self.image_label = QLabel(self)
        self.edges_label = QLabel(self)
        self.setWindowTitle('Canny边缘检测')
        self.open_image_button = QPushButton('打开图像', self)
        self.open_video_button = QPushButton('打开视频', self)
        self.open_camera_button = QPushButton('打开摄像头', self)
        self.canny_image_button = QPushButton('Canny检测图像', self)
        self.canny_video_button = QPushButton('Canny检测视频', self)
        self.canny_camera_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.edges_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.open_camera_button.setGeometry(230, 420, 100, 30)
        self.canny_image_button.setGeometry(10, 460, 100, 30)
        self.canny_video_button.setGeometry(120, 460, 100, 30)
        self.canny_camera_button.setGeometry(230, 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.open_camera_button.clicked.connect(self.open_camera)
        self.canny_image_button.clicked.connect(self.canny_image)
        self.canny_video_button.clicked.connect(self.start_canny_video)
        self.canny_camera_button.clicked.connect(self.start_canny_camera)
        self.threshold_slider.valueChanged.connect(self.set_threshold)

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

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

    def open_image(self):       #打开图像文件的方法,通过QFileDialog选择图像文件,读取图像,将图像转化为QImage格式,显示在界面上面
        # 打开图像文件
        file_name, _ = QFileDialog.getOpenFileName(self, '打开图像', '', 'Image Files(*.jpg *.png *.bmp)')
        print('file name:', file_name)

        if file_name:
            # 释放原有数据
            if self.cap is not None:
                self.cap.release()

            # 读取图像
            self.image = cv2.imread(file_name)
            print('image:', self.image)

            if self.image is None:
                 print('Error: failed to read image')
                 return
            # 将图像转换为QImage格式
            image_qimage = QImage(self.image.data, self.image.shape[1], self.image.shape[0], QImage.Format_RGB888).rgbSwapped()
            edges_qimage = QImage(self.image.data, self.image.shape[1], self.image.shape[0], QImage.Format_Grayscale8)

            # 将QImage显示在界面上
            image_pixmap = QPixmap.fromImage(image_qimage)
            edges_pixmap = QPixmap.fromImage(edges_qimage)
            self.image_label.setPixmap(image_pixmap)
            self.edges_label.setPixmap(edges_pixmap)

            # 释放视频播放定时器
            if self.timer:
                self.timer.cancel()
                self.timer = None

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

        if file_name:
            # 释放原有数据
            if self.image is not None:
                self.image = None
                self.image_label.clear()
                self.edges_label.clear()

            if self.cap is not None:
                self.cap.release()

            # 打开新的视频
            self.cap = cv2.VideoCapture(file_name)

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

                # 将QImage显示在界面上
                image_pixmap = QPixmap.fromImage(image_qimage)
                edges_pixmap = QPixmap.fromImage(edges_qimage)
                self.image_label.setPixmap(image_pixmap)
                self.edges_label.setPixmap(edges_pixmap)

            # 取消视频播放定时器
            if self.timer:
                self.timer.cancel()
                self.timer = None

    def open_camera(self):
        # 打开摄像头
        if self.cap is not None:
            self.cap.release()

        self.cap = cv2.VideoCapture(0)

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

            # 将QImage显示在界面上
            image_pixmap = QPixmap.fromImage(image_qimage)
            edges_pixmap = QPixmap.fromImage(edges_qimage)
            self.image_label.setPixmap(image_pixmap)
            self.edges_label.setPixmap(edges_pixmap)

        # 取消视频播放定时器
        if self.timer:
            self.timer.cancel()
            self.timer = None

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

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

            # 将QImage显示在界面上
            edges_pixmap = QPixmap.fromImage(edges_qimage)
            self.edges_label.setPixmap(edges_pixmap)

    def start_canny_video(self):
        # 启动视频播放定时器
        if self.timer is None:
            self.timer = threading.Timer(0.03, self.canny_video)
            self.timer.start()

    def start_canny_camera(self):
        # 启动视频播放定时器
        if self.timer is None:
            self.timer = threading.Timer(0.03, self.canny_camera)
            self.timer.start()

    def canny_video(self):
        if self.cap is not None:
            # 读取视频帧
            ret, frame = self.cap.read()
            if ret:
                # Canny边缘检测
                edges = cv2.Canny(frame, self.threshold, self.threshold * 2)

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

                # 将QImage显示在界面上
                edges_pixmap = QPixmap.fromImage(edges_qimage)
                self.edges_label.setPixmap(edges_pixmap)

            # 启动视频播放定时器
            self.timer = threading.Timer(0.03, self.canny_video)
            self.timer.start()

    def canny_camera(self):
        if self.cap is not None:
            # 读取视频帧
            ret, frame = self.cap.read()
            if ret:
                # Canny边缘检测
                edges = cv2.Canny(frame, self.threshold, self.threshold * 2)

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

                # 将QImage显示在界面上
                edges_pixmap = QPixmap.fromImage(edges_qimage)
                self.edges_label.setPixmap(edges_pixmap)

            # 启动视频播放定时器
            self.timer = threading.Timer(0.03, self.canny_camera)
            self.timer.start()

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

    def __del__(self):
        # 清理资源
        if self.cap:
            self.cap.release
        cv2.destroyAllWindows()

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

使用方法

  1. 确保已安装必要的库,包括 opencv-pythonPyQt5
  2. 运行代码。
  3. 点击 打开图像打开视频打开摄像头 按钮选择要处理的图像、视频或摄像头。
  4. 点击 Canny检测图像Canny检测视频Canny检测摄像头 按钮进行边缘检测。
  5. 使用 阈值 滚动条调整 Canny 边缘检测的阈值参数。

注意事项

  • 该工具仅支持 JPG、PNG 和 BMP 图像文件,以及 MP4 和 AVI 视频文件。
  • 可以根据需要调整代码中 setGeometry 方法的参数来调整窗口和控件的大小和位置。

联系方式

如果您有任何问题或建议,请随时联系我。

许可证

该工具是免费的,并使用 MIT 许可证授权。

Canny 边缘检测工具 - 实时显示原图像和边缘检测结果

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

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