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

相关推荐
深蓝海拓3 小时前
opencv的模板匹配(Template Matching)学习笔记
人工智能·opencv·计算机视觉
美林数据Tempodata3 小时前
李飞飞最新论文深度解读:从语言到世界,空间智能将重写AI的未来十年
人工智能·ai·空间智能
东哥说-MES|从入门到精通3 小时前
数字化部分内容 | 十四五年规划和2035年远景目标纲要(新华社正式版)
大数据·人工智能·数字化转型·mes·数字化工厂·2035·十四五规划
小殊小殊3 小时前
DeepSeek为什么这么慢?
人工智能·深度学习
极客BIM工作室3 小时前
从静态到动态:Sora与文生图潜在扩散模型的技术同异与AIGC演进逻辑
人工智能·aigc
松果财经3 小时前
长沙的青年友好,五年见“城”心
人工智能
秋邱3 小时前
智启未来:AGI 教育融合 × 跨平台联盟 × 个性化空间,重构教育 AI 新范式开篇:一场 “教育 ×AI” 的范式革命
人工智能·python·重构·推荐算法·agi
黑客思维者3 小时前
ChatGPT软件开发提示词库:开发者常用150个中文提示词分类与应用场景设计
人工智能·chatgpt·提示词·软件开发
IT_陈寒3 小时前
React性能优化:这5个Hooks技巧让我减少了40%的重新渲染
前端·人工智能·后端
七牛云行业应用3 小时前
解决 AI 视频角色闪烁与时长限制:基于即梦/可灵的多模型 Pipeline 实战
人工智能·音视频·ai视频