一、创建一个 PyQt 应用程序,该应用程序能够:
- 使用 OpenCV 加载一张图像。
- 在 PyQt 的窗口中显示这张图像。
- 提供四个按钮(QPushButton):
- 一个用于将图像转换为灰度图
- 一个用于将图像恢复为原始彩色图
- 一个用于将图像进行翻转
- 一个用于将图像进行旋转
- 当用户点击按钮时,相应地更新窗口中显示的图像。
思路分析
- 加载图像 :
- 使用 OpenCV 加载一张图像,并将其存储为类的一个属性,以便在后续操作中访问。
- 显示图像 :
- 使用 PyQt6 的
QLabel来显示图像。 - 将图像转换为
QPixmap,然后设置为QLabel的图像。
- 使用 PyQt6 的
- 创建按钮 :
- 使用 PyQt6 的
QPushButton创建四个按钮,每个按钮对应一个图像处理功能。
- 使用 PyQt6 的
- 实现图像处理功能 :
- 灰度图 :使用 OpenCV 的
cv2.cvtColor函数将图像转换为灰度图。 - 恢复原始图像:重新加载或存储原始图像,并在需要时恢复。
- 翻转图像 :使用 OpenCV 的
cv2.flip函数进行水平翻转。 - 旋转图像 :使用 OpenCV 的
cv2.getRotationMatrix2D和cv2.warpAffine函数进行旋转。
- 灰度图 :使用 OpenCV 的
- 更新显示 :
- 每当用户点击按钮时,调用相应的图像处理函数,更新存储的图像,并刷新
QLabel上的显示。
- 每当用户点击按钮时,调用相应的图像处理函数,更新存储的图像,并刷新
涉及到的函数方法
cv2.imread(filepath): 加载图像。cv2.cvtColor(image, cv2.COLOR_BGR2GRAY): 将图像转换为灰度图。cv2.flip(image, 1): 水平翻转图像。cv2.getRotationMatrix2D(center, angle, scale): 获取旋转矩阵。cv2.warpAffine(image, rotation_matrix, (width, height)): 使用旋转矩阵旋转图像。QImage(data, width, height, format): 将图像数据转换为QImage。QPixmap.fromImage(image): 将QImage转换为QPixmap。QLabel.setPixmap(pixmap): 设置QLabel的图像。
代码实现
python
import sys
import cv2
from PyQt6.QtWidgets import QApplication, QMainWindow, QLabel, QPushButton, QVBoxLayout, QWidget
from PyQt6.QtGui import QImage, QPixmap
from PyQt6.QtCore import Qt
import numpy as np
class ImageProcessor(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Image Processor")
self.setGeometry(100, 100, 800, 600)
self.original_image = cv2.imread('path_to_your_image.jpg')
self.current_image = self.original_image.copy()
self.qimage = self.convert_cv_qt(self.current_image)
self.image_label = QLabel(self)
self.image_label.setPixmap(QPixmap.fromImage(self.qimage))
self.image_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
self.gray_button = QPushButton('Gray Scale')
self.restore_button = QPushButton('Restore Original')
self.flip_button = QPushButton('Flip Image')
self.rotate_button = QPushButton('Rotate Image')
self.gray_button.clicked.connect(self.convert_to_gray)
self.restore_button.clicked.connect(self.restore_original)
self.flip_button.clicked.connect(self.flip_image)
self.rotate_button.clicked.connect(self.rotate_image)
layout = QVBoxLayout()
layout.addWidget(self.image_label)
layout.addWidget(self.gray_button)
layout.addWidget(self.restore_button)
layout.addWidget(self.flip_button)
layout.addWidget(self.rotate_button)
container = QWidget()
container.setLayout(layout)
self.setCentralWidget(container)
def convert_cv_qt(self, cv_img):
rgb_image = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB)
h, w, ch = rgb_image.shape
bytes_per_line = ch * w
convert_to_Qt_format = QImage(rgb_image.data, w, h, bytes_per_line, QImage.Format.Format_RGB888)
return convert_to_Qt_format
def update_image_display(self):
self.qimage = self.convert_cv_qt(self.current_image)
self.image_label.setPixmap(QPixmap.fromImage(self.qimage))
def convert_to_gray(self):
self.current_image = cv2.cvtColor(self.current_image, cv2.COLOR_BGR2GRAY)
# Convert back to BGR for compatibility (if needed)
self.current_image = cv2.cvtColor(self.current_image, cv2.COLOR_GRAY2BGR)
self.update_image_display()
def restore_original(self):
self.current_image = self.original_image.copy()
self.update_image_display()
def flip_image(self):
"""Flip the image horizontally"""
self.current_image = cv2.flip(self.current_image, 1)
self.update_image_display()
def rotate_image(self):
"""Rotate the image by 90 degrees"""
(h, w) = self.current_image.shape[:2]
center = (w // 2, h // 2)
rotation_matrix = cv2.getRotationMatrix2D(center, 90, 1.0)
self.current_image = cv2.warpAffine(self.current_image, rotation_matrix, (w, h))
self.update_image_display()
if __name__ == '__main__':
app = QApplication(sys.argv)
window = ImageProcessor()
window.show()
sys.exit(app.exec())
效果展示
QQ20241228-94934-HD
二、创建一个 PyQt 应用程序,该应用程序能够:
- 使用 OpenCV 加载一张彩色图像,并在 PyQt 的窗口中显示它。
- 提供一个滑动条(QSlider),允许用户调整图像的亮度。
- 当用户调整滑动条时,实时更新窗口中显示的图像亮度。
- 添加另一个滑动条(QSlider),允许用户调整图像的对比度。
- 当用户调整滚动条时,实时更新窗口中显示的图像对比度。
- 提供一个按钮(QPushButton),允许用户将图像保存为新的文件。
- 当用户点击保存按钮时,将调整后的图像保存到指定的路径,OpenCV中使用cv2.imwrite()来保存图片。
思路分析
- 创建 PyQt 应用程序 :
- 使用
QApplication创建应用程序实例。 - 使用
QMainWindow或QWidget创建主窗口。
- 使用
- 加载和显示图像 :
- 使用 OpenCV (
cv2.imread()) 加载彩色图像。 - 将 OpenCV 图像(NumPy 数组)转换为 QImage,以便在 PyQt 中显示。
- 使用
QLabel来显示 QImage。
- 使用 OpenCV (
- 实现亮度调整 :
- 添加一个
QSlider用于亮度调整。 - 连接滑动条的
valueChanged信号到一个槽函数,该槽函数根据滑动条的值调整图像的亮度。 - 亮度调整可以通过将每个像素值加上一个偏移量来实现。
- 添加一个
- 实现对比度调整 :
- 添加另一个
QSlider用于对比度调整。 - 连接滑动条的
valueChanged信号到一个槽函数,该槽函数根据滑动条的值调整图像的对比度。 - 对比度调整可以通过线性变换(如
new_pixel = alpha * (old_pixel - 127) + 127)来实现,其中alpha是对比度因子。
- 添加另一个
- 保存图像 :
- 添加一个
QPushButton用于保存图像。 - 连接按钮的
clicked信号到一个槽函数,该槽函数使用 OpenCV 的cv2.imwrite()保存调整后的图像。
- 添加一个
设计到的函数方法
cv2.imread(): 加载图像。cv2.cvtColor(): 转换图像颜色空间(如从 BGR 到 RGB)。QImage(): 创建 QImage 对象。QSlider(): 创建滑动条。QPushButton(): 创建按钮。QLabel(): 创建标签用于显示图像。QVBoxLayout()/QHBoxLayout(): 布局管理器。valueChanged信号: 捕捉滑动条值的变化。clicked信号: 捕捉按钮点击事件。cv2.imwrite(): 保存图像。
代码实现
python
import sys
import cv2
from PyQt6.QtWidgets import QApplication, QMainWindow, QSlider, QVBoxLayout, QWidget, QPushButton, QLabel
from PyQt6.QtGui import QImage, QPixmap
from PyQt6.QtCore import Qt
class ImageProcessor(QMainWindow):
def __init__(self):
super().__init__()
# 加载图像
self.image_path = 'C:\\Users\\lilba\\Desktop\\1228.jpg'
self.image = cv2.imread(self.image_path)
if self.image is None:
print(f"Error: Unable to load image at {self.image_path}")
sys.exit(1)
self.brightness = 0
self.contrast = 1
self.initUI()
def initUI(self):
self.setWindowTitle('Image Processor')
self.setGeometry(100, 100, 800, 600)
self.central_widget = QWidget()
self.setCentralWidget(self.central_widget)
self.layout = QVBoxLayout()
self.central_widget.setLayout(self.layout)
self.image_label = QLabel()
self.layout.addWidget(self.image_label)
self.brightness_slider = QSlider()
self.brightness_slider.setOrientation(Qt.Orientation.Vertical)
self.brightness_slider.setMinimum(-100)
self.brightness_slider.setMaximum(100)
self.brightness_slider.setValue(0)
self.brightness_slider.valueChanged.connect(self.updateBrightness)
self.layout.addWidget(self.brightness_slider)
self.contrast_slider = QSlider()
self.contrast_slider.setOrientation(Qt.Orientation.Vertical)
self.contrast_slider.setMinimum(1)
self.contrast_slider.setMaximum(10)
self.contrast_slider.setValue(1)
self.contrast_slider.valueChanged.connect(self.updateContrast)
self.layout.addWidget(self.contrast_slider)
self.save_button = QPushButton('保存图像')
self.save_button.clicked.connect(self.saveImage)
self.layout.addWidget(self.save_button)
self.updateImageLabel()
def updateImageLabel(self):
# 调整图像亮度和对比度
adjusted_image = cv2.convertScaleAbs(self.image, alpha=self.contrast, beta=self.brightness)
adjusted_image = cv2.cvtColor(adjusted_image, cv2.COLOR_BGR2RGB)
# 将 OpenCV 图像转换为 QImage
height, width, channel = adjusted_image.shape
bytes_per_line = 3 * width
q_image = QImage(adjusted_image.data, width, height, bytes_per_line, QImage.Format.Format_RGB888)
# 确保 QImage 不在调整后被释放
q_image = q_image.copy()
# 将 QImage 转换为 QPixmap
pixmap = QPixmap.fromImage(q_image)
# 在 QLabel 上显示 QPixmap
self.image_label.setPixmap(pixmap)
def updateBrightness(self, value):
self.brightness = value
self.updateImageLabel()
def updateContrast(self, value):
self.contrast = value / 5.0 * 4 + 1
self.updateImageLabel()
def saveImage(self):
adjusted_image = cv2.convertScaleAbs(self.image, alpha=self.contrast, beta=self.brightness)
cv2.imwrite('adjusted_image.jpg', adjusted_image)
print("Image saved as adjusted_image.jpg")
if __name__ == '__main__':
app = QApplication(sys.argv)
window = ImageProcessor()
window.show()
sys.exit(app.exec())
效果展示
QQ20241228-103924
三、创建一个 PyQt 应用程序,该应用程序能够:
- 使用 OpenCV 加载一张图像。
- 在 PyQt 的窗口中显示这张图像。
- 提供一个下拉列表(QComboBox),对图像做(模糊、锐化、边缘检测)处理:
- 模糊------使用cv2.GaussianBlur()实现
- 锐化------使用cv2.Laplacian()、cv2.Sobel()实现
- 边缘检测------使用cv2.Canny()实现
- 当用户点击下拉列表选项时,相应地更新窗口中显示的图像。
- 提供一个按钮,当用户点击按钮时,能保存调整后的图像。
思路分析
- 初始化 PyQt 应用程序 :
- 创建一个基本的 PyQt 应用程序窗口。
- 设置窗口标题和大小。
- 加载图像 :
- 使用 OpenCV 加载图像。
- 将图像从 BGR 格式转换为 RGB 格式(因为 PyQt 使用 RGB 格式)。
- 显示图像 :
- 使用 QLabel 来显示图像。
- 将图像转换为 QPixmap 格式以便在 QLabel 中显示。
- 创建下拉列表(QComboBox) :
- 添加选项:"模糊"、"锐化"、"边缘检测"。
- 连接 QComboBox 的信号(currentIndexChanged)到槽函数,以便在用户选择选项时更新图像。
- 图像处理 :
- 根据用户选择的选项,使用 OpenCV 对图像进行相应处理。
- 更新 QLabel 中显示的图像。
- 保存图像 :
- 提供一个 QPushButton,当用户点击时,保存当前显示的图像。
- 使用 QFileDialog 让用户选择保存路径。
设计到的函数方法
cv2.imread():加载图像。cv2.cvtColor():转换图像颜色格式。cv2.GaussianBlur():对图像进行高斯模糊。cv2.Laplacian()和cv2.Sobel():对图像进行锐化。cv2.Canny():进行边缘检测。QImage()和QPixmap():在 PyQt 中处理和显示图像。QComboBox():创建下拉列表。QPushButton():创建按钮。QFileDialog():打开文件保存对话框。
代码实现
python
import sys
import cv2
from PyQt6.QtWidgets import QApplication, QMainWindow, QComboBox, QVBoxLayout, QWidget, QPushButton, QLabel, QFileDialog
from PyQt6.QtGui import QImage, QPixmap
class ImageProcessor(QMainWindow):
def __init__(self):
super().__init__()
# 加载图像,确保图像路径正确或添加错误处理
self.image_path = 'C:\\Users\\lilba\\Desktop\\1228.jpg'
self.image = cv2.imread(self.image_path)
if self.image is None:
print(f"Error: Unable to load image at {self.image_path}")
sys.exit(1)
self.initUI()
def initUI(self):
self.setWindowTitle('Image Processor')
self.setGeometry(100, 100, 800, 600)
self.central_widget = QWidget()
self.setCentralWidget(self.central_widget)
self.layout = QVBoxLayout()
self.central_widget.setLayout(self.layout)
self.image_label = QLabel()
self.layout.addWidget(self.image_label)
self.processing_combobox = QComboBox()
self.processing_combobox.addItems(['模糊', '锐化', '边缘检测'])
self.processing_combobox.currentIndexChanged.connect(self.updateImage)
self.layout.addWidget(self.processing_combobox)
self.save_button = QPushButton('保存图像')
self.save_button.clicked.connect(self.saveImage)
self.layout.addWidget(self.save_button)
self.updateImageLabel()
def updateImageLabel(self):
# 根据下拉列表选项处理图像
processing_option = self.processing_combobox.currentText()
processed_image = self.image.copy() # 从原始图像复制,避免修改原始数据
if processing_option == '模糊':
processed_image = cv2.GaussianBlur(processed_image, (5, 5), 0)
elif processing_option == '锐化':
processed_image = cv2.Laplacian(processed_image, cv2.CV_64F)
processed_image = cv2.convertScaleAbs(processed_image)
elif processing_option == '边缘检测':
processed_image = cv2.Canny(processed_image, 100, 200)
# 将 OpenCV 图像转换为 QImage
processed_image = cv2.cvtColor(processed_image, cv2.COLOR_BGR2RGB)
height, width, channel = processed_image.shape
bytes_per_line = 3 * width
q_image = QImage(processed_image.data, width, height, bytes_per_line, QImage.Format.Format_RGB888)
# 将 QImage 转换为 QPixmap
pixmap = QPixmap.fromImage(q_image)
# 在 QLabel 上显示 QPixmap
self.image_label.setPixmap(pixmap)
def updateImage(self, index):
self.updateImageLabel()
def saveImage(self):
# 保存调整后的图像
processing_option = self.processing_combobox.currentText()
processed_image = self.image.copy() # 从原始图像复制
if processing_option == '模糊':
processed_image = cv2.GaussianBlur(processed_image, (5, 5), 0)
elif processing_option == '锐化':
processed_image = cv2.Laplacian(processed_image, cv2.CV_64F)
processed_image = cv2.convertScaleAbs(processed_image)
elif processing_option == '边缘检测':
processed_image = cv2.Canny(processed_image, 100, 200)
# 使用文件对话框选择保存路径
options = QFileDialog.Options()
file_path, _ = QFileDialog.getSaveFileName(self, "保存图像", "", "JPEG Files (*.jpg);;PNG Files (*.png)",
options=options)
if file_path:
cv2.imwrite(file_path, processed_image)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = ImageProcessor()
window.show()
sys.exit(app.exec())
效果展示
QQ20241228-112315