美丽的神话 发表于 2025-1-1 16:27:33

pyQT + OpenCV相关训练

一、设计思路

1、思路分析与设计

        本段代码是一个使用 PyQt6 和 OpenCV 创建的图像处理应用步伐。其重要功能是通过一个图形界面让用户对图片进行基本的图像处理操作,如灰度化、翻转、旋转、亮度与对比度调整,以及一些滤镜效果(模糊、锐化、边缘检测等)。应用步伐的核心思想是将图像通过差异的算法进行处理,并通过一个图形用户界面与用户进行交互。

2、重要设计思路:

界面设计:

        通过 PyQt6 提供的 QWidget 底子类构建一个窗口界面。
        在界面中使用了 QLabel 显示图像,使用 QPushButton 实现用户操作按钮,使用 QSlider 控制图像亮度和对比度,使用 QComboBox 提供滤镜选择。
图像加载与转换:

        使用 OpenCV 的 cv2.imread() 函数加载图像。
        将 OpenCV 中使用的 BGR 图像格式转换为适合 PyQt6 显示的 RGB 格式,并将其转换为 QImage,然后再转换为 QPixmap 显示在 QLabel 上。
事件与信号槽机制:

        通过 PyQt6 提供的信号-槽机制将 GUI 元素(如按钮、滑块、下拉框)与对应的处理函数进行关联。
        点击按钮或滑动滑块时,步伐会相应地调用相应的图像处理函数,处理后的图像通过更新 QLabel 的显示内容反馈给用户。
图像处理:

        灰度化:将图片转换为灰度图像,通过 cv2.cvtColor() 函数实现。
        翻转:通过 cv2.flip() 函数实现水平翻转。
        旋转:通过 cv2.getRotationMatrix2D() 和 cv2.warpAffine() 函数实现图片的旋转。
        亮度与对比度调整:通过滑块获取当前值,对图像进行线性亮度和对比度调整。
        滤镜处理:通过下拉框选择差异的滤镜效果,如模糊、锐化、边缘检测等,使用 OpenCV 中的相应函数(如 cv2.blur()、cv2.GaussianBlur()、cv2.Canny())处理图像。
保存图片:

        用户可以通过按钮将处理后的图像保存到当地。

二、设计到的函数方法

1. Qimg(self, img)

功能:将 OpenCV 图像格式(BGR)转换为 PyQt6 可以显示的格式(RGB 和 QImage)。
实现:
        使用 cv2.cvtColor() 将图像从 BGR 转换为 RGB 格式。
        使用 QImage 类构造图像对象,准备好用于显示。

2. gray_image(self)

功能:将图像转换为灰度图像并更新显示。
实现:
        使用 cv2.cvtColor() 将图像转换为灰度图。
        更新 QLabel 中显示的图像。

3. rec(self)

功能:恢复原图,重新加载图片。
实现:
        使用 cv2.imread() 重新加载原始图片并更新显示。

4. flip(self)

功能:翻转图像(水平翻转)。
实现:
        使用 cv2.flip() 实行水平翻转。
        更新显示的图像。

5. warp(self)

功能:旋转图像(90度旋转)。
实现:
        使用 cv2.getRotationMatrix2D() 和 cv2.warpAffine() 进行旋转。
        更新显示的图像。

6. bright(self)

功能:调整图像的亮度和对比度。
实现:
        获取滑块的值,计算出相应的亮度和对比度调整系数。
        使用这些系数调整图像的像素值,并更新显示。

7. save(self)

功能:保存当前图像到当地文件。
实现:
        使用 cv2.imwrite() 保存图像。

8. dispose(self)

功能:根据选择的滤镜效果(模糊、锐化、边缘检测)处理图像。
实现:
        使用下拉框选择差异的滤镜效果,并根据选择的内容应用相应的图像处理方法。

三、代码

import cv2
import numpy as np

import sys

from PyQt6 import uic
from PyQt6.QtGui import QPixmap, QImage
from PyQt6.QtWidgets import QWidget, QApplication, QLabel, QPushButton, QSlider, QComboBox


