pyQT + OpenCV 的三个练习

一、创建一个 PyQt 应用程序,该应用程序能够:

  1. 使用 OpenCV 加载一张图像。
  2. 在 PyQt 的窗口中显示这张图像。
  3. 提供四个按钮(QPushButton):
  • 一个用于将图像转换为灰度图
  • 一个用于将图像恢复为原始彩色图
  • 一个用于将图像进行翻转
  • 一个用于将图像进行旋转
  • 当用户点击按钮时,相应地更新窗口中显示的图像。

思路分析

  1. 加载图像
    • 使用 OpenCV 加载一张图像,并将其存储为类的一个属性,以便在后续操作中访问。
  2. 显示图像
    • 使用 PyQt6 的 QLabel 来显示图像。
    • 将图像转换为 QPixmap,然后设置为 QLabel 的图像。
  3. 创建按钮
    • 使用 PyQt6 的 QPushButton 创建四个按钮,每个按钮对应一个图像处理功能。
  4. 实现图像处理功能
    • 灰度图 :使用 OpenCV 的 cv2.cvtColor 函数将图像转换为灰度图。
    • 恢复原始图像:重新加载或存储原始图像,并在需要时恢复。
    • 翻转图像 :使用 OpenCV 的 cv2.flip 函数进行水平翻转。
    • 旋转图像 :使用 OpenCV 的 cv2.getRotationMatrix2Dcv2.warpAffine 函数进行旋转。
  5. 更新显示
    • 每当用户点击按钮时,调用相应的图像处理函数,更新存储的图像,并刷新 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 应用程序,该应用程序能够:

  1. 使用 OpenCV 加载一张彩色图像,并在 PyQt 的窗口中显示它。
  2. 提供一个滑动条(QSlider),允许用户调整图像的亮度。
  3. 当用户调整滑动条时,实时更新窗口中显示的图像亮度。
  4. 添加另一个滑动条(QSlider),允许用户调整图像的对比度。
  5. 当用户调整滚动条时,实时更新窗口中显示的图像对比度。
  6. 提供一个按钮(QPushButton),允许用户将图像保存为新的文件。
  7. 当用户点击保存按钮时,将调整后的图像保存到指定的路径,OpenCV中使用cv2.imwrite()来保存图片。

思路分析

  1. 创建 PyQt 应用程序
    • 使用 QApplication 创建应用程序实例。
    • 使用 QMainWindowQWidget 创建主窗口。
  2. 加载和显示图像
    • 使用 OpenCV (cv2.imread()) 加载彩色图像。
    • 将 OpenCV 图像(NumPy 数组)转换为 QImage,以便在 PyQt 中显示。
    • 使用 QLabel 来显示 QImage。
  3. 实现亮度调整
    • 添加一个 QSlider 用于亮度调整。
    • 连接滑动条的 valueChanged 信号到一个槽函数,该槽函数根据滑动条的值调整图像的亮度。
    • 亮度调整可以通过将每个像素值加上一个偏移量来实现。
  4. 实现对比度调整
    • 添加另一个 QSlider 用于对比度调整。
    • 连接滑动条的 valueChanged 信号到一个槽函数,该槽函数根据滑动条的值调整图像的对比度。
    • 对比度调整可以通过线性变换(如 new_pixel = alpha * (old_pixel - 127) + 127)来实现,其中 alpha 是对比度因子。
  5. 保存图像
    • 添加一个 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 应用程序,该应用程序能够:

  1. 使用 OpenCV 加载一张图像。
  2. 在 PyQt 的窗口中显示这张图像。
  3. 提供一个下拉列表(QComboBox),对图像做(模糊、锐化、边缘检测)处理:
  • 模糊------使用cv2.GaussianBlur()实现
  • 锐化------使用cv2.Laplacian()、cv2.Sobel()实现
  • 边缘检测------使用cv2.Canny()实现
  1. 当用户点击下拉列表选项时,相应地更新窗口中显示的图像。
  2. 提供一个按钮,当用户点击按钮时,能保存调整后的图像。

思路分析

  1. 初始化 PyQt 应用程序
    • 创建一个基本的 PyQt 应用程序窗口。
    • 设置窗口标题和大小。
  2. 加载图像
    • 使用 OpenCV 加载图像。
    • 将图像从 BGR 格式转换为 RGB 格式(因为 PyQt 使用 RGB 格式)。
  3. 显示图像
    • 使用 QLabel 来显示图像。
    • 将图像转换为 QPixmap 格式以便在 QLabel 中显示。
  4. 创建下拉列表(QComboBox)
    • 添加选项:"模糊"、"锐化"、"边缘检测"。
    • 连接 QComboBox 的信号(currentIndexChanged)到槽函数,以便在用户选择选项时更新图像。
  5. 图像处理
    • 根据用户选择的选项,使用 OpenCV 对图像进行相应处理。
    • 更新 QLabel 中显示的图像。
  6. 保存图像
    • 提供一个 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

相关推荐
电子基础知识2 小时前
NanoEdge AI Studio入门
人工智能·硬件工程
LeeZhao@2 小时前
【项目】多模态图文理解-GLM-Edge实战
人工智能·yolo·计算机视觉·语言模型·aigc
橙狮科技6 小时前
提示词工程教程:提示词安全
人工智能·安全·自然语言处理
cxr8286 小时前
五类推理(逻辑推理、概率推理、图推理、基于深度学习的推理)的开源库 (二)
人工智能·深度学习
魔理沙偷走了BUG6 小时前
【AI数学基础】线性代数:内积和范数
人工智能·线性代数·机器学习
salsm7 小时前
使用 C++ 和函数式编程构建高效的 AI 模型
c++·人工智能
qq_273900237 小时前
pytorch torch.scatter_reduce函数介绍
人工智能·pytorch·python
MediaTea7 小时前
Ae 效果详解:放大
图像处理·人工智能·深度学习·计算机视觉
小码贾7 小时前
OpenCV-Python实战(15)——像素直方图均衡画
人工智能·python·opencv
网易智企8 小时前
游戏社交趋势下,游戏语音再升级!
人工智能·游戏·音视频·语音识别·实时音视频·信息与通信·通信