题目1、简单图像处理
创建一个 PyQt 应用程序,该应用程序能够:
1、使用 OpenCV 加载一张图像。
2、在 PyQt 的窗口中显示这张图像。
3、提供四个按钮(QPushButton):
- 一个用于将图像转换为灰度图
- 一个用于将图像恢复为原始彩色图
- 一个用于将图像进行翻转
- 一个用于将图像进行旋转
4、当用户点击按钮时,相应地更新窗口中显示的图像。
用于测试的图片如下:
QT窗口界面搭建
首先,我在QT Designer里搭建了如下窗口:
并且对内部的组件进行了命名,方便后续搭建对应的槽函数
代码实现
import sys
import cv2
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPixmap, QImage
from PyQt5.QtWidgets import QWidget, QPushButton, QLabel, QApplication
from qtpy import uic
class MyWidget(QWidget):
def __init__(self):
super().__init__()
ui = uic.loadUi('./image.ui', self)
#设置窗口固定大小
self.setFixedSize(1000,800)
self.GrayBtn: QPushButton = ui.graybtn # 灰度化按钮
self.ImgBtn: QPushButton = ui.imgbtn # 显示原图按钮
self.FlipBtn: QPushButton = ui.filipbtn # 翻转按钮
self.RotateBtn: QPushButton = ui.rotatebtn # 旋转按钮
self.imagelab: QLabel = ui.imagelab # 显示图片
# 读取图片
self.original_image = cv2.imread('./lena.png')
self.current_image = self.original_image.copy() #复制原图用于后续处理
# 信号和槽的连接
self.GrayBtn.clicked.connect(self.to_grayscale)
self.ImgBtn.clicked.connect(self.restore_color)
self.FlipBtn.clicked.connect(self.flip_image)
self.RotateBtn.clicked.connect(self.rotate_image)
# 初始化显示原图
self.update_image()
def convert_cv_qt(self, img):
"""将 OpenCV 图像转换为 QImage"""
if len(img.shape) == 2: # 灰度图
height, width = img.shape
bytes_per_line = width
qimg = QImage(img.data, width, height, bytes_per_line, QImage.Format_Grayscale8)
else: # 彩色图
height, width, channel = img.shape
bytes_per_line = 3 * width
qimg = QImage(img.data, width, height, bytes_per_line, QImage.Format_RGB888).rgbSwapped()
return qimg
def update_image(self):
"""更新 QLabel 上显示的图像"""
qimg = self.convert_cv_qt(self.current_image)
pixmap = QPixmap.fromImage(qimg)
self.imagelab.setPixmap(pixmap)
self.imagelab.setAlignment(Qt.AlignCenter)
def to_grayscale(self):
"""转换为灰度图"""
self.current_image = cv2.cvtColor(self.original_image, cv2.COLOR_BGR2GRAY)
self.current_image = cv2.cvtColor(self.current_image, cv2.COLOR_GRAY2BGR) # 转换为伪彩色以便显示
self.update_image()
def restore_color(self):
"""恢复为原图"""
self.current_image = self.original_image.copy()
self.update_image()
def flip_image(self):
"""翻转图像"""
self.current_image = cv2.flip(self.original_image, 1) # 水平翻转
self.update_image()
def rotate_image(self):
"""旋转图像"""
(h, w) = self.original_image.shape[:2]
center = (w // 2, h // 2)
M = cv2.getRotationMatrix2D(center, 90, 1.0) # 顺时针旋转90度
self.current_image = cv2.warpAffine(self.original_image, M, (w, h)) # 注意:这里可能会裁剪图像
# 如果需要保留全部图像,可以调整输出图像大小或使用填充
self.update_image()
if __name__ == "__main__":
app = QApplication(sys.argv)
myWidget = MyWidget()
myWidget.show()
sys.exit(app.exec_())
结果展示
题目2、图像亮度对比度调整
创建一个 PyQt 应用程序,该应用程序能够:
- 使用 OpenCV 加载一张彩色图像,并在 PyQt 的窗口中显示它。
- 提供一个滑动条(QSlider),允许用户调整图像的亮度。
- 当用户调整滑动条时,实时更新窗口中显示的图像亮度。
- 添加另一个滑动条(QSlider),允许用户调整图像的对比度。
- 当用户调整滚动条时,实时更新窗口中显示的图像对比度。
- 提供一个按钮(QPushButton),允许用户将图像保存为新的文件。
- 当用户点击保存按钮时,将调整后的图像保存到指定的路径,OpenCV中使用cv2.imwrite()来保存图片。
QT窗口界面搭建
首先,我在QT Designer里搭建了如下窗口:
并且对内部的组件进行了命名,方便后续搭建对应的槽函数
代码实现
import sys
import cv2
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPixmap, QImage
from PyQt5.QtWidgets import QWidget, QPushButton, QLabel, QApplication, QSlider, QFileDialog
from qtpy import uic
class MyWidget(QWidget):
def __init__(self):
super().__init__()
ui = uic.loadUi('./form2.ui', self)
#设置窗口固定大小
self.setFixedSize(1100,1000)
self.imagelab.setAlignment(Qt.AlignCenter) #设置居中显示图片
self.SaveBtn: QPushButton = ui.savebtn # 保存按钮
self.imagelab: QLabel = ui.imagelab # 显示图片
self.contrastSlider: QSlider = ui.contrastSlider #对比度滑块
self.lightSlider:QSlider = ui.lightSlider #亮度滑块
# 读取图片
self.original_image = cv2.imread('./lena.png')
self.current_image = self.original_image.copy()
# 信号和槽的连接
self.SaveBtn.clicked.connect(self.SaveBtn_slot)
self.contrastSlider.valueChanged.connect(self.change_contrast) # 改变对比度
self.lightSlider.valueChanged.connect(self.change_light) # 改变亮度
# 初始化显示原图
self.update_image()
def convert_cv_qt(self, img):
"""将 OpenCV 图像转换为 QImage"""
if len(img.shape) == 2: # 灰度图
height, width = img.shape
bytes_per_line = width
qimg = QImage(img.data, width, height, bytes_per_line, QImage.Format_Grayscale8)
else: # 彩色图
height, width, channel = img.shape
bytes_per_line = 3 * width
qimg = QImage(img.data, width, height, bytes_per_line, QImage.Format_RGB888).rgbSwapped()
return qimg
def update_image(self):
"""更新 QLabel 上显示的图像"""
qimg = self.convert_cv_qt(self.current_image)
pixmap = QPixmap.fromImage(qimg)
self.imagelab.setPixmap(pixmap)
def change_contrast(self,value):
alpha = value / 50.0 # 将滑动条的值映射到0到2
self.current_image = cv2.convertScaleAbs(self.original_image.copy(), alpha=alpha, beta=0)
self.update_image()
def change_light(self,value):
beta = value - 50 # 将滑动条的值映射到-50到50
self.current_image = cv2.convertScaleAbs(self.original_image.copy(), alpha=1, beta=beta)
self.update_image()
def SaveBtn_slot(self):
options = QFileDialog.Options()
filePath, _ = QFileDialog.getSaveFileName(self, "Save Image", "", "Images (*.png *.xpm *.jpg);;All Files (*)",
options=options)
if filePath:
cv2.imwrite(filePath, self.current_image)
if __name__ == "__main__":
app = QApplication(sys.argv)
myWidget = MyWidget()
myWidget.show()
sys.exit(app.exec_())
这个代码并不完善,滑块位于中间时才是原图的样式,且亮度和对比度不能同时调整,希望后续我能将代码有所改进。
结果展示
题目3、图像锐化模糊等操作
创建一个 PyQt 应用程序,该应用程序能够:
1.使用 OpenCV 加载一张图像。
2.在 PyQt 的窗口中显示这张图像。
3.提供一个下拉列表(QComboBox),对图像做(模糊、锐化、边缘检测)处理:
- - 模糊——使用cv2.GaussianBlur()实现
- - 锐化——使用cv2.Laplacian()、cv2.Sobel()实现
- - 边缘检测——使用cv2.Canny()实现
4.当用户点击下拉列表选项时,相应地更新窗口中显示的图像。
5.提供一个按钮,当用户点击按钮时,能保存调整后的图像。
QT窗口界面搭建
首先,我在QT Designer里搭建了如下窗口:
并且对内部的组件进行了命名,方便后续搭建对应的槽函数
代码实现
import sys
import cv2
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPixmap, QImage
from PyQt5.QtWidgets import QWidget, QPushButton, QLabel, QApplication, QComboBox, QFileDialog
from qtpy import uic
class MyWidget(QWidget):
def __init__(self):
super().__init__()
ui = uic.loadUi('./form3.ui', self)
#设置窗口固定大小
self.setFixedSize(1000,800)
self.imagelab.setAlignment(Qt.AlignCenter) #设置居中显示图片
self.imagelab: QLabel = ui.imagelab # 显示图片
self.SaveBtn: QPushButton = ui.savebtn # 保存按钮
self.comboBox: QComboBox = ui.comboBox #下拉列表
# 读取图片
self.original_image = cv2.imread('./lena.png')
self.current_image = self.original_image.copy()
# 信号和槽的连接
self.SaveBtn.clicked.connect(self.SaveBtn_slot)
self.comboBox.currentIndexChanged.connect(self.processImage)
# 初始化显示原图
self.update_image()
def SaveBtn_slot(self):
options = QFileDialog.Options()
filePath, _ = QFileDialog.getSaveFileName(self, "Save Image", "", "Images (*.png *.xpm *.jpg);;All Files (*)",
options=options)
if filePath:
cv2.imwrite(filePath, self.current_image)
def processImage(self, index):
"""根据下拉列表的选项处理图像"""
if index == 0:
self.current_image = self.original_image.copy()
elif index == 1:
# 模糊
self.current_image = cv2.GaussianBlur(self.original_image, (15, 15), 0)
elif index == 2:
# 锐化
laplacian = cv2.Laplacian(self.original_image, cv2.CV_64F)
sobelx = cv2.Sobel(self.original_image, cv2.CV_64F, 1, 0, ksize=3)
sobely = cv2.Sobel(self.original_image, cv2.CV_64F, 0, 1, ksize=3)
sharpened = cv2.convertScaleAbs(self.original_image - laplacian + sobelx + sobely)
self.current_image = sharpened
elif index == 3:
# 边缘检测
edges = cv2.Canny(self.original_image, 100, 200)
# Canny 边缘检测返回的是灰度图,但我们可以将其转换为彩色图以更好地在 QLabel 上显示
edges_color = cv2.cvtColor(edges, cv2.COLOR_GRAY2RGB)
self.current_image = edges_color
self.update_image()
def convert_cv_qt(self, img):
"""将 OpenCV 图像转换为 QImage"""
if len(img.shape) == 2: # 灰度图
height, width = img.shape
bytes_per_line = width
qimg = QImage(img.data, width, height, bytes_per_line, QImage.Format_Grayscale8)
else: # 彩色图
height, width, channel = img.shape
bytes_per_line = 3 * width
qimg = QImage(img.data, width, height, bytes_per_line, QImage.Format_RGB888).rgbSwapped()
return qimg
def update_image(self):
"""更新 QLabel 上显示的图像"""
qimg = self.convert_cv_qt(self.current_image)
pixmap = QPixmap.fromImage(qimg)
self.imagelab.setPixmap(pixmap)
if __name__ == "__main__":
app = QApplication(sys.argv)
myWidget = MyWidget()
myWidget.show()
sys.exit(app.exec_())