本次学习我们学习的是PyQt5。PyQt实现了一个Python模块集。它有超过300类,将近6000个函数和方法。它是一个多平台的工具包,可以运行在所有主要操作系统上,包括UNIX,Windows和Mac。这是一个十分重要的
1.初识pyqt
1.在 PyCharm 中编写第一个 PyQt5 应用程序
接下来,我们将在 PyCharm 中创建一个简单的 PyQt5 应用程序,显示一个包含 “Hello, World!” 的窗口。
- 创建 Python 文件:在 PyCharm 项目中,右键点击项目文件夹,选择 New -> Python File,将文件命名为 main.py。
- 编写代码: 在新建的 main.py 文件中,输入以下代码:
import sys # 导入 sys 模块,用于与 Python 解释器交互 from PyQt5.QtWidgets import QApplication, QLabel, QMainWindow # 从 PyQt5 中导入所需的类 # 创建一个主窗口类,继承自 QMainWindow class MainWindow(QMainWindow): def __init__(self): super().__init__() # 调用父类 QMainWindow 的初始化方法 self.setWindowTitle("PyQt5 第一个窗口") # 设置窗口标题 # 创建一个 QLabel 标签,并将其作为主窗口的中央控件 label = QLabel("Hello, World!", self) self.setCentralWidget(label) # 将标签作为窗口的中央控件 # 创建一个 PyQt5 应用程序对象 app = QApplication(sys.argv) # 创建主窗口实例 window = MainWindow() window.show() # 显示窗口 # 进入应用程序的事件循环,保持应用程序运行,直到关闭窗口 sys.exit(app.exec_())2.代码详细解释:
-
import sys 作用:sys 是 Python 的内置模块,提供了一些与 Python 解释器进行交互的功能。在 PyQt5 中,sys.exit() 用来确保应用程序关闭时退出干净,不留任何后台进程。
-
from PyQt5.QtWidgets import QApplication, QLabel, QMainWindow QApplication:每个 PyQt5 程序必须有一个 QApplication 实例,它管理应用程序的控制流和设置。
-
QMainWindow:这是 PyQt5 中的主窗口类,它是所有复杂窗口的基础。可以包含菜单栏、工具栏、状态栏、中央控件等。
-
QLabel:这是一个简单的控件,用于显示文本。
-
class MainWindow(QMainWindow): 作用:定义了一个名为 MainWindow 的类,继承自 QMainWindow。通过继承 QMainWindow,我们可以自定义窗口的行为和外观。
-
self.setWindowTitle("PyQt5 第一个窗口") 作用:设置窗口的标题,标题显示在应用程序窗口的顶部。
-
label = QLabel("Hello, World!", self) 作用:创建一个 QLabel 控件,显示文本 “Hello, World!”。 self 参数:将标签关联到当前窗口(MainWindow),即将其设置为窗口的子控件。
-
self.setCentralWidget(label) 作用:设置 label 为窗口的中央控件,中央控件是填充窗口中间区域的控件。
-
app = QApplication(sys.argv) 作用:QApplication 是 PyQt5 应用程序的基础,每个 PyQt5 应用程序都必须有一个 QApplication 实例,它管理整个应用程序的生命周期和事件处理。 sys.argv:传递命令行参数,通常可以忽略。
-
window.show() 作用:将窗口设置为可见,并显示在屏幕上。 sys.exit(app.exec_()) 作用:app.exec_() 开始应用程序的事件循环,保持应用程序的持续运行,直到用户关闭窗口。sys.exit() 确保应用程序正常退出。
3.运行代码后:

2.核心概念
信号与槽机制
这是 PyQt5 里处理事件的关键机制。信号代表事件的发生,槽则是对该事件做出响应的函数。当信号被发射时,与之连接的槽函数就会被调用。 下面是一个简单示例:
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton
def on_button_click():
print("按钮被点击了!")
if __name__ == '__main__':
app = QApplication(sys.argv)
window = QWidget()
button = QPushButton('点击我', window)
button.clicked.connect(on_button_click)
window.show()
sys.exit(app.exec_())
在这个例子中,clicked 是 QPushButton 发出的信号,on_button_click 是与之连接的槽函数。当按钮被点击时,clicked 信号被发射,on_button_click 函数就会被调用。

布局管理
布局管理能够帮助你在窗口中合理排列和管理各种组件。PyQt5 提供了多种布局管理器,像 QVBoxLayout(垂直布局)、QHBoxLayout(水平布局)、QGridLayout(网格布局)等。
以下是使用 QVBoxLayout 的示例:
import sys # 导入 sys 模块,用于与 Python 解释器交互
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton # 导入 PyQt5 中的必要组件
if __name__ == '__main__': # 确保这段代码是作为主程序运行,而不是作为模块导入
app = QApplication(sys.argv) # 创建一个 QApplication 对象,它是每个 PyQt5 应用程序的核心,sys.argv 是命令行参数列表
window = QWidget() # 创建一个 QWidget 对象,作为应用程序的主窗口
layout = QVBoxLayout() # 创建一个 QVBoxLayout 布局管理器,用于垂直排列窗口中的组件
button1 = QPushButton('按钮 1') # 创建一个 QPushButton 对象,按钮上显示文本 "按钮 1"
button2 = QPushButton('按钮 2') # 创建另一个 QPushButton 对象,按钮上显示文本 "按钮 2"
layout.addWidget(button1) # 将按钮 1 添加到布局管理器中
layout.addWidget(button2) # 将按钮 2 添加到布局管理器中
window.setLayout(layout) # 将布局管理器设置为窗口的布局
window.show() # 显示窗口
sys.exit(app.exec_()) # 启动应用程序的事件循环,等待用户操作,并在关闭窗口时退出程序
在这个例子中,两个按钮通过 QVBoxLayout 垂直排列在窗口中。

