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

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 npimport sysfrom 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.labelself.pushButton: QPushButton = ui.pushButtonself.pushButton_2: QPushButton = ui.pushButton_2self.pushButton_3: QPushButton = ui.pushButton_3self.pushButton_4: QPushButton = ui.pushButton_4self.horizontalSlider: QSlider = ui.horizontalSlider  # 亮度滑块self.horizontalSlider.setRange(0, 50)  # 设置亮度调整范围self.horizontalSlider.setValue(0)  # 设置默认亮度值为0self.horizontalSlider_2: QSlider = ui.horizontalSlider_2  # 对比度滑块self.horizontalSlider_2.setRange(1, 100)  # 设置对比度调整范围self.horizontalSlider_2.setValue(1)  # 设置默认对比度值为1self.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图像转换为RGBh, 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)  # 转换为QImagereturn 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())  # 进入应用的事件循环

四、效果展示

原始界面

灰度化

恢复

翻转

旋转

亮度

对比度

模糊

锐化

边缘检测

保存

相关文章:

pyQT + OpenCV相关练习

一、设计思路 1、思路分析与设计 本段代码是一个使用 PyQt6 和 OpenCV 创建的图像处理应用程序。其主要功能是通过一个图形界面让用户对图片进行基本的图像处理操作,如灰度化、翻转、旋转、亮度与对比度调整,以及一些滤镜效果(模糊、锐化、边…...

音视频入门基础:MPEG2-PS专题(3)——MPEG2-PS格式简介

一、引言 本文对MPEG2-PS格式进行简介。 进行简介之前,请各位先下载MPEG2-PS的官方文档。ITU-T和ISO/IEC都分别提供MPEG2-PS的官方文档。但是ITU提供的文档是免费的,ISO/IEC是付费的,所以我们主要阅读ITU提供的官方文档,比如较新…...

云计算学习架构篇之HTTP协议、Nginx常用模块与Nginx服务实战

一.HTTP协议讲解 1.1rsync服务重构 bash 部署服务端: 1.安装服务 [rootbackup ~]# yum -y install rsync 2.配置服务 [rootbackup ~]# vim /etc/rsyncd.conf uid rsync gid rsync port 873 fake super yes use chroot no max connections 200 timeout 600 ignore erro…...

Zookeeper模式安装Kafka(含常规、容器两种安装方式)

一、#创作灵感# 公司使用Kafka的软件项目较多,故写技术笔记巩固知识要点 二、软件环境 - Kafka 3.9.0 官方下载地址:Kafka 3.9.0 - ZooKeeper 3.9.3 官方下载地址:ZooKeeper 3.9.3 - Docker Desktop 4.37 容器图形化工具 官方下载地址…...

【游戏设计原理】41 - 游戏的核心

1. 如何理解? 这条原理主要在讲述“游戏核心”这一概念的重要性及其在游戏开发中的作用。游戏的核心是指决定游戏整体玩法和体验的核心元素,它通常是游戏的主要机制、目标或动作方式。理解这一原理时,我们可以从以下几个层面来考虑&#xff…...

机器学习算法基础知识1:决策树

机器学习算法基础知识1:决策树 一、本文内容与前置知识点1. 本文内容2. 前置知识点 二、场景描述三、决策树的训练1. 决策树训练方式(1)分类原则-Gini(2)分类原则-entropy(3)加权系数-样本量&am…...

[Qt] 信号和槽(1) | 本质 | 使用 | 自定义

目录 一、信号和槽概述 二、本质 底层实现 1. 函数间的相互调用 2. 类成员中的特殊角色 三、使用 四. 自定义信号和槽 1. 基本语法 (1) 自定义信号函数书写规范 (2) 自定义槽函数书写规范 (3) 发送信号 (4) 示例 A. 示例一 B. 示例二 —— 老师说“上课了”&…...

33. 简易内存池

1、题目描述 ● 请实现一个简易内存池,根据请求命令完成内存分配和释放。 ● 内存池支持两种操作命令,REQUEST和RELEASE,其格式为: ● REQUEST请求的内存大小 表示请求分配指定大小内存,如果分配成功,返回分配到的内存…...

win32汇编环境,对话框程序模版,含文本框与菜单简单功能

;运行效果 ;win32汇编环境,对话框程序模版,含文本框与菜单简单功能 ;直接抄进RadAsm可编译运行。 ;下面为asm文件 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>&g…...

人工智能与传统编程的主要区别是什么?

传统编程:开发者预先编写软件行为规则,代码基于程序员定义逻辑处理输入并产生确定输出,具有确定性、手动编写规则和结构化逻辑特点,如垃圾邮件分类程序基于预设关键词等规则。AI 编程:从数据中学习而非手动编写规则&am…...

实战交易策略 篇十一:一揽子交易策略

文章目录 系列文章适用条件核心策略小额大量投资行业或主题聚焦同步操作优势系列文章 实战交易策略 篇一:奥利弗瓦莱士短线交易策略 实战交易策略 篇二:杰西利弗莫尔股票大作手操盘术策略 实战交易策略 篇三:333交易策略 实战交易策略 篇四:价值投资交易策略 实战交易策略…...

doris 2.1 -Data Manipulation-Transaction

注意:doris 只能控制读一致性,并不能rollback 1 Explicit and Implicit Transactions 1.1 Explicit Transactions 1.1.1 Explicit transactions require users to actively start, commit transactions. Only insert into values statement is supported in 2.1. BEGIN; …...

多模态融合:阿尔茨海默病检测

🍨 本文为🔗365天深度学习训练营 中的学习记录博客🍖 原作者:K同学啊 一、实验介绍 本实验包含 645 名阿尔茨海默病受试者,分为 AD、CN 和 MCI 组,数据集包含 3D MRI 图像与一份CSV数据,MRI数据…...

Ceph 手动部署(CentOS9)

#Ceph手动部署、CentOS9、squid版本、数字版本19.2.0 #部署服务:块、对象、文件 一、部署前规划 1、兼容性确认 2、资源规划 节点类型节点名称操作系统CPU/内存硬盘网络组件安装集群节点CephAdm01CentOS94U/8GOS:40G,OSD:2*100GIP1:192.169.0.9(管理&集群),IP2:…...

家政预约小程序05活动管理

目录 1 搭建活动管理页面2 搭建活动规则页面3 搭建规则新增页面3 配置规则跳转4 搭建活动参与记录总结 上一篇我们介绍了活动管理的表结构设计,本篇我们介绍一下后台功能。 1 搭建活动管理页面 我们一共搭建了三个表,先搭建主表的后台功能。打开我们的后…...

解决安装pynini和WeTextProcessing报错问题

点击这里,访问博客 0. 背景 最近在给别人有偿部署ASR-LLM-TTS项目时遇到安装pynini和WeTextProcessing依赖报错的问题,报错信息如下: IC:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\ucrt" "-IC:\Program Files…...

【PCIe 总线及设备入门学习专栏 4.1 -- PCI 总线的地址空间分配】

文章目录 Overview 本文转自:https://blog.chinaaet.com/justlxy/p/5100053219 Overview PCI 总线具有32位数据/地址复用总线,所以其存储地址空间为 2324GB。也就是PCI上的所有设备共同映射到这4GB上,每个PCI设备占用唯一的一段PCI地址&…...

华为配置 之 RIP

简介: RIP(路由信息协议)是一种广泛使用的内部网关协议,基于距离向量算法来决定路径。它通过向全网广播路由控制信息来动态交换网络拓扑信息,从而计算出最佳路由路径。RIP易于配置和理解,非常适用于小型网络…...

探寻AI Agent:开启知识图谱自动生成新篇章(17/30)

一、AI Agent 与知识图谱:智能时代的双雄 在当今科技飞速发展的时代,人工智能如同一股汹涌澎湃的浪潮,正以前所未有的力量重塑着我们的世界。而在这股浪潮中,AI Agent 与知识图谱无疑是两颗最为璀璨的明珠,它们各自发挥…...

卸载wps后word图标没有变成白纸恢复

这几天下载了个wps教育版,后头用完了删了 用习惯的2019图标 给兄弟我干没了??? 其他老哥说什么卸载关联重新下 ,而且还要什么撤销保存原来的备份什么,兄弟也是不得不怂了 后头就发现了这个半宝藏博主&…...

LeetCode 热题 100_二叉树的直径(40_543_简单_C++)(二叉树;递归)

LeetCode 热题 100_二叉树的直径(40_543) 题目描述:输入输出样例:题解:解题思路:思路一(递归): 代码实现代码实现(思路一(递归)&#…...

【数据结构】线性数据结构——链表

1. 定义 链表是一种线性数据结构,由多个节点(Node)组成。每个节点存储数据和指向下一个节点的指针。与数组不同,链表的节点不需要在内存中连续存储。 2. 特点 动态存储: 链表的大小不固定,可以动态增加或…...

开源存储详解-分布式存储与ceph

ceph体系结构 rados:reliable, autonomous, distributed object storage, rados rados采用c开发 对象存储 ceph严格意义讲只提供对象存储能力,ceph的块存储能力实际是基于对象存储库librados的rbd 对象存储特点 对象存储采用put/get/delete&#xf…...

[算法] [leetcode-509] 斐波那契数

509 斐波那契数 斐波那契数 (通常用 F(n) 表示)形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是: F(0) 0,F(1) 1 F(n) F(n - 1) F(n - 2),其中 n…...

运维人员的Go语言学习路线

以下是一份更为详细的适合运维人员的Go语言学习路线图: 一、基础环境搭建与入门(第 1 - 2 周) 第 1 周 环境搭建 在本地开发机和常用的运维服务器环境(如 Linux 系统)中安装 Go 语言。从官方网站(https://…...

[创业之路-222]:波士顿矩阵与GE矩阵在业务组合选中作用、优缺点比较

目录 一、波士顿矩阵 1、基本原理 2、各象限产品的定义及战略对策 3、应用 4、优点与局限性 二、技术成熟度模型与产品生命周期模型的配对 1、技术成熟度模型 2、产品生命周期模型 3、技术成熟度模型与产品生命周期模型的配对 三、产品生命周期与产品类型的对应关系 …...

安卓入门十一 常用网络协议四

MQTT(Message Queuing Telemetry Transport) MQTT是一种轻量级的、发布/订阅模式的消息传输协议。它被设计用于在低带宽或不稳定网络环境下,实现物联网设备之间的可靠通信。 4.1 MQTT详细介绍 发布/订阅模式:MQTT 使用发布/订…...

《机器学习》——利用OpenCV库中的KNN算法进行图像识别

文章目录 KNN算法介绍下载OpenCV库实验内容实验结果完整代码手写数字传入模型训练 KNN算法介绍 一、KNN算法的基本要素 K值的选择:K值代表选择与新测试样本距离最近的前K个训练样本数,通常K是不大于20的整数。K值的选择对算法结果有重要影响&#xff0c…...

StarRocks 存算分离在得物的降本增效实践

编者荐语: 得物优化数据引擎布局,近期将 4000 核 ClickHouse 迁移至自建 StarRocks,成本降低 40%,查询耗时减半,集群稳定性显著提升。本文详解迁移实践与成果,文末附丁凯剑老师 StarRocks Summit Asia 2024…...

Tube Qualify弯管测量系统在汽车管路三维检测中的应用

从使用量上来说,汽车行业是使用弯管零件数量最大的单一行业。在汽车的燃油,空调,排气,转向,制动等系统中都少不了管路。汽车管件形状复杂,且由于安装空间限制,汽车管件拥有不同弯曲半径&#xf…...