当前位置: 首页 > article >正文

pyQT + OpenCV相关练习

一、设计思路

1、思路分析与设计

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

2、主要设计思路:

界面设计

        通过 PyQt6 提供的 QWidget 基础类构建一个窗口界面。

        在界面中使用了 QLabel 显示图像,使用 QPushButton 实现用户操作按钮,使用 QSlider 控制图像亮度和对比度,使用 QComboBox 提供滤镜选择。

图像加载与转换

        使用 OpenCVcv2.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[1] / 2, self.img.shape[0] / 2), 90, 1)  # 获取旋转矩阵
        self.img = cv2.warpAffine(self.img, M, (self.img.shape[1], self.img.shape[0]))  # 应用旋转
        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())  # 进入应用的事件循环

四、效果展示

原始界面

灰度化

恢复

翻转

旋转

亮度

对比度

模糊

锐化

边缘检测

保存


http://www.kler.cn/a/456743.html

相关文章:

  • 【最新】沃德协会管理系统源码+uniapp前端+环境教程
  • linux中,redis分布式集群搭建
  • Android MQTT关于断开连接disconnect报错原因
  • 计算机网络|数据流向剖析与分层模型详解
  • 如何设置在启动时进入命令行模式彻底删除中文输入法。然后重启仍然是图形界面?
  • mysql的安装下载
  • Debian操作系统相对于Ubuntu有什么优势吗?
  • 集成RabbitMQ+MQ常用操作
  • redis相关数据类型介绍
  • .NET常用的ORM框架及性能优劣分析总结
  • 梳理你的思路(从OOP到架构设计)_介绍Android的Java层应用框架03
  • Web Bluetooth API 开发记录
  • 常见局域网硬件故障诊断
  • linux驱动:6ull(5)自定义根节点
  • flink cdc使用flink sql方式运行一直报Make sure a planner module is on the classpath
  • Linux下基本指令
  • 咖啡即将“从天而降”,无人机外卖时代来袭
  • 【C#设计模式(21)——状态模式(State Pattern)】
  • DVWA安装
  • CSS学习记录20