当前位置: 首页 > 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图标 给兄弟我干没了??? 其他老哥说什么卸载关联重新下 ,而且还要什么撤销保存原来的备份什么,兄弟也是不得不怂了 后头就发现了这个半宝藏博主&…...

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)

2025年能源电力系统与流体力学国际会议&#xff08;EPSFD 2025&#xff09;将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会&#xff0c;EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版​分享

平时用 iPhone 的时候&#xff0c;难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵&#xff0c;或者买了二手 iPhone 却被原来的 iCloud 账号锁住&#xff0c;这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...

学校招生小程序源码介绍

基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码&#xff0c;专为学校招生场景量身打造&#xff0c;功能实用且操作便捷。 从技术架构来看&#xff0c;ThinkPHP提供稳定可靠的后台服务&#xff0c;FastAdmin加速开发流程&#xff0c;UniApp则保障小程序在多端有良好的兼…...

【Go】3、Go语言进阶与依赖管理

前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课&#xff0c;做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程&#xff0c;它的核心机制是 Goroutine 协程、Channel 通道&#xff0c;并基于CSP&#xff08;Communicating Sequential Processes&#xff0…...

leetcodeSQL解题:3564. 季节性销售分析

leetcodeSQL解题&#xff1a;3564. 季节性销售分析 题目&#xff1a; 表&#xff1a;sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...

【C语言练习】080. 使用C语言实现简单的数据库操作

080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...

C++八股 —— 单例模式

文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全&#xff08;Thread Safety&#xff09; 线程安全是指在多线程环境下&#xff0c;某个函数、类或代码片段能够被多个线程同时调用时&#xff0c;仍能保证数据的一致性和逻辑的正确性&#xf…...

华硕a豆14 Air香氛版,美学与科技的馨香融合

在快节奏的现代生活中&#xff0c;我们渴望一个能激发创想、愉悦感官的工作与生活伙伴&#xff0c;它不仅是冰冷的科技工具&#xff0c;更能触动我们内心深处的细腻情感。正是在这样的期许下&#xff0c;华硕a豆14 Air香氛版翩然而至&#xff0c;它以一种前所未有的方式&#x…...

佰力博科技与您探讨热释电测量的几种方法

热释电的测量主要涉及热释电系数的测定&#xff0c;这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中&#xff0c;积分电荷法最为常用&#xff0c;其原理是通过测量在电容器上积累的热释电电荷&#xff0c;从而确定热释电系数…...