一、设计思路
1、思路分析与设计
本段代码是一个使用 PyQt6 和 OpenCV 创建的图像处理应用程序。其主要功能是通过一个图形界面让用户对图片进行基本的图像处理操作,如灰度化、翻转、旋转、亮度与对比度调整,以及一些滤镜效果(模糊、锐化、边缘检测等)。应用程序的核心思想是将图像通过不同的算法进行处理,并通过一个图形用户界面与用户进行交互。
2、主要设计思路:
界面设计:
通过 PyQt6 提供的 QWidget
基础类构建一个窗口界面。
在界面中使用了 QLabel
显示图像,使用 QPushButton
实现用户操作按钮,使用 QSlider
控制图像亮度和对比度,使用 QComboBox
提供滤镜选择。
图像加载与转换:
使用 OpenCV 的 cv2.imread()
函数加载图像。
将 OpenCV 中使用的 BGR 图像格式转换为适合 PyQt6 显示的 RGB 格式,并将其转换为 QImage
,然后再转换为 QPixmap
显示在 QLabel
上。
事件与信号槽机制:
通过 PyQt6 提供的信号-槽机制将 GUI 元素(如按钮、滑块、下拉框)与对应的处理函数进行关联。
点击按钮或滑动滑块时,程序会相应地调用相应的图像处理函数,处理后的图像通过更新 QLabel
的显示内容反馈给用户。
图像处理:
灰度化:将图片转换为灰度图像,通过 cv2.cvtColor()
函数实现。
翻转:通过 cv2.flip()
函数实现水平翻转。
旋转:通过 cv2.getRotationMatrix2D()
和 cv2.warpAffine()
函数实现图片的旋转。
亮度与对比度调整:通过滑块获取当前值,对图像进行线性亮度和对比度调整。
滤镜处理:通过下拉框选择不同的滤镜效果,如模糊、锐化、边缘检测等,利用 OpenCV 中的相应函数(如 cv2.blur()
、cv2.GaussianBlur()
、cv2.Canny()
)处理图像。
保存图片:
用户可以通过按钮将处理后的图像保存到本地。
二、设计到的函数方法
1. Qimg(self, img)
功能:将 OpenCV 图像格式(BGR)转换为 PyQt6 可以显示的格式(RGB 和 QImage
)。
实现:
使用 cv2.cvtColor()
将图像从 BGR 转换为 RGB 格式。
使用 QImage
类构造图像对象,准备好用于显示。
2. gray_image(self)
功能:将图像转换为灰度图像并更新显示。
实现:
使用 cv2.cvtColor()
将图像转换为灰度图。
更新 QLabel
中显示的图像。
3. rec(self)
功能:恢复原图,重新加载图片。
实现:
使用 cv2.imread()
重新加载原始图片并更新显示。
4. flip(self)
功能:翻转图像(水平翻转)。
实现:
使用 cv2.flip()
执行水平翻转。
更新显示的图像。
5. warp(self)
功能:旋转图像(90度旋转)。
实现:
使用 cv2.getRotationMatrix2D()
和 cv2.warpAffine()
进行旋转。
更新显示的图像。
6. bright(self)
功能:调整图像的亮度和对比度。
实现:
获取滑块的值,计算出相应的亮度和对比度调整系数。
使用这些系数调整图像的像素值,并更新显示。
7. save(self)
功能:保存当前图像到本地文件。
实现:
使用 cv2.imwrite()
保存图像。
8. dispose(self)
功能:根据选择的滤镜效果(模糊、锐化、边缘检测)处理图像。
实现:
使用下拉框选择不同的滤镜效果,并根据选择的内容应用相应的图像处理方法。
三、代码
import cv2
import numpy as npimport sysfrom PyQt6 import uic
from PyQt6.QtGui import QPixmap, QImage
from PyQt6.QtWidgets import QWidget, QApplication, QLabel, QPushButton, QSlider, QComboBox# 创建一个继承自QWidget的自定义窗口类
class MyWidget(QWidget):def __init__(self):super().__init__()# 加载并初始化UI文件ui = uic.loadUi("./Form.ui", self)# 加载初始图片,并为其创建副本和QImage对象self.img = cv2.imread("../demo.png") # 读取图片self.img_2 = self.img.copy() # 创建图片副本,用于亮度和对比度调整self.q_img = self.Qimg(self.img) # 将OpenCV格式的图像转换为QImage格式# 初始化UI组件,包括标签、按钮、滑块等self.label: QLabel = ui.labelself.pushButton: QPushButton = ui.pushButtonself.pushButton_2: QPushButton = ui.pushButton_2self.pushButton_3: QPushButton = ui.pushButton_3self.pushButton_4: QPushButton = ui.pushButton_4self.horizontalSlider: QSlider = ui.horizontalSlider # 亮度滑块self.horizontalSlider.setRange(0, 50) # 设置亮度调整范围self.horizontalSlider.setValue(0) # 设置默认亮度值为0self.horizontalSlider_2: QSlider = ui.horizontalSlider_2 # 对比度滑块self.horizontalSlider_2.setRange(1, 100) # 设置对比度调整范围self.horizontalSlider_2.setValue(1) # 设置默认对比度值为1self.pushButton_5: QPushButton = ui.pushButton_5 # 保存按钮self.comboBox: QComboBox = ui.comboBox # 下拉框,用于选择滤镜效果# 连接按钮的点击事件到相应的槽函数self.pushButton.clicked.connect(self.gray_image) # 点击“灰度化”按钮self.pushButton_2.clicked.connect(self.rec) # 点击“恢复”按钮self.pushButton_3.clicked.connect(self.flip) # 点击“翻转”按钮self.pushButton_4.clicked.connect(self.warp) # 点击“旋转”按钮self.horizontalSlider.valueChanged.connect(self.bright) # 亮度滑块改变时self.horizontalSlider_2.valueChanged.connect(self.bright) # 对比度滑块改变时self.pushButton_5.clicked.connect(self.save) # 点击“保存”按钮self.comboBox.currentIndexChanged.connect(self.dispose) # 选择滤镜时# 为下拉框添加滤镜选项list1 = [' ','模糊', '锐化', '边缘检测']self.comboBox.addItems(list1)# 将QImage转换为QPixmap并设置为label的图片显示self.label.setPixmap(QPixmap.fromImage(self.q_img))self.label.setScaledContents(True) # 设置图片自适应标签大小# 设置标志位,用于判断是否已经应用灰度化self.slot = False# 图片转换函数,将OpenCV格式的BGR图片转换为QImage格式def Qimg(self, img):img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # 将BGR图像转换为RGBh, w, c = img_rgb.shape # 获取图像的高度、宽度和通道数bytes_per_line = c * w # 每行字节数q_img = QImage(img_rgb.data, w, h, bytes_per_line, QImage.Format.Format_RGB888) # 转换为QImagereturn q_img# 定义将图片灰度化的按钮响应函数def gray_image(self):if not self.slot: # 判断是否已经灰度化过self.img = cv2.cvtColor(self.img, cv2.COLOR_BGR2GRAY) # 将图片转换为灰度图q_img = self.Qimg(self.img) # 转换为QImage格式self.label.setPixmap(QPixmap.fromImage(q_img)) # 更新显示的图片self.slot = True # 更新标志位,表示已经灰度化# 定义恢复原图的按钮响应函数def rec(self):self.img = cv2.imread('../demo.png') # 重新加载原始图片self.q_img = self.Qimg(self.img) # 转换为QImage格式self.label.setPixmap(QPixmap(self.q_img)) # 更新显示的图片self.slot = False # 重置标志位,表示恢复为原图# 定义图片翻转的按钮响应函数def flip(self):self.img = cv2.flip(self.img, 1) # 进行水平翻转self.q_img = self.Qimg(self.img) # 转换为QImage格式self.label.setPixmap(QPixmap.fromImage(self.q_img)) # 更新显示的图片# 定义图片旋转的按钮响应函数def warp(self):M = cv2.getRotationMatrix2D((self.img.shape[1] / 2, self.img.shape[0] / 2), 90, 1) # 获取旋转矩阵self.img = cv2.warpAffine(self.img, M, (self.img.shape[1], self.img.shape[0])) # 应用旋转self.q_img = self.Qimg(self.img) # 转换为QImage格式self.label.setPixmap(QPixmap.fromImage(self.q_img)) # 更新显示的图片# 定义亮度和对比度调整的函数def bright(self):brightness = self.horizontalSlider.value() # 获取当前亮度值contrast = self.horizontalSlider_2.value() / 100 + 1 # 获取当前对比度值,范围在1到2之间img_copy = contrast * self.img_2 + brightness # 应用对比度和亮度调整img_copy = np.clip(img_copy, 0, 255) # 保证像素值在0到255之间img_copy = np.uint8(img_copy) # 转换为无符号8位整数类型self.img = img_copy # 更新图片self.q_img = self.Qimg(self.img) # 转换为QImage格式self.label.setPixmap(QPixmap.fromImage(self.q_img)) # 更新显示的图片# 定义保存图片的函数def save(self):cv2.imwrite('./img.png', self.img) # 保存当前图片到本地文件# 根据选择的滤镜效果处理图片def dispose(self):# - 模糊——使用cv2.GaussianBlur()实现# - 锐化——使用cv2.Laplacian()、cv2.Sobel()实现# - 边缘检测——使用cv2.Canny()实现if self.comboBox.currentText() == ' ':self.rec()elif self.comboBox.currentText() == '模糊':self.img = cv2.GaussianBlur(self.img, (5, 5), 0)self.q_img = self.Qimg(self.img) # 转换为QImage格式self.label.setPixmap(QPixmap.fromImage(self.q_img))elif self.comboBox.currentText() == '锐化':self.img = cv2.Laplacian(self.img, cv2.CV_64F)self.img = cv2.convertScaleAbs(self.img)self.q_img = self.Qimg(self.img) # 转换为QImage格式self.label.setPixmap(QPixmap.fromImage(self.q_img)) # 更新显示的图片elif self.comboBox.currentText() =='边缘检测':M = cv2.Canny(self.img, 100, 200) # 应用Canny边缘检测算法contours, h = cv2.findContours(M, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # 查找轮廓self.img = cv2.drawContours(self.img, contours, -1, (0, 255, 0), 3) # 绘制轮廓self.q_img = self.Qimg(self.img) # 转换为QImage格式self.label.setPixmap(QPixmap.fromImage(self.q_img)) # 更新显示的图片# 主程序入口
if __name__ == '__main__':app = QApplication(sys.argv) # 创建应用对象myWidget = MyWidget() # 创建自定义窗口对象myWidget.show() # 显示窗口sys.exit(app.exec()) # 进入应用的事件循环
四、效果展示
原始界面
灰度化
恢复
翻转
旋转
亮度
对比度
模糊
锐化
边缘检测
保存