# 创建一个继承自QWidget的自定义窗口类
class MyWidget(QWidget):
    def __init__(self):
      super().__init__()

      # 加载并初始化UI文件
      ui = uic.loadUi("./Form.ui", self)

      # 加载初始图片,并为其创建副本和QImage对象
      self.img = cv2.imread("../demo.png")# 读取图片
      self.img_2 = self.img.copy()# 创建图片副本,用于亮度和对比度调整
      self.q_img = self.Qimg(self.img)# 将OpenCV格式的图像转换为QImage格式

      # 初始化UI组件,包括标签、按钮、滑块等
      self.label: QLabel = ui.label
      self.pushButton: QPushButton = ui.pushButton
      self.pushButton_2: QPushButton = ui.pushButton_2
      self.pushButton_3: QPushButton = ui.pushButton_3
      self.pushButton_4: QPushButton = ui.pushButton_4

      self.horizontalSlider: QSlider = ui.horizontalSlider# 亮度滑块
      self.horizontalSlider.setRange(0, 50)# 设置亮度调整范围
      self.horizontalSlider.setValue(0)# 设置默认亮度值为0

      self.horizontalSlider_2: QSlider = ui.horizontalSlider_2# 对比度滑块
      self.horizontalSlider_2.setRange(1, 100)# 设置对比度调整范围
      self.horizontalSlider_2.setValue(1)# 设置默认对比度值为1

      self.pushButton_5: QPushButton = ui.pushButton_5# 保存按钮
      self.comboBox: QComboBox = ui.comboBox# 下拉框,用于选择滤镜效果

      # 连接按钮的点击事件到相应的槽函数
      self.pushButton.clicked.connect(self.gray_image)# 点击“灰度化”按钮
      self.pushButton_2.clicked.connect(self.rec)# 点击“恢复”按钮
      self.pushButton_3.clicked.connect(self.flip)# 点击“翻转”按钮
      self.pushButton_4.clicked.connect(self.warp)# 点击“旋转”按钮
      self.horizontalSlider.valueChanged.connect(self.bright)# 亮度滑块改变时
      self.horizontalSlider_2.valueChanged.connect(self.bright)# 对比度滑块改变时
      self.pushButton_5.clicked.connect(self.save)# 点击“保存”按钮
      self.comboBox.currentIndexChanged.connect(self.dispose)# 选择滤镜时

      # 为下拉框添加滤镜选项
      list1 = [' ','模糊', '锐化', '边缘检测']
      self.comboBox.addItems(list1)

      # 将QImage转换为QPixmap并设置为label的图片显示
      self.label.setPixmap(QPixmap.fromImage(self.q_img))
      self.label.setScaledContents(True)# 设置图片自适应标签大小

      # 设置标志位,用于判断是否已经应用灰度化
      self.slot = False

    # 图片转换函数,将OpenCV格式的BGR图片转换为QImage格式
    def Qimg(self, img):
      img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)# 将BGR图像转换为RGB
      h, w, c = img_rgb.shape# 获取图像的高度、宽度和通道数
      bytes_per_line = c * w# 每行字节数
      q_img = QImage(img_rgb.data, w, h, bytes_per_line, QImage.Format.Format_RGB888)# 转换为QImage
      return q_img

    # 定义将图片灰度化的按钮响应函数
    def gray_image(self):
      if not self.slot:# 判断是否已经灰度化过
            self.img = cv2.cvtColor(self.img, cv2.COLOR_BGR2GRAY)# 将图片转换为灰度图
            q_img = self.Qimg(self.img)# 转换为QImage格式
            self.label.setPixmap(QPixmap.fromImage(q_img))# 更新显示的图片
            self.slot = True# 更新标志位,表示已经灰度化

    # 定义恢复原图的按钮响应函数
    def rec(self):
      self.img = cv2.imread('../demo.png')# 重新加载原始图片
      self.q_img = self.Qimg(self.img)# 转换为QImage格式
      self.label.setPixmap(QPixmap(self.q_img))# 更新显示的图片
      self.slot = False# 重置标志位,表示恢复为原图

    # 定义图片翻转的按钮响应函数
    def flip(self):
      self.img = cv2.flip(self.img, 1)# 进行水平翻转
      self.q_img = self.Qimg(self.img)# 转换为QImage格式
      self.label.setPixmap(QPixmap.fromImage(self.q_img))# 更新显示的图片

    # 定义图片旋转的按钮响应函数
    def warp(self):
      M = cv2.getRotationMatrix2D((self.img.shape / 2, self.img.shape / 2), 90, 1)# 获取旋转矩阵
      self.img = cv2.warpAffine(self.img, M, (self.img.shape, self.img.shape))# 应用旋转
      self.q_img = self.Qimg(self.img)# 转换为QImage格式
      self.label.setPixmap(QPixmap.fromImage(self.q_img))# 更新显示的图片

    # 定义亮度和对比度调整的函数
    def bright(self):
      brightness = self.horizontalSlider.value()# 获取当前亮度值
      contrast = self.horizontalSlider_2.value() / 100 + 1# 获取当前对比度值,范围在1到2之间

      img_copy = contrast * self.img_2 + brightness# 应用对比度和亮度调整
      img_copy = np.clip(img_copy, 0, 255)# 保证像素值在0到255之间
      img_copy = np.uint8(img_copy)# 转换为无符号8位整数类型
      self.img = img_copy# 更新图片
      self.q_img = self.Qimg(self.img)# 转换为QImage格式
      self.label.setPixmap(QPixmap.fromImage(self.q_img))# 更新显示的图片

    # 定义保存图片的函数
    def save(self):
      cv2.imwrite('./img.png', self.img)# 保存当前图片到本地文件

    # 根据选择的滤镜效果处理图片
    def dispose(self):
    # - 模糊——使用cv2.GaussianBlur()实现
    # - 锐化——使用cv2.Laplacian()、cv2.Sobel()实现
    # - 边缘检测——使用cv2.Canny()实现
      if self.comboBox.currentText() == ' ':
            self.rec()
      elif self.comboBox.currentText() == '模糊':
            self.img = cv2.GaussianBlur(self.img, (5, 5), 0)
            self.q_img = self.Qimg(self.img)# 转换为QImage格式
            self.label.setPixmap(QPixmap.fromImage(self.q_img))
      elif self.comboBox.currentText() == '锐化':
            self.img = cv2.Laplacian(self.img, cv2.CV_64F)
            self.img = cv2.convertScaleAbs(self.img)
            self.q_img = self.Qimg(self.img)# 转换为QImage格式
            self.label.setPixmap(QPixmap.fromImage(self.q_img))# 更新显示的图片
      elif self.comboBox.currentText() =='边缘检测':
            M = cv2.Canny(self.img, 100, 200)# 应用Canny边缘检测算法
            contours, h = cv2.findContours(M, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)# 查找轮廓
            self.img = cv2.drawContours(self.img, contours, -1, (0, 255, 0), 3)# 绘制轮廓
            self.q_img = self.Qimg(self.img)# 转换为QImage格式
            self.label.setPixmap(QPixmap.fromImage(self.q_img))# 更新显示的图片



