基于 PyQt5 的 Canny 边缘检测工具 - 图像与视频处理
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_())
功能介绍
该程序提供以下功能:
- 打开图像:选择本地图像文件并显示在界面上。
- 打开视频:选择本地视频文件并显示在界面上。
- Canny 检测图像:对已打开的图像进行 Canny 边缘检测。
- Canny 检测视频:对已打开的视频进行 Canny 边缘检测。
- 阈值调节:使用进度条控制 Canny 边缘检测的阈值,使您可以根据需要调整边缘检测效果。
使用方法
- 运行程序。
- 点击 “打开图像” 按钮选择要处理的图像文件。
- 点击 “Canny 检测图像” 按钮进行边缘检测。
- 使用阈值进度条调节阈值,观察边缘检测效果的变化。
- 点击 “打开视频” 按钮选择要处理的视频文件。
- 点击 “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 边缘检测,使用threshold和threshold * 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 边缘检测的基本原理,并为您开发更复杂的图像和视频处理应用提供参考。
原文地址: https://www.cveoy.top/t/topic/ntBu 著作权归作者所有。请勿转载和采集!