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())  # 进入应用的事件循环

四、效果展示

原始界面

灰度化

恢复

翻转

旋转

亮度

对比度

模糊

锐化

边缘检测

保存

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/944399.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

mac中idea中英文版本切换

1.快捷键command,或者 2.找到插件(plugins),搜索chinese,安装 第一次安装好点击应用会提示重启,直接重启就好了,如果已经安装过,只需要切换中英文 3.中英文切换 外观与行为&#xf…

linux 7.6安装mysql 8.0步骤如下

linux 7.6安装mysql 8.0步骤如下: 注意:在导入密钥的时候这个不行,可更换为 rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2023

GEE云计算、多源遥感、高光谱遥感技术蓝碳储量估算;红树林植被指数计算及提取

大气温室气体浓度不断增加,导致气候变暖加剧,随之会引发一系列气象、生态和环境灾害。如何降低温室气体浓度和应对气候变化已成为全球关注的焦点。海洋是地球上最大的“碳库”,“蓝碳”即海洋活动以及海洋生物(特别是红树林、盐沼和海草&…

头部固定的响应式jQuery表格插件

jquery.fixme是一款头部固定的响应式jQuery表格插件。该表格通过jQuery来构造固定的表格头效果&#xff0c;在页面向下滚动时&#xff0c;表格头固定在页面的顶部。 在线预览 下载 使用方法 HTML结构 该表格的HTML结构使用标准的HTML表格的结构&#xff1a; <table clas…

系统思考—冰山模型

“卓越不是因机遇而生&#xff0c;而是智慧的选择与用心的承诺。”—— 亚里士多德 卓越&#xff0c;从来不是一次性行为&#xff0c;而是一种习惯。正如我们在日常辅导中常提醒自己&#xff1a;行为的背后&#xff0c;隐藏着选择的逻辑&#xff0c;而选择的根源&#xff0c;源…

基于aspose.words组件的word bytes转pdf bytes,去除水印和解决linux中文乱码问题

详情见 https://preferdoor.top/archives/ji-yu-aspose.wordszu-jian-de-word-byteszhuan-pdf-bytes

文档大师:打造一站式 Word 报告解决方案1

前言 在政府、医院、银行、财务以及销售等领域&#xff0c;常常需要创建各种报告文件来展开工作汇报&#xff0c;譬如季度销售报告、年度总结报告、体检报告和保险合同等。在没有报表工具支持之前&#xff0c;这类报告主要通过 Word 制作&#xff0c;费时费力且难以维护&#…

不安全物联网的轻量级加密:综述

Abstract 本文综述了针对物联网&#xff08;IoT&#xff09;的轻量级加密解决方案。这项综述全面覆盖了从轻量级加密方案到不同类型分组密码的比较等多个方面。同时&#xff0c;还对硬件与软件解决方案之间的比较进行了讨论&#xff0c;并分析了当前最受信赖且研究最深入的分组…

实现某海外大型车企(T)Cabin Wi-Fi 需求的概述 - 4

大家好&#xff0c;我是Q&#xff0c;邮箱&#xff1a;1042484520qq.com。 今天我们在上几讲的基础上再扩展下 Cabin Wi-Fi 的功能需求&#xff0c;讲讲如何使能 5G TCU Wi-Fi STA Bridge 模式。 参考&#xff1a; 实现某海外大型车企&#xff08;T&#xff09;Cabin Wi-Fi 需求…

当视觉提示调优遇到无源领域自适应语义分割

首先将源预训练骨干与冻结参数分为多个阶段&#xff0c;并提出了一个轻量级的提示适配器&#xff0c;用于渐进地将信息性知识编码为提示&#xff0c;并增强相邻骨干阶段之间目标特征的泛化。 同时&#xff0c;设计了一种具有多尺度一致性损失的新型自适应伪标签校正策略&#x…

40.2 预聚合和prometheus-record使用

本节重点介绍 : downsample降采样可以降低查询数据量 prometheus原生不支持downsample 实时查询/聚合 VS 预查询/聚合的优缺点 实时查询/聚合条件随意组合&#xff0c;性能差预查询/聚合 性能好&#xff0c;聚合条件需要提前定义 prometheus的预查询/聚合配置举例 downsample…

Docker安装GPUStack详细教程

目录 前置条件 安装Nvidia Container Tooikit 前置条件 DockerNvidia Container Toolkit 安装Nvidia Container Tooikit 1.安装必要的包 # 更新系统 sudo apt update && sudo apt upgrade -y# 安装 CUDA 相关包 sudo apt-get install -y cuda-drivers nvidia-cuda-…

Intent--组件通信

组件通信1 获取子活动的返回值 创建Activity时实现自动注册&#xff01;【Activity必须要注册才能使用】 默认 LinearLayout 布局&#xff0c;注意 xml 中约束布局的使用&#xff1b; 若需要更改 线性布局 只需要将标签更改为 LinearLayout 即可&#xff0c;记得 设置线性布局…

overleaf中文生僻字显示不正确,显示双线F

我是不想换全文字体的&#xff0c;只是一个生僻字显示不出来&#xff0c;就想要像word一样&#xff0c;把这个生僻字用包含这个生僻字的字体来显示就好了。 解决步骤&#xff1a; 1、使用如下宏包&#xff1a; \usepackage{xeCJK} %声明宏包&#xff0c;主要用于支持在XeTeX…

info There appears to be trouble with your network connection. Retrying

这个错误信息表明你在使用包管理器安装项目依赖时遇到了网络连接问题。 可能的解决方法&#xff1a; 检查当前node.js版本是否过低。 建议使用当前长期支持版本 yarn的淘宝镜像&#xff1a;yarn的淘宝镜像-CSDN博客 nvm常用命令:NVM常用命令-CSDN博客 下载 | Node.js 中文…

使用 HTML 和 CSS 实现绚丽的节日烟花效果

文章目录 1. 效果预览2. 核心技术栈3. 核心代码解读3.1 HTML结构3.2 霓虹文字的CSS样式3.2.1 核心样式代码3.2.2 动画效果 3.3 JavaScript 的烟花效果实现3.3.1 烟花上升3.3.2 粒子爆炸 4. 用户交互5. 运行步骤总结 1. 效果预览 打开后输入文本的展示内容 用户点击页面后播放…

金仓数据库之巡查KCP-客户端验证

巡查 查看KES 服务器的时区 show timezone;查看KES 服务器的时间 select now;查看KES 无故障运行时长 select now-sys_postmaster_start_time as uptime;查看数据库占用的磁盘空间 查看数据库占用的磁盘空间 select sys_database_size(current_database)/1024/1024; sele…

二分和离散化

为什么把二分和离散化放一起&#xff1a;因为离散化其实是一种二分整数的过程。 二分 相信大家都接触过二分查找&#xff08;折半查找&#xff09;&#xff0c;这就是二分的思想。 二分通过每次舍弃一半并不存在答案的区间&#xff0c;进而快速锁定要求的答案&#xff08;二…

OpenCV-Python实战(9)——滤波降噪

一、均值滤波器 cv2.blur() img cv2.blur(src*,ksize*,anchor*,borderType*)img&#xff1a;目标图像。 src&#xff1a;原始图像。 ksize&#xff1a;滤波核大小&#xff0c;&#xff08;width&#xff0c;height&#xff09;。 anchor&#xff1a;滤波核锚点&#xff0c…

Java MySQL 连接

Java MySQL 连接 本章节我们为大家介绍 Java 如何使用 使用 JDBC 连接 MySQL 数据库。 Java 连接 MySQL 需要驱动包&#xff0c;最新版下载地址为&#xff1a;http://dev.mysql.com/downloads/connector/j/&#xff0c;解压后得到 jar 库文件&#xff0c;然后在对应的项目中导…