# 主程序入口
if __name__ == '__main__':
    app = QApplication(sys.argv)# 创建应用对象
    myWidget = MyWidget()# 创建自定义窗口对象
    myWidget.show()# 显示窗口
    sys.exit(app.exec())# 进入应用的事件循环

四、效果展示

原始界面
https://i-blog.csdnimg.cn/direct/aadae45f9b0b4a91b78b7046d6000dd4.png

灰度化
https://i-blog.csdnimg.cn/direct/13c2e95642f64844966dd5c5b32042e2.png

恢复
https://i-blog.csdnimg.cn/direct/7ee2f5070e734bc7b50258a53efc4fd7.png

翻转
https://i-blog.csdnimg.cn/direct/19afd46de23148b7845b9dd9c9462660.png

旋转
https://i-blog.csdnimg.cn/direct/2464b20947f64fc8bbc13f0652cf4f06.png

亮度
https://i-blog.csdnimg.cn/direct/ece4c0fec0bf4b68be2df71d2fda6ef2.png

对比度
https://i-blog.csdnimg.cn/direct/d7f1194b32b8449d9d8e1698ebbbbfa1.png

模糊
https://i-blog.csdnimg.cn/direct/f14bfc078deb44c4b02e9337a84a2410.png

锐化
https://i-blog.csdnimg.cn/direct/c6145793b835454d890fab1a3f22ed5a.png

边缘检测
https://i-blog.csdnimg.cn/direct/4a14fc07728a484fb96cd537c49eaab7.png

保存
https://i-blog.csdnimg.cn/direct/92c88d46ad704559871879fe04b3f9fb.png






免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: pyQT + OpenCV相关训练