第一题
创建一个 PyQt 应用程序,该应用程序能够:
1.使用 OpenCV 加载一张图像。
2.在 PyQt 的窗口中显示这张图像。
3.提供四个按钮(QPushButton):
- 一个用于将图像转换为灰度图
- 一个用于将图像恢复为原始彩色图
- 一个用于将图像进行翻转
- 一个用于将图像进行旋转
4.当用户点击按钮时,相应地更新窗口中显示的图像。
思路分析:
- 创建 PyQt 应用程序:
- 使用
QApplication
初始化应用程序。- 创建一个主窗口
QMainWindow
或QWidget
。- 加载和显示图像:
- 使用 OpenCV 加载图像。
- 将 OpenCV 的图像格式转换为 Qt 可以显示的格式(QImage)。
- 使用
QLabel
显示图像。- 创建按钮并添加功能:
- 使用
QPushButton
创建四个按钮,每个按钮对应一个图像处理操作。- 将按钮添加到布局中。
- 连接按钮的点击信号到相应的槽函数。
- 图像处理:
- 编写槽函数来处理按钮点击事件,执行相应的图像处理操作。
- 更新
QLabel
上显示的图像。- 更新显示:
- 在槽函数中,每次图像处理后,更新
QLabel
的图像显示。
涉及到的函数及方法:
cv2
相关
cv2.imread(filepath, flags=cv2.IMREAD_COLOR)
:- 功能:读取图像文件。
- 参数:
filepath
:图像文件的路径。flags
:指定读取图像的方式(例如,彩色图像、灰度图像等)。
- 返回值:图像数据,通常是一个 NumPy 数组。
cv2.cvtColor(src, code)
:- 功能:转换图像从一个颜色空间到另一个。
- 参数:
src
:源图像。code
:转换代码(例如,从 BGR 到 RGB,从 BGR 到灰度等)。
- 返回值:转换后的图像。
cv2.flip(src, flipCode)
:- 功能:翻转图像。
- 参数:
src
:源图像。flipCode
:翻转方式(例如,水平翻转、垂直翻转等)。
- 返回值:翻转后的图像。
PyQt6
相关
uic.loadUi(ui_file, baseinstance)
:- 功能:从指定的 UI 文件加载界面,并将其设置到
baseinstance
中。 - 参数:
ui_file
:UI 文件的路径。baseinstance
:一个 QWidget 或其子类实例,用于加载 UI。
- 功能:从指定的 UI 文件加载界面,并将其设置到
QImage(data, width, height, bytes_per_line, format)
:- 功能:创建一个 QImage 对象。
- 参数:
data
:图像数据的指针。width
:图像的宽度。height
:图像的高度。bytes_per_line
:每行的字节数。format
:图像格式。
QPixmap.fromImage(image)
:- 功能:从 QImage 对象创建一个 QPixmap 对象。
- 参数:
image
:QImage 对象。
QLabel.setPixmap(pixmap)
:- 功能:设置 QLabel 的图像。
- 参数:
pixmap
:QPixmap 对象。
QLabel.setScaledContents(True)
:- 功能:使 QLabel 根据其内容自动调整大小。
源码如下:
import cv2
from PyQt6 import uic
from PyQt6.QtGui import QImage, QPixmap
from PyQt6.QtWidgets import QApplication, QWidget, QPushButton, QLabel
import sysclass MyWidget(QWidget):def __init__(self):super().__init__()ui = uic.loadUi("form1.ui", self)#图片灰度化self.gray:QPushButton = ui.grayself.gray.clicked.connect(self.gray_slot)#图片恢复原状self.original:QPushButton = ui.originalself.original.clicked.connect(self.original_slot)#图片翻转self.flip:QPushButton = ui.flipself.flip.clicked.connect(self.flip_slot)#图片旋转self.rotate:QPushButton = ui.rotateself.rotate.clicked.connect(self.rotate_slot)self.img:QLabel = ui.imgself.img_data = cv2.imread("flower.png")self.display_image(self.img_data)def gray_slot(self):img_gray = cv2.cvtColor(self.img_data, cv2.COLOR_BGR2GRAY)self.display_image(img_gray)def original_slot(self):self.img_data = cv2.imread("flower.png")self.display_image(self.img_data)def flip_slot(self):self.img_data = cv2.flip(self.img_data, 1) # 1 为水平翻转self.display_image(self.img_data)def rotate_slot(self):M=cv2.getRotationMatrix2D((self.img_data.shape[1]/2,self.img_data.shape[0]/2),90,1)self.img_data = cv2.warpAffine(self.img_data,M,(self.img_data.shape[1],self.img_data.shape[0]))self.display_image(self.img_data)def display_image(self,img):if len(img.shape) == 2: # 灰度图没有 color channelsimg_rgb = cv2.cvtColor(img, cv2.COLOR_GRAY2RGB)else:img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)# 转换为 QPixmaph, w, ch = img_rgb.shapebytes_per_line = ch * wq_image = QImage(img_rgb.data, w, h, bytes_per_line, QImage.Format.Format_RGB888)# 显示图像self.img.setPixmap(QPixmap.fromImage(q_image))self.img.setScaledContents(True)if __name__ == "__main__":app = QApplication(sys.argv)window = MyWidget()window.show()sys.exit(app.exec())
效果展示
从左到右,从上到下依次为:转灰度图,水平翻转,图像旋转,恢复原状
第二题
创建一个 PyQt 应用程序,该应用程序能够:
- 使用 OpenCV 加载一张彩色图像,并在 PyQt 的窗口中显示它。
- 提供一个滑动条(QSlider),允许用户调整图像的亮度。
- 当用户调整滑动条时,实时更新窗口中显示的图像亮度。
- 添加另一个滑动条(QSlider),允许用户调整图像的对比度。
- 当用户调整滚动条时,实时更新窗口中显示的图像对比度。
- 提供一个按钮(QPushButton),允许用户将图像保存为新的文件。
- 当用户点击保存按钮时,将调整后的图像保存到指定的路径,OpenCV中使用cv2.imwrite()来保存图片。
思路分析
1. 初始化 PyQt 应用程序和主窗口
- 创建一个 QApplication 实例。
- 创建一个 QWidget 或 QMainWindow 实例作为主窗口。
- 使用 Qt Designer 或手动编写代码来设计界面,包括 QLabel 用于显示图像,QSlider 用于调整亮度和对比度,以及 QPushButton 用于保存图像。
2. 使用 OpenCV 加载图像
- 在应用程序启动时,使用 OpenCV 的
cv2.imread()
函数加载彩色图像。- 将加载的图像转换为适合 PyQt 显示的格式(例如,从 BGR 转换为 RGB)。
3. 显示图像
- 将加载的图像转换为 QImage,然后设置为 QLabel 的 pixmap。
- 确保 QLabel 的
scaledContents
属性设置为True
,以便图像适应 QLabel 的大小。4. 创建滑动条(QSlider)
- 为亮度和对比度各创建一个 QSlider 实例。
- 设置滑动条的范围(例如,亮度可以在 -100 到 100 之间调整,对比度可以在 0 到 200 之间调整)。
- 将滑动条的
valueChanged
信号连接到自定义的槽函数,以便在用户调整滑动条时更新图像。5. 实时更新图像亮度和对比度
- 在槽函数中,根据滑动条的值调整图像的亮度和对比度。
- 使用 NumPy 对图像数据进行算术运算来实现亮度和对比度的调整。
- 更新 QLabel 上显示的图像。
6. 创建保存按钮(QPushButton)
- 创建一个 QPushButton 实例,设置其文本为“保存”。
- 将按钮的
clicked
信号连接到自定义的槽函数,以便在用户点击按钮时保存图像。7. 保存调整后的图像
- 在保存图像的槽函数中,使用 OpenCV 的
cv2.imwrite()
函数将调整后的图像保存到指定的路径。
涉及到的函数和方法
cv2(OpenCV库)
cv2.imread(filepath)
: 读取图像文件。cv2.addWeighted(src1, alpha, src2, beta, gamma)
: 对两个图像进行加权求和,用于调整亮度。cv2.convertScaleAbs(src, alpha=None, beta=None)
: 按比例缩放图像,然后转换为绝对值,并转换为8位。用于调整对比度。cv2.cvtColor(src, code)
: 转换图像颜色空间,如从BGR转换为RGB。cv2.imwrite(filepath, img)
: 将图像保存到文件。
PyQt6.QtGui 中的类和方法
QImage(data, width, height, bytes_per_line, format)
: 创建一个QImage对象,用于图像处理。QPixmap.fromImage(image)
: 将QImage对象转换为QPixmap对象,以便在QLabel等控件中显示。
PyQt6.QtWidgets 中的类和方法
QApplication(argv)
: 创建QApplication对象,是PyQt应用程序的基础。QWidget()
: 创建QWidget对象,是所有用户界面对象的基类。QLabel()
: 创建QLabel对象,用于显示文本或图像。QSlider()
: 创建QSlider对象,用于提供滑块输入。QPushButton()
: 创建QPushButton对象,用于提供按钮点击输入。slider.valueChanged.connect(slot)
: 连接QSlider的值变化信号到槽函数。button.clicked.connect(slot)
: 连接QPushButton的点击信号到槽函数。label.setPixmap(pixmap)
: 在QLabel中设置QPixmap对象以显示图像。label.setScaledContents(True)
: 使QLabel自动缩放其内容以适应其大小。
源码如下
import cv2
from PyQt6 import uic
from PyQt6.QtGui import QImage, QPixmap
from PyQt6.QtWidgets import QApplication, QWidget, QPushButton, QLabel, QSlider
import sysclass MyWidget(QWidget):def __init__(self):super().__init__()ui = uic.loadUi("form2.ui", self)self.img: QLabel = ui.img# 图片亮度调整self.gamer: QSlider = ui.gamerself.gamer.setMinimum(-100) # 设置亮度最小值self.gamer.setMaximum(100) # 设置亮度最大值self.gamer.setValue(0) # 设置初始值为 0self.gamer.valueChanged.connect(self.gamer_slot)# 图片对比度调整self.contrast: QSlider = ui.contrast_radioself.contrast.setMinimum(1) # 设置对比度最小值self.contrast.setMaximum(100) # 设置对比度最大值self.contrast.setValue(50) # 设置初始值为 50self.contrast.valueChanged.connect(self.contrast_slot)# 保存图片self.save: QPushButton = ui.saveself.save.clicked.connect(self.save_slot)# 读取图片self.img_data = cv2.imread("flower.png")self.display_image(self.img_data)# 初始亮度和对比度增量self.initial_brightness = 0self.initial_contrast = 1.0def gamer_slot(self):# 计算亮度变化brightness_change = self.gamer.value() - self.initial_brightnessself.initial_brightness = self.gamer.value()# 使用 addWeighted 来调整亮度self.img_data = cv2.addWeighted(self.img_data, 1.0, 0, 0, brightness_change)self.display_image(self.img_data)def contrast_slot(self):# 计算对比度变化contrast_change = self.contrast.value() - self.initial_contrastself.initial_contrast = self.contrast.value()# 根据对比度调整图像alpha = 1 + (contrast_change / 100.0) # 控制对比度变化的灵敏度self.img_data = cv2.convertScaleAbs(self.img_data, alpha=alpha, beta=0)self.display_image(self.img_data)def save_slot(self):cv2.imwrite("flower2.png", self.img_data)def display_image(self, img):if len(img.shape) == 2: # 灰度图没有 color channelsimg_rgb = cv2.cvtColor(img, cv2.COLOR_GRAY2RGB)else:img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)# 转换为 QPixmaph, w, ch = img_rgb.shapebytes_per_line = ch * wq_image = QImage(img_rgb.data, w, h, bytes_per_line, QImage.Format.Format_RGB888)# 显示图像self.img.setPixmap(QPixmap.fromImage(q_image))self.img.setScaledContents(True)if __name__ == "__main__":app = QApplication(sys.argv)myWin = MyWidget()myWin.show()sys.exit(app.exec())
效果展示
第三题
创建一个 PyQt 应用程序,该应用程序能够:
1.使用 OpenCV 加载一张图像。
2.在 PyQt 的窗口中显示这张图像。
3.提供一个下拉列表(QComboBox),对图像做(模糊、锐化、边缘检测)处理:
- 模糊——使用cv2.GaussianBlur()实现
- 锐化——使用cv2.Laplacian()、cv2.Sobel()实现
- 边缘检测——使用cv2.Canny()实现
4.当用户点击下拉列表选项时,相应地更新窗口中显示的图像。
5.提供一个按钮,当用户点击按钮时,能保存调整后的图像。
思路分析
1. 初始化应用程序
- 创建一个
QApplication
实例。- 定义一个主窗口类,继承自
QWidget
或QMainWindow
。2. 加载图像
- 在主窗口类中,定义一个方法使用 OpenCV 加载图像。
- 将加载的图像保存为类属性,以便后续处理。
3. 显示图像
- 使用
QLabel
显示图像。- 将 OpenCV 图像转换为
QImage
或QPixmap
,以便在QLabel
中显示。4. 创建下拉列表(QComboBox)
- 在主窗口类中,创建一个
QComboBox
实例。- 向
QComboBox
中添加模糊、锐化、边缘检测等选项。- 连接
QComboBox
的currentIndexChanged
信号到一个槽函数,用于处理图像。5. 处理图像
- 定义一个槽函数,根据
QComboBox
的当前选项对图像进行处理。- 使用 OpenCV 的
GaussianBlur
、Laplacian
、Sobel
和Canny
函数实现模糊、锐化和边缘检测。- 处理后的图像需要再次转换为
QImage
或QPixmap
,以便更新QLabel
。6. 保存图像
- 创建一个按钮,并将其连接到一个槽函数,用于保存图像。
- 在槽函数中,使用 OpenCV 的
imwrite
函数将处理后的图像保存到文件。7. 更新用户界面
- 每次处理图像后,更新
QLabel
以显示新图像。- 确保用户界面响应用户操作,如选择下拉列表选项和点击按钮。
涉及到的函数及方法
cv2.imread("flower.png")
: 使用OpenCV加载图像文件。cv2.GaussianBlur(self.img_data, (5, 5), 0)
: 使用高斯模糊处理图像。cv2.Laplacian(self.img_data, -1)
: 使用拉普拉斯算子进行锐化(但注意,拉普拉斯算子通常用于边缘检测,并且输出的是灰度图)。cv2.Canny(self.img_data, 100, 200)
: 使用Canny边缘检测算法。cv2.cvtColor(...)
: 用于转换图像的颜色空间。QImage(...)
和QPixmap.fromImage(...)
: 用于将OpenCV图像转换为PyQt可以显示的格式。
源码如下
import cv2
from PyQt6.QtGui import QImage, QPixmap
from PyQt6.QtWidgets import QApplication, QWidget, QPushButton, QLabel, QComboBox
from PyQt6 import uic
import sysclass MyWidget(QWidget):def __init__(self):super().__init__()ui = uic.loadUi("form3.ui", self)self.img: QLabel = ui.labelself.combox: QComboBox = ui.comboBoxself.save: QPushButton = ui.save# 添加选项到下拉列表self.combox.addItems(["原图", "模糊", "锐化", "边缘检测"])# 加载图像self.img_data = cv2.imread("flower.png")self.modified_img = self.img_data # 当前显示的图像self.display_image(self.img_data)# 信号与槽连接self.combox.currentIndexChanged.connect(self.combox_slot)self.save.clicked.connect(self.save_image)def combox_slot(self, index):if index == 0:img = self.img_dataelif index == 1:img = cv2.GaussianBlur(self.img_data, (5, 5), 0)elif index == 2:img = cv2.Laplacian(self.img_data, -1)elif index == 3:img = cv2.Canny(self.img_data, 100, 200)self.modified_img = img # 更新当前显示的图像self.display_image(img)def display_image(self, img):if len(img.shape) == 2: # 灰度图没有 color channelsimg_rgb = cv2.cvtColor(img, cv2.COLOR_GRAY2RGB)else:img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)# 转换为 QPixmaph, w, ch = img_rgb.shapebytes_per_line = ch * wq_image = QImage(img_rgb.data, w, h, bytes_per_line, QImage.Format.Format_RGB888)# 显示图像self.img.setPixmap(QPixmap.fromImage(q_image))self.img.setScaledContents(True)def save_image(self):if self.modified_img is not None:cv2.imwrite("output.png", self.modified_img)print("图像已保存为 output.png")if __name__ == "__main__":app = QApplication(sys.argv)window = MyWidget()window.show()sys.exit(app.exec())
效果展示