实战演练
1.0
我们先放入“灰度化处理”和“高斯模糊”两项功能。
import sys
import cv2
import numpy as np
from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel, QPushButton, QVBoxLayout, QWidget, QFileDialog
from PyQt5.QtGui import QPixmap, QImage
from PyQt5.QtCore import Qt
class ImageProcessingApp(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("图像处理系统")
self.setGeometry(100, 100, 800, 600) # 设置窗口位置和大小
# 创建中心部件
self.central_widget = QWidget()
self.setCentralWidget(self.central_widget)
# 创建布局
self.layout = QVBoxLayout(self.central_widget)
# 创建标签用于显示原始图像
self.original_label = QLabel("原始图像", self)
self.original_label.setAlignment(Qt.AlignCenter)
self.layout.addWidget(self.original_label)
# 创建标签用于显示处理后的图像
self.processed_label = QLabel("处理后的图像", self)
self.processed_label.setAlignment(Qt.AlignCenter)
self.layout.addWidget(self.processed_label)
# 创建按钮用于加载图像
self.load_button = QPushButton("加载图像", self)
self.layout.addWidget(self.load_button)
self.load_button.clicked.connect(self.load_image)
# 创建按钮用于灰度化处理
self.process_button = QPushButton("灰度化处理", self)
self.layout.addWidget(self.process_button)
self.process_button.clicked.connect(self.process_image)
# 创建按钮用于高斯模糊处理
self.blur_button = QPushButton("高斯模糊", self)
self.layout.addWidget(self.blur_button)
self.blur_button.clicked.connect(self.blur_image)
# 初始化图像变量
self.original_image = None
self.processed_image = None
def load_image(self):
"""加载图像"""
file_path, _ = QFileDialog.getOpenFileName(self, "选择图像文件", "", "Image Files (*.png *.jpg *.bmp *.gif)")
if file_path:
# 使用 OpenCV 加载图像
self.original_image = cv2.imread(file_path)
if self.original_image is not None:
# 将 OpenCV 图像转换为 QPixmap 并显示
self.display_image(self.original_image, self.original_label)
self.processed_image = None
self.processed_label.clear()
def process_image(self):
"""灰度化处理"""
if self.original_image is not None:
self.processed_image = cv2.cvtColor(self.original_image, cv2.COLOR_BGR2GRAY)
self.display_image(self.processed_image, self.processed_label)
def blur_image(self):
"""高斯模糊处理"""
if self.processed_image is not None:
self.processed_image = cv2.GaussianBlur(self.processed_image, (5, 5), 0)
self.display_image(self.processed_image, self.processed_label)
elif self.original_image is not None:
self.processed_image = cv2.cvtColor(self.original_image, cv2.COLOR_BGR2GRAY)
self.processed_image = cv2.GaussianBlur(self.processed_image, (5, 5), 0)
self.display_image(self.processed_image, self.processed_label)
def display_image(self, cv_image, label):
"""将 OpenCV 图像转换为 QPixmap 并显示"""
height, width = cv_image.shape[:2]
if len(cv_image.shape) == 2: # 灰度图像
image_format = QImage.Format_Grayscale8
else: # 彩色图像
image_format = QImage.Format_BGR888
qt_image = QImage(cv_image, width, height, cv_image.strides[0], image_format)
pixmap = QPixmap.fromImage(qt_image)
label.setPixmap(pixmap.scaled(label.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation))
if __name__ == "__main__":
app = QApplication(sys.argv)
window = ImageProcessingApp()
window.show()
sys.exit(app.exec_())

2.0
我们从1.0中看到我们实现的功能太少了,改进代码,添加功能
import sys
import cv2
import numpy as np
from PyQt5.QtWidgets import (
QApplication, QMainWindow, QWidget, QLabel, QPushButton,
QFileDialog, QMessageBox, QVBoxLayout, QHBoxLayout, QFrame
)
from PyQt5.QtGui import QPixmap, QImage
from PyQt5.QtCore import Qt
# 定义一个继承自QMainWindow的图像处理器类
class ImageProcessor(QMainWindow):
def __init__(self):
# 调用父类的构造函数
super().__init__()
# 设置窗口标题
self.setWindowTitle("PyQt演示")
# 设置窗口大小
self.resize(900, 600)
# 用于存储原始图像和处理后的图像数据
self.image_data = {}
# 创建主窗口小部件
main_widget = QWidget()
# 将主窗口小部件设置为中心部件
self.setCentralWidget(main_widget)
# 创建垂直布局
main_layout = QVBoxLayout(main_widget)
# 设置主窗口小部件的样式表
main_widget.setStyleSheet("""
QWidget {
background-color: #f0f4f8;
}
QLabel {
border: 2px solid #aaa;
border-radius: 10px;
background-color: white;
padding: 5px;
box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1);
}
QPushButton {
font-size: 15px;
padding: 8px 18px;
min-width: 100px;
}
""")
# 创建顶部水平布局
top_layout = QHBoxLayout()
# 创建加载图片按钮
load_btn = QPushButton("📂 加载图片")
# 创建保存图像按钮
save_btn = QPushButton("💾 保存图像")
# 为加载按钮绑定点击事件,点击时调用load_image方法
load_btn.clicked.connect(self.load_image)
# 为保存按钮绑定点击事件,点击时调用save_image方法
save_btn.clicked.connect(self.save_image)
# 将加载按钮添加到顶部布局
top_layout.addWidget(load_btn)
# 将保存按钮添加到顶部布局
top_layout.addWidget(save_btn)
# 在布局中添加一个拉伸项,使按钮靠左对齐
top_layout.addStretch()
# 将顶部布局添加到主布局
main_layout.addLayout(top_layout)
# 添加水平分割线
main_layout.addWidget(self._h_line())
# 创建用于显示图像的水平布局
img_layout = QHBoxLayout()
# 创建用于显示原始图像的标签
self.original_label = QLabel()
# 创建用于显示处理后图像的标签
self.processed_label = QLabel()
# 为原始图像和处理后图像的标签设置固定大小和对齐方式
for label in (self.original_label, self.processed_label):
label.setFixedSize(400, 400)
label.setAlignment(Qt.AlignmentFlag.AlignCenter)
# 将原始图像标签添加到图像布局
img_layout.addWidget(self.original_label)
# 添加垂直分割线
img_layout.addWidget(self._v_line())
# 将处理后图像标签添加到图像布局
img_layout.addWidget(self.processed_label)
# 设置布局中部件之间的间距
img_layout.setSpacing(0)
# 将图像布局添加到主布局
main_layout.addLayout(img_layout)
# 添加水平分割线
main_layout.addWidget(self._h_line())
# 创建底部水平布局
bottom_layout = QHBoxLayout()
# 定义按钮文本和对应的处理模式
for text, func in [("⚫灰度化", "gray"), ("🔍去噪", "denoise"),
("✨锐化", "sharpen"), ("🔄旋转", "rotate"),
("🔀反转", "flip"), ("🌫️模糊", "blur")]:
# 创建按钮
btn = QPushButton(text)
# 为按钮绑定点击事件,点击时调用process方法并传入对应的处理模式
btn.clicked.connect(lambda _, f=func: self.process(f))
# 将按钮添加到底部布局
bottom_layout.addWidget(btn)
# 在布局中添加一个拉伸项,使按钮靠左对齐
bottom_layout.addStretch()
# 将底部布局添加到主布局
main_layout.addLayout(bottom_layout)
# 创建水平分割线的方法
def _h_line(self):
line = QFrame()
line.setFrameShape(QFrame.Shape.HLine)
line.setFrameShadow(QFrame.Shadow.Sunken)
line.setStyleSheet("color: #ccc;")
return line
# 创建垂直分割线的方法
def _v_line(self):
line = QFrame()
line.setFrameShape(QFrame.Shape.VLine)
line.setFrameShadow(QFrame.Shadow.Sunken)
line.setStyleSheet("color: #ccc;")
return line
# 加载图像的方法
def load_image(self):
"""加载图像"""
# 打开文件选择对话框,选择图片文件
file, _ = QFileDialog.getOpenFileName(self, "选择图片", "", "图片文件 (*.png *.jpg *.bmp)")
if file:
# 使用OpenCV读取图片
img = cv2.imread(file)
if img is None:
# 若无法加载图像,显示错误消息框
QMessageBox.warning(self, "错误", "无法加载图像")
return
# 存储原始图像
self.image_data['original'] = img
# 存储处理后的图像,初始为原图的副本
self.image_data['processed'] = img.copy()
# 显示原始图像
self.show_image(img, self.original_label)
# 保存图像的方法
def save_image(self):
"""保存图像"""
if 'processed' not in self.image_data:
# 若没有处理后的图像,显示提示消息框
QMessageBox.warning(self, "提示", "没有可保存的图像")
return
# 打开文件保存对话框,选择保存路径和格式
file, _ = QFileDialog.getSaveFileName(self, "保存图像", "", "PNG (*.png);;JPG (*.jpg)")
if file:
# 使用OpenCV保存处理后的图像
cv2.imwrite(file, self.image_data['processed'])
# 显示保存成功的消息框
QMessageBox.information(self, "成功", f"图像已保存:{file}")
# 处理图像的方法
def process(self, mode):
"""根据选择的模式处理图像"""
if 'original' not in self.image_data:
# 若没有加载原始图像,显示提示消息框
QMessageBox.warning(self, "提示", "请先加载图片")
return
# 获取原始图像
img = self.image_data['original']
if mode == "gray": # 灰度化处理
# 将图像转换为灰度图
result = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 将灰度图转换回三通道图像
result = cv2.cvtColor(result, cv2.COLOR_GRAY2BGR)
elif mode == "denoise": # 去噪处理
# 使用快速非局部均值去噪算法对彩色图像去噪
result = cv2.fastNlMeansDenoisingColored(img, None, 10, 10, 7, 21)
elif mode == "sharpen": # 锐化处理
# 定义锐化核
kernel = np.array([[-1, -1, -1], [-1, 9, -1], [-1, -1, -1]])
# 使用卷积操作进行锐化处理
result = cv2.filter2D(img, -1, kernel)
elif mode == "rotate": # 旋转处理
# 获取图像的行数和列数
rows, cols = img.shape[:2]
# 计算旋转矩阵,旋转90度
M = cv2.getRotationMatrix2D((cols / 2, rows / 2), 90, 1)
# 应用仿射变换进行旋转
result = cv2.warpAffine(img, M, (cols, rows))
elif mode == "flip": # 反转处理
# 水平反转图像
result = cv2.flip(img, 1)
elif mode == "blur": # 模糊处理
# 使用高斯模糊对图像进行模糊处理
result = cv2.GaussianBlur(img, (5, 5), 0)
else:
return
# 存储处理后的图像
self.image_data['processed'] = result
# 显示处理后的图像
self.show_image(result, self.processed_label)
# 显示图像的方法
def show_image(self, img, label):
"""显示图像"""
# 将BGR格式的图像转换为RGB格式
rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# 获取图像的高度、宽度和通道数
h, w, ch = rgb.shape
# 计算每行的字节数
bytes_per_line = ch * w
# 将图像数据转换为QImage格式
q_img = QImage(rgb.data, w, h, bytes_per_line, QImage.Format.Format_RGB888)
# 将QImage转换为QPixmap并缩放后显示在标签上
label.setPixmap(QPixmap.fromImage(q_img).scaled(400, 400, Qt.AspectRatioMode.KeepAspectRatio))
if __name__ == "__main__":
# 创建应用程序对象
app = QApplication(sys.argv)
# 创建图像处理器窗口对象
window = ImageProcessor()
# 显示窗口
window.show()
# 进入应用程序的主循环
sys.exit(app.exec())

3.0
我们从2.0中得到,对这一张图片只能进行1次操作,无法在意造作的基础上进行二次更改,所以的活改进代码
import sys
import cv2
import numpy as np
from PyQt5.QtWidgets import (
QApplication, QMainWindow, QWidget, QLabel, QPushButton,
QFileDialog, QMessageBox, QVBoxLayout, QHBoxLayout, QFrame
)
from PyQt5.QtGui import QPixmap, QImage
from PyQt5.QtCore import Qt
# 定义一个继承自QMainWindow的图像处理器类
class ImageProcessor(QMainWindow):
def __init__(self):
# 调用父类QMainWindow的构造函数
super().__init__()
# 设置窗口的标题
self.setWindowTitle("PyQt演示")
# 设置窗口的大小
self.resize(900, 600)
# 用于存储原始图像和处理后的图像数据
self.image_data = {}
# 用于存储原始图像的副本,方便后续还原操作
self.original_image = None
# 创建主窗口的中心小部件
main_widget = QWidget()
# 将主窗口的中心小部件设置为main_widget
self.setCentralWidget(main_widget)
# 创建一个垂直布局用于主窗口的布局管理
main_layout = QVBoxLayout(main_widget)
# 设置主窗口小部件及其子部件的样式
main_widget.setStyleSheet("""
QWidget {
background-color: #f0f4f8;
}
QLabel {
border: 2px solid #aaa;
border-radius: 10px;
background-color: white;
padding: 5px;
box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1);
}
QPushButton {
font-size: 15px;
padding: 8px 18px;
min-width: 100px;
}
""")
# 创建顶部水平布局
top_layout = QHBoxLayout()
# 创建加载图片的按钮
load_btn = QPushButton("📂 加载图片")
# 创建保存图像的按钮
save_btn = QPushButton("💾 保存图像")
# 创建还原图像的按钮
restore_btn = QPushButton("🔙 还原")
# 为加载按钮绑定点击事件,点击时调用load_image方法
load_btn.clicked.connect(self.load_image)
# 为保存按钮绑定点击事件,点击时调用save_image方法
save_btn.clicked.connect(self.save_image)
# 为还原按钮绑定点击事件,点击时调用restore_image方法
restore_btn.clicked.connect(self.restore_image)
# 将加载按钮添加到顶部布局
top_layout.addWidget(load_btn)
# 将保存按钮添加到顶部布局
top_layout.addWidget(save_btn)
# 将还原按钮添加到顶部布局
top_layout.addWidget(restore_btn)
# 在布局末尾添加一个拉伸项,使按钮靠左对齐
top_layout.addStretch()
# 将顶部布局添加到主布局
main_layout.addLayout(top_layout)
# 添加水平分割线
main_layout.addWidget(self._h_line())
# 创建用于显示图像的水平布局
img_layout = QHBoxLayout()
# 创建用于显示原始图像的标签
self.original_label = QLabel()
# 创建用于显示处理后图像的标签
self.processed_label = QLabel()
# 为原始图像和处理后图像的标签设置固定大小和对齐方式
for label in (self.original_label, self.processed_label):
label.setFixedSize(400, 400)
label.setAlignment(Qt.AlignmentFlag.AlignCenter)
# 将原始图像标签添加到图像布局
img_layout.addWidget(self.original_label)
# 添加垂直分割线
img_layout.addWidget(self._v_line())
# 将处理后图像标签添加到图像布局
img_layout.addWidget(self.processed_label)
# 设置布局中部件之间的间距为0
img_layout.setSpacing(0)
# 将图像布局添加到主布局
main_layout.addLayout(img_layout)
# 添加水平分割线
main_layout.addWidget(self._h_line())
# 创建底部水平布局
bottom_layout = QHBoxLayout()
# 定义一系列图像处理操作的按钮文本和对应的处理模式
for text, func in [("⚫灰度化", "gray"), ("🔍去噪", "denoise"),
("✨锐化", "sharpen"), ("🔄旋转", "rotate"),
("🔀反转", "flip"), ("🌫️模糊", "blur")]:
# 创建按钮
btn = QPushButton(text)
# 为按钮绑定点击事件,点击时调用process方法并传入对应的处理模式
btn.clicked.connect(lambda _, f=func: self.process(f))
# 将按钮添加到底部布局
bottom_layout.addWidget(btn)
# 在布局末尾添加一个拉伸项,使按钮靠左对齐
bottom_layout.addStretch()
# 将底部布局添加到主布局
main_layout.addLayout(bottom_layout)
# 创建水平分割线的方法
def _h_line(self):
line = QFrame()
line.setFrameShape(QFrame.Shape.HLine)
line.setFrameShadow(QFrame.Shadow.Sunken)
line.setStyleSheet("color: #ccc;")
return line
# 创建垂直分割线的方法
def _v_line(self):
line = QFrame()
line.setFrameShape(QFrame.Shape.VLine)
line.setFrameShadow(QFrame.Shadow.Sunken)
line.setStyleSheet("color: #ccc;")
return line
# 加载图像的方法
def load_image(self):
"""加载图像"""
# 打开文件选择对话框,让用户选择图片文件
file, _ = QFileDialog.getOpenFileName(self, "选择图片", "", "图片文件 (*.png *.jpg *.bmp)")
if file:
# 使用OpenCV读取用户选择的图片
img = cv2.imread(file)
if img is None:
# 如果无法加载图像,显示警告消息框
QMessageBox.warning(self, "错误", "无法加载图像")
return
# 存储原始图像的副本,用于后续的还原操作
self.original_image = img.copy()
# 存储原始图像到image_data字典中
self.image_data['original'] = img
# 存储处理后的图像,初始状态为原始图像的副本
self.image_data['processed'] = img.copy()
# 在原始图像标签上显示原始图像
self.show_image(img, self.original_label)
# 在处理后图像标签上显示初始的处理后图像(即原始图像)
self.show_image(img, self.processed_label)
# 保存图像的方法
def save_image(self):
"""保存图像"""
if 'processed' not in self.image_data:
# 如果没有处理后的图像,显示提示消息框
QMessageBox.warning(self, "提示", "没有可保存的图像")
return
# 打开文件保存对话框,让用户选择保存路径和文件格式
file, _ = QFileDialog.getSaveFileName(self, "保存图像", "", "PNG (*.png);;JPG (*.jpg)")
if file:
# 使用OpenCV将处理后的图像保存到指定文件
cv2.imwrite(file, self.image_data['processed'])
# 显示保存成功的消息框
QMessageBox.information(self, "成功", f"图像已保存:{file}")
# 根据选择的模式处理图像的方法
def process(self, mode):
"""根据选择的模式处理图像"""
if 'original' not in self.image_data:
# 如果没有加载原始图像,显示提示消息框
QMessageBox.warning(self, "提示", "请先加载图片")
return
# 获取上一次处理后的图像作为本次处理的输入
img = self.image_data['processed']
if mode == "gray": # 灰度化处理
# 将图像转换为灰度图
result = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 将灰度图转换回三通道图像,以便后续显示
result = cv2.cvtColor(result, cv2.COLOR_GRAY2BGR)
elif mode == "denoise": # 去噪处理
# 使用快速非局部均值去噪算法对彩色图像进行去噪
result = cv2.fastNlMeansDenoisingColored(img, None, 10, 10, 7, 21)
elif mode == "sharpen": # 锐化处理
# 定义锐化卷积核
kernel = np.array([[-1, -1, -1], [-1, 9, -1], [-1, -1, -1]])
# 使用卷积操作对图像进行锐化
result = cv2.filter2D(img, -1, kernel)
elif mode == "rotate": # 旋转处理
# 获取图像的行数和列数
rows, cols = img.shape[:2]
# 计算旋转矩阵,以图像中心为旋转点,旋转90度
M = cv2.getRotationMatrix2D((cols / 2, rows / 2), 90, 1)
# 应用仿射变换对图像进行旋转
result = cv2.warpAffine(img, M, (cols, rows))
elif mode == "flip": # 反转处理
# 对图像进行水平反转
result = cv2.flip(img, 1)
elif mode == "blur": # 模糊处理
# 使用高斯模糊对图像进行模糊处理
result = cv2.GaussianBlur(img, (5, 5), 0)
else:
return
# 存储处理后的图像到image_data字典中
self.image_data['processed'] = result
# 在处理后图像标签上显示处理后的图像
self.show_image(result, self.processed_label)
# 还原图像到初始状态的方法
def restore_image(self):
"""还原图像到初始状态"""
if self.original_image is not None:
# 将处理后的图像恢复为原始图像的副本
self.image_data['processed'] = self.original_image.copy()
# 在处理后图像标签上显示原始图像
self.show_image(self.original_image, self.processed_label)
# 显示图像的方法
def show_image(self, img, label):
"""显示图像"""
# 将OpenCV的BGR颜色空间转换为Qt的RGB颜色空间
rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# 获取图像的高度、宽度和通道数
h, w, ch = rgb.shape
# 计算每行的字节数
bytes_per_line = ch * w
# 将图像数据转换为QImage对象
q_img = QImage(rgb.data, w, h, bytes_per_line, QImage.Format.Format_RGB888)
# 将QImage对象转换为QPixmap对象,并按比例缩放后显示在指定的标签上
label.setPixmap(QPixmap.fromImage(q_img).scaled(400, 400, Qt.AspectRatioMode.KeepAspectRatio))
if __name__ == "__main__":
# 创建一个QApplication对象,用于管理应用程序的资源和事件循环
app = QApplication(sys.argv)
# 创建ImageProcessor类的实例,即主窗口
window = ImageProcessor()
# 显示主窗口
window.show()
# 进入应用程序的主事件循环,直到窗口关闭
sys.exit(app.exec())

4.0
从3.0的基础上再次增加各种功能
import sys
import cv2
import numpy as np
from PyQt5.QtWidgets import (
QApplication, QMainWindow, QWidget, QLabel, QPushButton,
QFileDialog, QMessageBox, QVBoxLayout, QHBoxLayout, QFrame,
QGridLayout, QCheckBox, QGroupBox, QScrollArea
)
from PyQt5.QtGui import QPixmap, QImage
from PyQt5.QtCore import Qt
class ImageProcessor(QMainWindow):
def __init__(self):
super().__init__()
# 设置窗口标题
self.setWindowTitle("PyQt图像处理器")
# 设置窗口初始大小
self.resize(900, 800)
# 存储原始图像和处理后的图像数据
self.image_data = {}
# 存储原始图像的副本,用于还原操作
self.original_image = None
# 创建主窗口的中心部件
main_widget = QWidget()
self.setCentralWidget(main_widget)
# 创建主布局,采用垂直布局
main_layout = QVBoxLayout(main_widget)
# 设置主窗口及部分子部件的样式
main_widget.setStyleSheet("""
QWidget {
background-color: #f0f4f8;
}
QLabel {
border: 2px solid #aaa;
border-radius: 10px;
background-color: white;
padding: 5px;
box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1);
}
QPushButton {
font-size: 15px;
padding: 8px 18px;
min-width: 100px;
}
QGroupBox {
border: 1px solid #aaa;
border-radius: 5px;
margin-top: 10px;
}
""")
# 创建顶部布局,包含加载、保存和还原按钮
top_layout = QHBoxLayout()
# 创建加载图片按钮
load_btn = QPushButton("📂 加载图片")
# 创建保存图像按钮
save_btn = QPushButton("💾 保存图像")
# 创建还原图像按钮
restore_btn = QPushButton("🔙 还原")
# 连接加载按钮的点击事件到load_image方法
load_btn.clicked.connect(self.load_image)
# 连接保存按钮的点击事件到save_image方法
save_btn.clicked.connect(self.save_image)
# 连接还原按钮的点击事件到restore_image方法
restore_btn.clicked.connect(self.restore_image)
# 将加载按钮添加到顶部布局
top_layout.addWidget(load_btn)
# 将保存按钮添加到顶部布局
top_layout.addWidget(save_btn)
# 将还原按钮添加到顶部布局
top_layout.addWidget(restore_btn)
# 在布局末尾添加拉伸项,使按钮靠左排列
top_layout.addStretch()
# 将顶部布局添加到主布局
main_layout.addLayout(top_layout)
# 添加水平分割线
main_layout.addWidget(self._h_line())
# 创建2x2的网格布局用于显示图片
self.img_grid_layout = QGridLayout()
# 存储用于显示图片的标签列表
self.image_labels = []
for i in range(2):
for j in range(2):
# 创建用于显示图片的标签
label = QLabel()
# 设置标签的固定大小
label.setFixedSize(400, 400)
# 设置标签内容居中显示
label.setAlignment(Qt.AlignmentFlag.AlignCenter)
# 将标签添加到网格布局中
self.img_grid_layout.addWidget(label, i, j)
# 将标签添加到标签列表
self.image_labels.append(label)
# 将图片网格布局添加到主布局
main_layout.addLayout(self.img_grid_layout)
# 添加水平分割线
main_layout.addWidget(self._h_line())
# 创建用于控制图片框显示或隐藏的复选框布局
self.show_checkboxes = []
checkbox_layout = QHBoxLayout()
for i in range(4):
# 创建复选框
checkbox = QCheckBox(f"显示图片框 {i + 1}")
# 默认选中复选框
checkbox.setChecked(True)
# 连接复选框状态改变事件到toggle_image_display方法
checkbox.stateChanged.connect(lambda state, idx=i: self.toggle_image_display(idx, state))
# 将复选框添加到复选框布局
checkbox_layout.addWidget(checkbox)
# 将复选框添加到复选框列表
self.show_checkboxes.append(checkbox)
# 将复选框布局添加到主布局
main_layout.addLayout(checkbox_layout)
# 添加水平分割线
main_layout.addWidget(self._h_line())
# 创建功能分类布局
self.category_layout = QHBoxLayout()
# 存储每个类别对应的展开/收起按钮
self.category_buttons = {}
# 存储每个类别对应的功能按钮布局
self.function_layouts = {}
# 定义功能类别及其包含的具体功能
categories = {
"色彩调整": [("⚫灰度化", "gray"), ("🌇色调调整", "hue"), ("📊对比度调整", "contrast")],
"滤波处理": [("🔍去噪", "denoise"), ("🌫️模糊", "blur"), ("✨锐化", "sharpen")],
"几何变换": [("🔄旋转", "rotate"), ("📏缩放", "scale"), ("🖼️裁剪", "crop"), ("🔀反转", "flip")],
"形态学操作": [("🟩腐蚀", "erode"), ("🟨膨胀", "dilate"), ("🌪️开运算", "opening"), ("🌊闭运算", "closing")]
}
for category, functions in categories.items():
# 创建类别分组框
group_box = QGroupBox(category)
# 创建该类别下功能按钮的垂直布局
function_layout = QVBoxLayout()
# 存储该类别对应的功能按钮布局
self.function_layouts[category] = function_layout
# 创建展开/收起该类别功能按钮的按钮
category_btn = QPushButton(f"展开 {category}")
# 连接按钮点击事件到toggle_category方法
category_btn.clicked.connect(lambda _, cat=category: self.toggle_category(cat))
# 存储该类别对应的展开/收起按钮
self.category_buttons[category] = category_btn
for text, func in functions:
# 创建功能按钮
btn = QPushButton(text)
# 连接按钮点击事件到process方法
btn.clicked.connect(lambda _, f=func: self.process(f))
# 将功能按钮添加到功能按钮布局
function_layout.addWidget(btn)
# 将功能按钮布局设置到分组框中
group_box.setLayout(function_layout)
# 将展开/收起按钮添加到功能分类布局
self.category_layout.addWidget(category_btn)
# 将分组框添加到功能分类布局
self.category_layout.addWidget(group_box)
# 创建滚动区域,用于显示功能分类布局
scroll_area = QScrollArea()
# 设置滚动区域可调整大小
scroll_area.setWidgetResizable(True)
# 创建滚动区域内的部件
scroll_widget = QWidget()
# 将功能分类布局设置到滚动区域内的部件中
scroll_widget.setLayout(self.category_layout)
# 将滚动区域内的部件设置到滚动区域中
scroll_area.setWidget(scroll_widget)
# 将滚动区域添加到主布局
main_layout.addWidget(scroll_area)
def _h_line(self):
"""创建水平分割线"""
line = QFrame()
line.setFrameShape(QFrame.Shape.HLine)
line.setFrameShadow(QFrame.Shadow.Sunken)
line.setStyleSheet("color: #ccc;")
return line
def _v_line(self):
"""创建垂直分割线"""
line = QFrame()
line.setFrameShape(QFrame.Shape.VLine)
line.setFrameShadow(QFrame.Shadow.Sunken)
line.setStyleSheet("color: #ccc;")
return line
def load_image(self):
"""加载图像"""
# 打开文件选择对话框,让用户选择图片文件
file, _ = QFileDialog.getOpenFileName(self, "选择图片", "", "图片文件 (*.png *.jpg *.bmp)")
if file:
# 读取用户选择的图片文件
img = cv2.imread(file)
if img is None:
# 若无法加载图像,显示警告消息框
QMessageBox.warning(self, "错误", "无法加载图像")
return
# 存储原始图像的副本,用于后续还原操作
self.original_image = img.copy()
# 存储原始图像数据
self.image_data['original'] = img
# 存储处理后的图像数据,初始为原始图像副本
self.image_data['processed'] = img.copy()
# 在第一个图片框显示原始图像
self.show_image(img, self.image_labels[0])
# 在第二个图片框显示处理后的图像(初始为原始图像)
self.show_image(img, self.image_labels[1])
def save_image(self):
"""保存图像"""
if 'processed' not in self.image_data:
# 若没有处理后的图像,显示提示消息框
QMessageBox.warning(self, "提示", "没有可保存的图像")
return
# 打开文件保存对话框,让用户选择保存路径和文件格式
file, _ = QFileDialog.getSaveFileName(self, "保存图像", "", "PNG (*.png);;JPG (*.jpg)")
if file:
# 保存处理后的图像到指定文件
cv2.imwrite(file, self.image_data['processed'])
# 显示保存成功的消息框
QMessageBox.information(self, "成功", f"图像已保存:{file}")
def process(self, mode):
"""根据选择的模式处理图像"""
if 'original' not in self.image_data:
# 若没有加载原始图像,显示提示消息框
QMessageBox.warning(self, "提示", "请先加载图片")
return
# 获取上一次处理后的图像
img = self.image_data['processed']
if mode == "gray": # 灰度化处理
# 将图像转换为灰度图
result = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 将灰度图转换回三通道图像,以便后续显示
result = cv2.cvtColor(result, cv2.COLOR_GRAY2BGR)
elif mode == "hue": # 色调调整
# 将图像转换为HSV颜色空间
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# 调整色调值
hsv[:, :, 0] = (hsv[:, :, 0] + 10) % 180
# 将HSV图像转换回BGR颜色空间
result = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)
elif mode == "contrast": # 对比度调整
# 设置对比度调整系数
alpha = 1.5
# 设置亮度调整系数
beta = 0
# 调整图像的对比度和亮度
result = cv2.convertScaleAbs(img, alpha=alpha, beta=beta)
elif mode == "denoise": # 去噪处理
# 使用快速非局部均值去噪算法对彩色图像进行去噪
result = cv2.fastNlMeansDenoisingColored(img, None, 10, 10, 7, 21)
elif mode == "blur": # 模糊处理
# 使用高斯模糊对图像进行模糊处理
result = cv2.GaussianBlur(img, (5, 5), 0)
elif mode == "sharpen": # 锐化处理
# 定义锐化卷积核
kernel = np.array([[-1, -1, -1], [-1, 9, -1], [-1, -1, -1]])
# 使用卷积操作对图像进行锐化
result = cv2.filter2D(img, -1, kernel)
elif mode == "rotate": # 旋转处理
# 获取图像的行数和列数
rows, cols = img.shape[:2]
# 计算旋转矩阵,以图像中心为旋转点,旋转90度
M = cv2.getRotationMatrix2D((cols / 2, rows / 2), 90, 1)
# 应用仿射变换对图像进行旋转
result = cv2.warpAffine(img, M, (cols, rows))
elif mode == "scale": # 缩放处理
# 对图像进行缩放操作,缩小为原来的0.5倍
result = cv2.resize(img, (int(img.shape[1] * 0.5), int(img.shape[0] * 0.5)))
elif mode == "crop": # 裁剪处理
# 简单示例:裁剪图像的一部分
result = img[100:300, 100:300]
elif mode == "flip": # 反转处理
# 对图像进行水平反转
result = cv2.flip(img, 1)
elif mode == "erode": # 腐蚀操作
# 定义腐蚀核
kernel = np.ones((5, 5), np.uint8)
# 对图像进行腐蚀操作
result = cv2.erode(img, kernel, iterations=1)
elif mode == "dilate": # 膨胀操作
# 定义膨胀核
kernel = np.ones((5, 5), np.uint8)
# 对图像进行膨胀操作
result = cv2.dilate(img, kernel, iterations=1)
elif mode == "opening": # 开运算
# 定义开运算核
kernel = np.ones((5, 5), np.uint8)
# 对图像进行开运算
result = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
elif mode == "closing": # 闭运算
# 定义闭运算核
kernel = np.ones((5, 5), np.uint8)
# 对图像进行闭运算
result = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
else:
return
# 存储处理后的图像
self.image_data['processed'] = result
# 在第二个图片框显示处理后的图像
self.show_image(result, self.image_labels[1])
# 在第三个图片框显示处理后的图像
self.show_image(result, self.image_labels[2])
# 在第四个图片框显示处理后的图像
self.show_image(result, self.image_labels[3])
def restore_image(self):
"""还原图像到初始状态"""
if self.original_image is not None:
# 将处理后的图像恢复为原始图像的副本
self.image_data['processed'] = self.original_image.copy()
# 在第二个图片框显示原始图像
self.show_image(self.original_image, self.image_labels[1])
# 在第三个图片框显示原始图像
self.show_image(self.original_image, self.image_labels[2])
# 在第四个图片框显示原始图像
self.show_image(self.original_image, self.image_labels[3])
def show_image(self, img, label):
"""显示图像"""
# 将OpenCV的BGR颜色空间转换为Qt的RGB颜色空间
rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# 获取图像的高度、宽度和通道数
h, w, ch = rgb.shape
# 计算每行的字节数
bytes_per_line = ch * w
# 将图像数据转换为QImage对象
q_img = QImage(rgb.data, w, h, bytes_per_line, QImage.Format.Format_RGB888)
# 将QImage对象转换为QPixmap对象,并按比例缩放后显示在指定标签上
label.setPixmap(QPixmap.fromImage(q_img).scaled(400, 400, Qt.AspectRatioMode.KeepAspectRatio))
def toggle_image_display(self, index, state):
"""隐藏/显示图片框"""
if state == Qt.Checked:
# 若复选框选中,显示对应的图片框
self.image_labels[index].show()
else:
# 若复选框未选中,隐藏对应的图片框
self.image_labels[index].hide()
def toggle_category(self, category):
"""展开或收起功能类别"""
layout = self.function_layouts[category]
btn = self.category_buttons[category]
if layout.count() > 0:
# 若布局中有子部件,收起该类别功能按钮
for i in reversed(range(layout.count())):
widget = layout.itemAt(i).widget()
if widget:
# 移除子部件
widget.setParent(None)
btn.setText(f"展开 {category}")
else:
# 若布局中没有子部件,展开该类别功能按钮
functions = self.get_functions_by_category(category)
for func in functions:
# 添加子部件
layout.addWidget(func)
btn.setText(f"收起 {category}")
def get_functions_by_category(self, category):
"""根据类别获取功能按钮列表"""
functions = []
layout = self.function_layouts[category]
for i in range(layout.count()):
widget = layout.itemAt(i).widget()
if widget:
functions.append(widget)
return functions
if __name__ == "__main__":
# 创建应用程序对象
app = QApplication(sys.argv)
# 创建图像处理器窗口对象
window = ImageProcessor()
# 显示窗口
window.show()
# 进入应用程序的主事件循环
sys.exit(app.exec())

5.0
我们发现4.0的效果有点不好看,所以我们调整了一下布局,形成了接下来好看的界面
# 使用PyQt5和OpenCV实现一个简单的图像处理系统界面
import sys
import cv2
import numpy as np
import scipy as sp
from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel, QPushButton, QVBoxLayout, QWidget, QFileDialog, QAction, \
QComboBox, QHBoxLayout
from PyQt5.QtGui import QPixmap, QImage, QLinearGradient, QBrush, QPainter, QColor
from PyQt5.QtCore import Qt
class ImageProcessingApp(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("图像处理系统")
self.setGeometry(100, 100, 1220, 725) # 设置窗口位置和大小
# 创建中心部件
self.central_widget = QWidget()
self.setCentralWidget(self.central_widget)
# 创建布局
self.main_layout = QVBoxLayout(self.central_widget)
# 创建按钮布局(顶部)
self.button_layout = QHBoxLayout()
# 设置按钮的固定大小
button_size = (150, 30)
# 添加控件到按钮布局
# 加载图像按钮
# 添加控件到按钮布局
# 加载图像按钮
self.load_button = QPushButton("📂 加载图片", self)
self.load_button.setFixedSize(*button_size)
self.button_layout.addWidget(self.load_button)
self.load_button.clicked.connect(self.load_image)
# 色彩调整下拉菜单
self.color_combo = QComboBox(self)
self.color_combo.addItem("⚫ 灰度化")
self.color_combo.addItem("🌇 色调调整")
self.color_combo.addItem("📊 对比度调整")
self.color_combo.setFixedSize(*button_size)
self.button_layout.addWidget(self.color_combo)
self.color_combo.currentIndexChanged.connect(self.change_color_operation)
# 滤波处理下拉菜单
self.filter_combo = QComboBox(self)
self.filter_combo.addItem("🔍 去噪")
self.filter_combo.addItem("🌫️ 模糊")
self.filter_combo.addItem("✨ 锐化")
self.filter_combo.setFixedSize(*button_size)
self.button_layout.addWidget(self.filter_combo)
self.filter_combo.currentIndexChanged.connect(self.change_filter_operation)
# 几何变换下拉菜单
self.geo_combo = QComboBox(self)
self.geo_combo.addItem("🔄 旋转")
self.geo_combo.addItem("📏 缩放")
self.geo_combo.addItem("🖼️ 裁剪")
self.geo_combo.addItem("🔀 反转")
self.geo_combo.setFixedSize(*button_size)
self.button_layout.addWidget(self.geo_combo)
self.geo_combo.currentIndexChanged.connect(self.change_geo_operation)
# 形态学变换下拉菜单
self.morph_combo = QComboBox(self)
self.morph_combo.addItem("🟩 腐蚀")
self.morph_combo.addItem("🟨 膨胀")
self.morph_combo.addItem("🌪️ 开运算")
self.morph_combo.addItem("🌊 闭运算")
self.morph_combo.setFixedSize(*button_size)
self.button_layout.addWidget(self.morph_combo)
self.morph_combo.currentIndexChanged.connect(self.change_morph_operation)
# 复原按钮
self.restore_button = QPushButton("🔙 还原", self)
self.restore_button.setFixedSize(*button_size)
self.button_layout.addWidget(self.restore_button)
self.restore_button.clicked.connect(self.restore_image)
# 保存图像按钮
self.save_button = QPushButton("💾 保存图像", self)
self.save_button.setFixedSize(*button_size)
self.button_layout.addWidget(self.save_button)
self.save_button.clicked.connect(self.save_processed_image)
# 将按钮布局添加到主布局
self.main_layout.addLayout(self.button_layout)
# 创建水平布局用于显示原始图像和处理后的图像
self.image_layout = QHBoxLayout()
# 创建标签用于显示原始图像
self.original_label = QLabel("原始图像", self)
self.original_label.setAlignment(Qt.AlignCenter)
self.original_label.setStyleSheet(
"QLabel { background-color: rgb(238, 242, 255); border-radius: 15px; min-height: 200px; min-width: 200px; }"
)
self.image_layout.addWidget(self.original_label)
# 创建标签用于显示处理后的图像
self.processed_label = QLabel("处理后的图像", self)
self.processed_label.setAlignment(Qt.AlignCenter)
self.processed_label.setStyleSheet(
"QLabel { background-color: rgb(238, 242, 255); border-radius: 15px; min-height: 200px; min-width: 200px; }"
)
self.image_layout.addWidget(self.processed_label)
# 将图像布局添加到主布局
self.main_layout.addLayout(self.image_layout)
# 初始化图像变量
self.original_image = None
self.processed_image = None
def paintEvent(self, event):
"""绘制渐变背景"""
painter = QPainter(self)
painter.begin(self)
gradient = QLinearGradient(0, 0, 0, self.height())
gradient.setColorAt(0, QColor(107, 128, 210))
gradient.setColorAt(1, QColor(180, 140, 255))
painter.fillRect(self.rect(), QBrush(gradient))
painter.end()
def load_image(self):
"""加载图像"""
file_path, _ = QFileDialog.getOpenFileName(self, "选择图像文件", "", "Image Files (*.png *.jpg *.bmp *.gif)")
if file_path:
# 使用 OpenCV 加载图像
self.original_image = cv2.imread(file_path)
if self.original_image is not None:
# 将 OpenCV 图像转换为 QPixmap 并显示
self.display_image(self.original_image, self.original_label)
self.processed_image = self.original_image.copy()
self.display_image(self.processed_image, self.processed_label)
def change_color_operation(self, index):
"""根据选择的色彩调整操作进行处理"""
if self.processed_image is not None:
if index == 0: # 灰度化
self.processed_image = cv2.cvtColor(self.processed_image, cv2.COLOR_BGR2GRAY)
elif index == 1: # 色调调整
self.processed_image = cv2.cvtColor(self.processed_image, cv2.COLOR_BGR2HSV)
self.processed_image[:, :, 0] = (self.processed_image[:, :, 0] * 1.2) % 180
self.processed_image = cv2.cvtColor(self.processed_image, cv2.COLOR_HSV2BGR)
elif index == 2: # 对比度调整
alpha = 1.5 # 对比度
beta = 30 # 亮度
self.processed_image = cv2.convertScaleAbs(self.processed_image, alpha=alpha, beta=beta)
self.display_image(self.processed_image, self.processed_label)
def change_filter_operation(self, index):
"""根据选择的滤波操作进行处理"""
if self.processed_image is not None:
if index == 0: # 去噪
self.processed_image = cv2.medianBlur(self.processed_image, 3)
elif index == 1: # 模糊
self.processed_image = cv2.GaussianBlur(self.processed_image, (5, 5), 0)
elif index == 2: # 锐化
kernel = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]])
self.processed_image = cv2.filter2D(self.processed_image, -1, kernel)
self.display_image(self.processed_image, self.processed_label)
def change_geo_operation(self, index):
"""根据选择的几何变换操作进行处理"""
if self.processed_image is not None:
if index == 0: # 旋转
(h, w) = self.processed_image.shape[:2]
center = (w // 2, h // 2)
M = cv2.getRotationMatrix2D(center, 45, 1.0)
self.processed_image = cv2.warpAffine(self.processed_image, M, (w, h))
elif index == 1: # 缩放
self.processed_image = cv2.resize(
self.processed_image,
(int(self.processed_image.shape[1] * 0.5), int(self.processed_image.shape[0] * 0.5)),
interpolation=cv2.INTER_LINEAR,
)
elif index == 2: # 裁剪
(h, w) = self.processed_image.shape[:2]
self.processed_image = self.processed_image[50:h - 50, 50:w - 50]
elif index == 3: # 反转
self.processed_image = cv2.flip(self.processed_image, 1) # 水平翻转
self.display_image(self.processed_image, self.processed_label)
def change_morph_operation(self, index):
"""根据选择的形态学操作进行处理"""
if self.processed_image is not None:
kernel = np.ones((3, 3), np.uint8)
if index == 0: # 腐蚀
self.processed_image = cv2.erode(self.processed_image, kernel, iterations=1)
elif index == 1: # 膨胀
self.processed_image = cv2.dilate(self.processed_image, kernel, iterations=1)
elif index == 2: # 开运算
self.processed_image = cv2.morphologyEx(self.processed_image, cv2.MORPH_OPEN, kernel)
elif index == 3: # 闭运算
self.processed_image = cv2.morphologyEx(self.processed_image, cv2.MORPH_CLOSE, kernel)
self.display_image(self.processed_image, self.processed_label)
def restore_image(self):
"""复原图像"""
if self.original_image is not None:
self.processed_image = self.original_image.copy()
self.display_image(self.processed_image, self.processed_label)
def save_processed_image(self):
"""保存处理后的图像"""
if self.processed_image is not None:
file_path, _ = QFileDialog.getSaveFileName(self, "保存图像文件", "",
"Image Files (*.png *.jpg *.bmp *.gif)")
if file_path:
cv2.imwrite(file_path, self.processed_image)
def display_image(self, cv_image, label):
"""将 OpenCV 图像转换为 QPixmap 并显示"""
if len(cv_image.shape) == 2: # 灰度图像
image_format = QImage.Format_Grayscale8
else: # 彩色图像
image_format = QImage.Format_BGR888
height, width = cv_image.shape[:2]
qt_image = QImage(cv_image, width, height, cv_image.strides[0], image_format)
pixmap = QPixmap.fromImage(qt_image)
label.setPixmap(pixmap.scaled(label.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation))
if __name__ == "__main__":
app = QApplication(sys.argv)
window = ImageProcessingApp()
window.show()
sys.exit(app.exec_())

基于yolov8的pyqt5界面
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'UiMain.ui'
#
# Created by: PyQt5 UI code generator 5.15.9
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(1250, 830)
MainWindow.setMinimumSize(QtCore.QSize(1250, 830))
MainWindow.setMaximumSize(QtCore.QSize(1250, 830))
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(":/icons/ui_imgs/icons/目标检测.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
MainWindow.setWindowIcon(icon)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.frame = QtWidgets.QFrame(self.centralwidget)
self.frame.setGeometry(QtCore.QRect(10, 100, 791, 711))
self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame.setObjectName("frame")
self.frame_2 = QtWidgets.QFrame(self.frame)
self.frame_2.setGeometry(QtCore.QRect(10, 0, 771, 481))
self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame_2.setObjectName("frame_2")
# 在 setupUi 方法中,找到 label_show 的设置部分
self.label_show = QtWidgets.QLabel(self.frame_2)
self.label_show.setGeometry(QtCore.QRect(0, 0, 770, 480))
self.label_show.setMinimumSize(QtCore.QSize(770, 480))
self.label_show.setMaximumSize(QtCore.QSize(770, 480))
# 动态加载图片
self.label_show.setPixmap(QtGui.QPixmap(r"E:\robot\UIProgram\ui_imgs\12.png"))
self.label_show.setScaledContents(True) # 确保图片适应标签大小
self.label_show.setText("")
self.label_show.setObjectName("label_show")
self.PiclineEdit = QtWidgets.QLineEdit(self.frame_2)
self.PiclineEdit.setGeometry(QtCore.QRect(350, 260, 20, 20))
self.PiclineEdit.setInputMask("")
self.PiclineEdit.setObjectName("PiclineEdit")
self.VideolineEdit = QtWidgets.QLineEdit(self.frame_2)
self.VideolineEdit.setGeometry(QtCore.QRect(360, 260, 20, 20))
self.VideolineEdit.setObjectName("VideolineEdit")
self.CaplineEdit = QtWidgets.QLineEdit(self.frame_2)
self.CaplineEdit.setGeometry(QtCore.QRect(350, 260, 20, 20))
self.CaplineEdit.setObjectName("CaplineEdit")
self.CaplineEdit.raise_()
self.VideolineEdit.raise_()
self.PiclineEdit.raise_()
self.label_show.raise_()
self.frame_3 = QtWidgets.QFrame(self.frame)
self.frame_3.setGeometry(QtCore.QRect(10, 480, 771, 221))
self.frame_3.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_3.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame_3.setObjectName("frame_3")
self.groupBox_3 = QtWidgets.QGroupBox(self.frame_3)
self.groupBox_3.setGeometry(QtCore.QRect(0, 10, 771, 221))
font = QtGui.QFont()
font.setFamily("华文楷体")
font.setPointSize(16)
self.groupBox_3.setFont(font)
self.groupBox_3.setObjectName("groupBox_3")
self.tableWidget = QtWidgets.QTableWidget(self.groupBox_3)
self.tableWidget.setGeometry(QtCore.QRect(10, 30, 751, 181))
font = QtGui.QFont()
font.setFamily("华文楷体")
font.setPointSize(14)
self.tableWidget.setFont(font)
self.tableWidget.setObjectName("tableWidget")
self.tableWidget.setColumnCount(5)
self.tableWidget.setRowCount(0)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(0, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(1, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(2, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(3, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(4, item)
self.frame_4 = QtWidgets.QFrame(self.centralwidget)
self.frame_4.setGeometry(QtCore.QRect(810, 100, 431, 711))
self.frame_4.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_4.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame_4.setObjectName("frame_4")
self.groupBox = QtWidgets.QGroupBox(self.frame_4)
self.groupBox.setGeometry(QtCore.QRect(0, 0, 431, 111))
font = QtGui.QFont()
font.setFamily("华文楷体")
font.setPointSize(16)
self.groupBox.setFont(font)
self.groupBox.setObjectName("groupBox")
self.checkBox = QtWidgets.QCheckBox(self.groupBox)
self.checkBox.setGeometry(QtCore.QRect(10, 80, 411, 16))
font = QtGui.QFont()
font.setFamily("华文楷体")
font.setPointSize(12)
self.checkBox.setFont(font)
self.checkBox.setObjectName("checkBox")
self.horizontalLayoutWidget = QtWidgets.QWidget(self.groupBox)
self.horizontalLayoutWidget.setGeometry(QtCore.QRect(10, 30, 191, 31))
self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget")
self.horizontalLayout_10 = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget)
self.horizontalLayout_10.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_10.setObjectName("horizontalLayout_10")
self.label_14 = QtWidgets.QLabel(self.horizontalLayoutWidget)
font = QtGui.QFont()
font.setFamily("楷体")
font.setPointSize(12)
self.label_14.setFont(font)
self.label_14.setLineWidth(2)
self.label_14.setObjectName("label_14")
self.horizontalLayout_10.addWidget(self.label_14)
self.doubleSpinBox = QtWidgets.QDoubleSpinBox(self.horizontalLayoutWidget)
font = QtGui.QFont()
font.setFamily("华文楷体")
font.setPointSize(12)
self.doubleSpinBox.setFont(font)
self.doubleSpinBox.setDecimals(2)
self.doubleSpinBox.setObjectName("doubleSpinBox")
self.horizontalLayout_10.addWidget(self.doubleSpinBox)
self.horizontalLayoutWidget_2 = QtWidgets.QWidget(self.groupBox)
self.horizontalLayoutWidget_2.setGeometry(QtCore.QRect(230, 30, 191, 31))
self.horizontalLayoutWidget_2.setObjectName("horizontalLayoutWidget_2")
self.horizontalLayout_11 = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget_2)
self.horizontalLayout_11.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_11.setObjectName("horizontalLayout_11")
self.label_15 = QtWidgets.QLabel(self.horizontalLayoutWidget_2)
font = QtGui.QFont()
font.setFamily("楷体")
font.setPointSize(12)
self.label_15.setFont(font)
self.label_15.setObjectName("label_15")
self.horizontalLayout_11.addWidget(self.label_15)
self.doubleSpinBox_2 = QtWidgets.QDoubleSpinBox(self.horizontalLayoutWidget_2)
font = QtGui.QFont()
font.setFamily("华文楷体")
font.setPointSize(12)
self.doubleSpinBox_2.setFont(font)
self.doubleSpinBox_2.setObjectName("doubleSpinBox_2")
self.horizontalLayout_11.addWidget(self.doubleSpinBox_2)
self.groupBox_2 = QtWidgets.QGroupBox(self.frame_4)
self.groupBox_2.setGeometry(QtCore.QRect(0, 120, 431, 371))
font = QtGui.QFont()
font.setFamily("华文楷体")
font.setPointSize(16)
self.groupBox_2.setFont(font)
self.groupBox_2.setObjectName("groupBox_2")
self.frame_6 = QtWidgets.QFrame(self.groupBox_2)
self.frame_6.setGeometry(QtCore.QRect(0, 190, 431, 171))
self.frame_6.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_6.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame_6.setObjectName("frame_6")
self.label_4 = QtWidgets.QLabel(self.frame_6)
self.label_4.setGeometry(QtCore.QRect(10, 10, 131, 41))
font = QtGui.QFont()
font.setFamily("华文楷体")
font.setPointSize(16)
self.label_4.setFont(font)
self.label_4.setStyleSheet("")
self.label_4.setObjectName("label_4")
self.layoutWidget = QtWidgets.QWidget(self.frame_6)
self.layoutWidget.setGeometry(QtCore.QRect(20, 60, 161, 37))
self.layoutWidget.setObjectName("layoutWidget")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.layoutWidget)
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout.setObjectName("horizontalLayout")
self.label_6 = QtWidgets.QLabel(self.layoutWidget)
font = QtGui.QFont()
font.setFamily("华文楷体")
font.setPointSize(16)
font.setBold(False)
font.setWeight(50)
self.label_6.setFont(font)
self.label_6.setObjectName("label_6")
self.horizontalLayout.addWidget(self.label_6)
self.label_xmin = QtWidgets.QLabel(self.layoutWidget)
palette = QtGui.QPalette()
brush = QtGui.QBrush(QtGui.QColor(255, 0, 0))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.WindowText, brush)
brush = QtGui.QBrush(QtGui.QColor(255, 0, 0))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.WindowText, brush)
brush = QtGui.QBrush(QtGui.QColor(120, 120, 120))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.WindowText, brush)
self.label_xmin.setPalette(palette)
font = QtGui.QFont()
font.setFamily("Arial")
font.setPointSize(16)
font.setBold(True)
font.setWeight(75)
self.label_xmin.setFont(font)
self.label_xmin.setText("")
self.label_xmin.setObjectName("label_xmin")
self.horizontalLayout.addWidget(self.label_xmin)
self.layoutWidget1 = QtWidgets.QWidget(self.frame_6)
self.layoutWidget1.setGeometry(QtCore.QRect(210, 60, 161, 37))
self.layoutWidget1.setObjectName("layoutWidget1")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.layoutWidget1)
self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.label_8 = QtWidgets.QLabel(self.layoutWidget1)
self.label_8.setObjectName("label_8")
self.horizontalLayout_2.addWidget(self.label_8)
self.label_ymin = QtWidgets.QLabel(self.layoutWidget1)
palette = QtGui.QPalette()
brush = QtGui.QBrush(QtGui.QColor(255, 0, 0))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.WindowText, brush)
brush = QtGui.QBrush(QtGui.QColor(255, 0, 0))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.WindowText, brush)
brush = QtGui.QBrush(QtGui.QColor(120, 120, 120))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.WindowText, brush)
self.label_ymin.setPalette(palette)
font = QtGui.QFont()
font.setFamily("Arial")
font.setPointSize(16)
font.setBold(True)
font.setWeight(75)
self.label_ymin.setFont(font)
self.label_ymin.setText("")
self.label_ymin.setObjectName("label_ymin")
self.horizontalLayout_2.addWidget(self.label_ymin)
self.layoutWidget2 = QtWidgets.QWidget(self.frame_6)
self.layoutWidget2.setGeometry(QtCore.QRect(20, 120, 161, 37))
self.layoutWidget2.setObjectName("layoutWidget2")
self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.layoutWidget2)
self.horizontalLayout_3.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
self.label_7 = QtWidgets.QLabel(self.layoutWidget2)
self.label_7.setObjectName("label_7")
self.horizontalLayout_3.addWidget(self.label_7)
self.label_xmax = QtWidgets.QLabel(self.layoutWidget2)
palette = QtGui.QPalette()
brush = QtGui.QBrush(QtGui.QColor(255, 0, 0))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.WindowText, brush)
brush = QtGui.QBrush(QtGui.QColor(255, 0, 0))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.WindowText, brush)
brush = QtGui.QBrush(QtGui.QColor(120, 120, 120))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.WindowText, brush)
self.label_xmax.setPalette(palette)
font = QtGui.QFont()
font.setFamily("Arial")
font.setPointSize(16)
font.setBold(True)
font.setWeight(75)
self.label_xmax.setFont(font)
self.label_xmax.setText("")
self.label_xmax.setObjectName("label_xmax")
self.horizontalLayout_3.addWidget(self.label_xmax)
self.layoutWidget3 = QtWidgets.QWidget(self.frame_6)
self.layoutWidget3.setGeometry(QtCore.QRect(210, 120, 161, 37))
self.layoutWidget3.setObjectName("layoutWidget3")
self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.layoutWidget3)
self.horizontalLayout_4.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_4.setObjectName("horizontalLayout_4")
self.label_9 = QtWidgets.QLabel(self.layoutWidget3)
self.label_9.setObjectName("label_9")
self.horizontalLayout_4.addWidget(self.label_9)
self.label_ymax = QtWidgets.QLabel(self.layoutWidget3)
palette = QtGui.QPalette()
brush = QtGui.QBrush(QtGui.QColor(255, 0, 0))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.WindowText, brush)
brush = QtGui.QBrush(QtGui.QColor(255, 0, 0))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.WindowText, brush)
brush = QtGui.QBrush(QtGui.QColor(120, 120, 120))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.WindowText, brush)
self.label_ymax.setPalette(palette)
font = QtGui.QFont()
font.setFamily("Arial")
font.setPointSize(16)
font.setBold(True)
font.setWeight(75)
self.label_ymax.setFont(font)
self.label_ymax.setText("")
self.label_ymax.setObjectName("label_ymax")
self.horizontalLayout_4.addWidget(self.label_ymax)
self.layoutWidget4 = QtWidgets.QWidget(self.groupBox_2)
self.layoutWidget4.setGeometry(QtCore.QRect(208, 40, 211, 37))
self.layoutWidget4.setObjectName("layoutWidget4")
self.horizontalLayout_5 = QtWidgets.QHBoxLayout(self.layoutWidget4)
self.horizontalLayout_5.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_5.setObjectName("horizontalLayout_5")
self.label = QtWidgets.QLabel(self.layoutWidget4)
self.label.setObjectName("label")
self.horizontalLayout_5.addWidget(self.label)
self.label_nums = QtWidgets.QLabel(self.layoutWidget4)
palette = QtGui.QPalette()
brush = QtGui.QBrush(QtGui.QColor(255, 0, 0))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.WindowText, brush)
brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Text, brush)
brush = QtGui.QBrush(QtGui.QColor(255, 0, 0, 128))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.PlaceholderText, brush)
brush = QtGui.QBrush(QtGui.QColor(255, 0, 0))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.WindowText, brush)
brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Text, brush)
brush = QtGui.QBrush(QtGui.QColor(255, 0, 0, 128))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.PlaceholderText, brush)
brush = QtGui.QBrush(QtGui.QColor(120, 120, 120))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.WindowText, brush)
brush = QtGui.QBrush(QtGui.QColor(120, 120, 120))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Text, brush)
brush = QtGui.QBrush(QtGui.QColor(0, 0, 0, 128))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.PlaceholderText, brush)
self.label_nums.setPalette(palette)
font = QtGui.QFont()
font.setFamily("Arial")
font.setPointSize(16)
font.setBold(True)
font.setWeight(75)
self.label_nums.setFont(font)
self.label_nums.setText("")
self.label_nums.setObjectName("label_nums")
self.horizontalLayout_5.addWidget(self.label_nums)
self.layoutWidget5 = QtWidgets.QWidget(self.groupBox_2)
self.layoutWidget5.setGeometry(QtCore.QRect(10, 90, 291, 38))
self.layoutWidget5.setObjectName("layoutWidget5")
self.horizontalLayout_6 = QtWidgets.QHBoxLayout(self.layoutWidget5)
self.horizontalLayout_6.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_6.setObjectName("horizontalLayout_6")
self.label_5 = QtWidgets.QLabel(self.layoutWidget5)
self.label_5.setObjectName("label_5")
self.horizontalLayout_6.addWidget(self.label_5)
self.comboBox = QtWidgets.QComboBox(self.layoutWidget5)
self.comboBox.setObjectName("comboBox")
self.horizontalLayout_6.addWidget(self.comboBox)
self.layoutWidget_2 = QtWidgets.QWidget(self.groupBox_2)
self.layoutWidget_2.setGeometry(QtCore.QRect(10, 40, 171, 37))
self.layoutWidget_2.setObjectName("layoutWidget_2")
self.horizontalLayout_7 = QtWidgets.QHBoxLayout(self.layoutWidget_2)
self.horizontalLayout_7.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_7.setObjectName("horizontalLayout_7")
self.label_10 = QtWidgets.QLabel(self.layoutWidget_2)
self.label_10.setObjectName("label_10")
self.horizontalLayout_7.addWidget(self.label_10)
self.time_lb = QtWidgets.QLabel(self.layoutWidget_2)
palette = QtGui.QPalette()
brush = QtGui.QBrush(QtGui.QColor(255, 0, 0))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.WindowText, brush)
brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Text, brush)
brush = QtGui.QBrush(QtGui.QColor(255, 0, 0, 128))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.PlaceholderText, brush)
brush = QtGui.QBrush(QtGui.QColor(255, 0, 0))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.WindowText, brush)
brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Text, brush)
brush = QtGui.QBrush(QtGui.QColor(255, 0, 0, 128))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.PlaceholderText, brush)
brush = QtGui.QBrush(QtGui.QColor(120, 120, 120))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.WindowText, brush)
brush = QtGui.QBrush(QtGui.QColor(120, 120, 120))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Text, brush)
brush = QtGui.QBrush(QtGui.QColor(0, 0, 0, 128))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.PlaceholderText, brush)
self.time_lb.setPalette(palette)
font = QtGui.QFont()
font.setFamily("Arial")
font.setPointSize(16)
font.setBold(True)
font.setWeight(75)
self.time_lb.setFont(font)
self.time_lb.setText("")
self.time_lb.setObjectName("time_lb")
self.horizontalLayout_7.addWidget(self.time_lb)
self.layoutWidget6 = QtWidgets.QWidget(self.groupBox_2)
self.layoutWidget6.setGeometry(QtCore.QRect(210, 140, 191, 41))
self.layoutWidget6.setObjectName("layoutWidget6")
self.horizontalLayout_8 = QtWidgets.QHBoxLayout(self.layoutWidget6)
self.horizontalLayout_8.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_8.setObjectName("horizontalLayout_8")
self.label_11 = QtWidgets.QLabel(self.layoutWidget6)
self.label_11.setObjectName("label_11")
self.horizontalLayout_8.addWidget(self.label_11)
self.label_conf = QtWidgets.QLabel(self.layoutWidget6)
palette = QtGui.QPalette()
brush = QtGui.QBrush(QtGui.QColor(255, 0, 0))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.WindowText, brush)
brush = QtGui.QBrush(QtGui.QColor(255, 0, 0))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.WindowText, brush)
brush = QtGui.QBrush(QtGui.QColor(120, 120, 120))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.WindowText, brush)
self.label_conf.setPalette(palette)
font = QtGui.QFont()
font.setFamily("Arial")
font.setPointSize(16)
font.setBold(True)
font.setWeight(75)
self.label_conf.setFont(font)
self.label_conf.setText("")
self.label_conf.setObjectName("label_conf")
self.horizontalLayout_8.addWidget(self.label_conf)
self.layoutWidget_3 = QtWidgets.QWidget(self.groupBox_2)
self.layoutWidget_3.setGeometry(QtCore.QRect(10, 140, 191, 41))
self.layoutWidget_3.setObjectName("layoutWidget_3")
self.horizontalLayout_9 = QtWidgets.QHBoxLayout(self.layoutWidget_3)
self.horizontalLayout_9.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_9.setObjectName("horizontalLayout_9")
self.label_13 = QtWidgets.QLabel(self.layoutWidget_3)
self.label_13.setMaximumSize(QtCore.QSize(60, 16777215))
self.label_13.setObjectName("label_13")
self.horizontalLayout_9.addWidget(self.label_13)
self.type_lb = QtWidgets.QLabel(self.layoutWidget_3)
palette = QtGui.QPalette()
brush = QtGui.QBrush(QtGui.QColor(255, 0, 0))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.WindowText, brush)
brush = QtGui.QBrush(QtGui.QColor(255, 0, 0))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.WindowText, brush)
brush = QtGui.QBrush(QtGui.QColor(120, 120, 120))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.WindowText, brush)
self.type_lb.setPalette(palette)
font = QtGui.QFont()
font.setFamily("Arial")
font.setPointSize(16)
font.setBold(True)
font.setWeight(75)
self.type_lb.setFont(font)
self.type_lb.setText("")
self.type_lb.setObjectName("type_lb")
self.horizontalLayout_9.addWidget(self.type_lb)
self.groupBox_4 = QtWidgets.QGroupBox(self.frame_4)
self.groupBox_4.setGeometry(QtCore.QRect(0, 490, 431, 211))
font = QtGui.QFont()
font.setFamily("华文楷体")
font.setPointSize(16)
self.groupBox_4.setFont(font)
self.groupBox_4.setObjectName("groupBox_4")
self.widget = QtWidgets.QWidget(self.groupBox_4)
self.widget.setGeometry(QtCore.QRect(17, 30, 430, 171))
self.widget.setObjectName("widget")
self.formLayout = QtWidgets.QFormLayout(self.widget)
self.formLayout.setLabelAlignment(QtCore.Qt.AlignCenter)
self.formLayout.setFormAlignment(QtCore.Qt.AlignCenter)
self.formLayout.setContentsMargins(0, 0, 77, 0)
self.formLayout.setHorizontalSpacing(51)
self.formLayout.setVerticalSpacing(11)
self.formLayout.setObjectName("formLayout")
self.FilesBtn = QtWidgets.QPushButton(self.widget)
self.FilesBtn.setMinimumSize(QtCore.QSize(150, 40))
self.FilesBtn.setMaximumSize(QtCore.QSize(150, 40))
font = QtGui.QFont()
font.setFamily("华文楷体")
font.setPointSize(16)
self.FilesBtn.setFont(font)
self.FilesBtn.setStyleSheet("")
icon1 = QtGui.QIcon()
icon1.addPixmap(QtGui.QPixmap(":/icons/ui_imgs/icons/folder.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.FilesBtn.setIcon(icon1)
self.FilesBtn.setIconSize(QtCore.QSize(30, 30))
self.FilesBtn.setObjectName("FilesBtn")
self.formLayout.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.FilesBtn)
self.VideoBtn = QtWidgets.QPushButton(self.widget)
self.VideoBtn.setMinimumSize(QtCore.QSize(150, 40))
self.VideoBtn.setMaximumSize(QtCore.QSize(150, 40))
font = QtGui.QFont()
font.setFamily("华文楷体")
font.setPointSize(16)
self.VideoBtn.setFont(font)
icon2 = QtGui.QIcon()
icon2.addPixmap(QtGui.QPixmap(":/icons/ui_imgs/icons/video.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.VideoBtn.setIcon(icon2)
self.VideoBtn.setIconSize(QtCore.QSize(30, 30))
self.VideoBtn.setObjectName("VideoBtn")
self.formLayout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.VideoBtn)
self.CapBtn = QtWidgets.QPushButton(self.widget)
self.CapBtn.setMinimumSize(QtCore.QSize(150, 40))
self.CapBtn.setMaximumSize(QtCore.QSize(150, 40))
font = QtGui.QFont()
font.setFamily("华文楷体")
font.setPointSize(16)
self.CapBtn.setFont(font)
icon3 = QtGui.QIcon()
icon3.addPixmap(QtGui.QPixmap(":/icons/ui_imgs/icons/camera.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.CapBtn.setIcon(icon3)
self.CapBtn.setIconSize(QtCore.QSize(30, 30))
self.CapBtn.setObjectName("CapBtn")
self.formLayout.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.CapBtn)
self.SaveBtn = QtWidgets.QPushButton(self.widget)
self.SaveBtn.setMinimumSize(QtCore.QSize(150, 40))
self.SaveBtn.setMaximumSize(QtCore.QSize(150, 40))
icon4 = QtGui.QIcon()
icon4.addPixmap(QtGui.QPixmap(":/icons/ui_imgs/icons/保存.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.SaveBtn.setIcon(icon4)
self.SaveBtn.setIconSize(QtCore.QSize(30, 30))
self.SaveBtn.setObjectName("SaveBtn")
self.formLayout.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.SaveBtn)
self.ExitBtn = QtWidgets.QPushButton(self.widget)
self.ExitBtn.setMinimumSize(QtCore.QSize(150, 40))
self.ExitBtn.setMaximumSize(QtCore.QSize(150, 40))
icon5 = QtGui.QIcon()
icon5.addPixmap(QtGui.QPixmap(":/icons/ui_imgs/icons/退出.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.ExitBtn.setIcon(icon5)
self.ExitBtn.setIconSize(QtCore.QSize(30, 30))
self.ExitBtn.setObjectName("ExitBtn")
self.formLayout.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.ExitBtn)
self.PicBtn = QtWidgets.QPushButton(self.widget)
self.PicBtn.setMinimumSize(QtCore.QSize(150, 40))
self.PicBtn.setMaximumSize(QtCore.QSize(150, 40))
font = QtGui.QFont()
font.setFamily("华文楷体")
font.setPointSize(16)
self.PicBtn.setFont(font)
self.PicBtn.setStyleSheet("")
icon6 = QtGui.QIcon()
icon6.addPixmap(QtGui.QPixmap(r"E:\robot\UIProgram\ui_imgs\12.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.PicBtn.setIcon(icon6)
self.PicBtn.setIconSize(QtCore.QSize(30, 30))
self.PicBtn.setObjectName("PicBtn")
self.formLayout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.PicBtn)
self.frame_5 = QtWidgets.QFrame(self.centralwidget)
self.frame_5.setGeometry(QtCore.QRect(10, 10, 1231, 91))
self.frame_5.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_5.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame_5.setObjectName("frame_5")
self.label_3 = QtWidgets.QLabel(self.frame_5)
self.label_3.setGeometry(QtCore.QRect(280, 0, 811, 51))
font = QtGui.QFont()
font.setFamily("微软雅黑") # 设置字体为微软雅黑
font.setPointSize(25)
self.label_3.setFont(font)
self.label_3.setAlignment(QtCore.Qt.AlignCenter) # 设置文字居中
self.label_3.setObjectName("label_3")
font = QtGui.QFont()
font.setFamily("华文楷体")
font.setPointSize(14)
font.setUnderline(True)
font = QtGui.QFont()
font.setFamily("华文楷体")
font.setPointSize(14)
font.setUnderline(True)
MainWindow.setCentralWidget(self.centralwidget)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "基于深度学习的检测系统"))
self.PiclineEdit.setPlaceholderText(_translate("MainWindow", "请选择图片文件"))
self.VideolineEdit.setPlaceholderText(_translate("MainWindow", "请选择视频文件"))
self.CaplineEdit.setPlaceholderText(_translate("MainWindow", "摄像头未开启"))
self.groupBox_3.setTitle(_translate("MainWindow", "检测结果与位置信息"))
item = self.tableWidget.horizontalHeaderItem(0)
item.setText(_translate("MainWindow", "序号"))
item = self.tableWidget.horizontalHeaderItem(1)
item.setText(_translate("MainWindow", "文件路径"))
item = self.tableWidget.horizontalHeaderItem(2)
item.setText(_translate("MainWindow", "类别"))
item = self.tableWidget.horizontalHeaderItem(3)
item.setText(_translate("MainWindow", "置信度"))
item = self.tableWidget.horizontalHeaderItem(4)
item.setText(_translate("MainWindow", "坐标位置"))
self.groupBox.setTitle(_translate("MainWindow", "检测参数设置"))
self.checkBox.setText(_translate("MainWindow", "显示标签名称与置信度"))
self.label_14.setText(_translate("MainWindow", "置信度阈值:"))
self.label_15.setText(_translate("MainWindow", "交并比阈值:"))
self.groupBox_2.setTitle(_translate("MainWindow", "检测结果"))
self.label_4.setText(_translate("MainWindow", "<html><head/><body><p><span style=\" font-weight:600;\">目标位置:</span></p></body></html>"))
self.label_6.setText(_translate("MainWindow", "<html><head/><body><p><span style=\" font-weight:600;\">xmin:</span></p></body></html>"))
self.label_8.setText(_translate("MainWindow", "<html><head/><body><p><span style=\" font-weight:600;\">ymin:</span></p></body></html>"))
self.label_7.setText(_translate("MainWindow", "<html><head/><body><p><span style=\" font-weight:600;\">xmax:</span></p></body></html>"))
self.label_9.setText(_translate("MainWindow", "<html><head/><body><p><span style=\" font-weight:600;\">ymax:</span></p></body></html>"))
self.label.setText(_translate("MainWindow", "<html><head/><body><p><span style=\" font-weight:600;\">目标数目:</span></p></body></html>"))
self.label_5.setText(_translate("MainWindow", "<html><head/><body><p><span style=\" font-weight:600;\">目标选择:</span></p></body></html>"))
self.label_10.setText(_translate("MainWindow", "<html><head/><body><p><span style=\" font-weight:600;\">用时:</span></p></body></html>"))
self.label_11.setText(_translate("MainWindow", "<html><head/><body><p><span style=\" font-weight:600;\">置信度:</span></p></body></html>"))
self.label_13.setText(_translate("MainWindow", "<html><head/><body><p><span style=\" font-weight:600;\">类型:</span></p></body></html>"))
self.groupBox_4.setTitle(_translate("MainWindow", "操作"))
self.FilesBtn.setText(_translate("MainWindow", "打开文件夹"))
self.VideoBtn.setText(_translate("MainWindow", "打开视频"))
self.CapBtn.setText(_translate("MainWindow", "打开摄像头"))
self.SaveBtn.setText(_translate("MainWindow", "保存"))
self.ExitBtn.setText(_translate("MainWindow", "退出"))
self.PicBtn.setText(_translate("MainWindow", "打开图片"))
self.label_3.setText(_translate("MainWindow", "基于深度学习的水下生物检测系统"))
import ui_sources_rc
这只是一个项目的UI界面的一部分代码

3.结论
在学习 PyQt5 的过程中,我深入掌握了其核心框架和开发流程。通过实践操作,我学会了创建窗口、布局管理以及添加按钮、文本框等基础控件,并在此过程中深刻理解了信号与槽机制在实现交互逻辑中的关键作用。此外,我们还可以通过使用 Qt Designer 快速搭建界面的方法,并能够通过代码将业务逻辑与界面有机结合,从而显著提升了开发效率。
在进阶应用实践中,我探索了多线程和数据库操作等功能,深刻体会到了 PyQt5 在 GUI 程序开发中所具备的强大扩展性。尽管在学习过程中遇到了诸如布局冲突、事件处理不响应等挑战,但我通过查阅官方文档和社区资料,逐步解决了这些问题,从而进一步加深了对 PyQt5 的理解。
总体而言,PyQt5 的学习之旅极大地增强了我开发功能丰富、界面美观的桌面应用的能力,使我能够利用其强大的功能和灵活的架构,创造出更加出色的应用程序。
2万+

被折叠的 条评论
为什么被折叠?



