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

四、效果展示

原始界面

灰度化

恢复

翻转

旋转

亮度

对比度

模糊

锐化

边缘检测

保存

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【数据库初阶】Linux中库的基础操作

🎉博主首页: 有趣的中国人 🎉专栏首页: 数据库初阶 🎉其它专栏: C初阶 | C进阶 | 初阶数据结构 亲爱的小伙伴们,大家好!在这篇文章中,我们将深入浅出地为大家讲解 Linux…

Element Plus 日期时间选择器大于当天时间置灰

效果: 实现思路: 点击官方链接的日期时间选择器的属性查看,发现disabled-date属性 一个用来判断该日期是否被禁用的函数,接受一个 Date 对象作为参数。 应该返回一个 Boolean 值,即用函数返回布尔值。 前言 JavaScrip…

线性直流电流

电阻网络的等效 等效是指被化简的电阻网络与等效电阻具有相同的 u-i 关系 (即端口方程),从而用等效电阻代替电阻网络之后,不 改变其余部分的电压和电流。 串联等效: 并联等效: 星角变换 若这两个三端网络是等效的,从任…

Java与SQL Server数据库连接的实践与要点

本文还有配套的精品资源,点击获取 简介:Java和SQL Server数据库交互是企业级应用开发中的重要环节。本文详细探讨了使用Java通过JDBC连接到SQL Server数据库的过程,包括加载驱动、建立连接、执行SQL语句、处理异常、资源管理、事务处理和连…

【Halcon】例程讲解:基于形状匹配与OCR的多图像处理(附图像、程序下载链接)

1. 开发需求 在参考图像中定义感兴趣区域(ROI),用于形状匹配和文本识别。通过形状匹配找到图像中的目标对象位置。对齐多幅输入图像,使其与参考图像保持一致。在对齐后的图像上进行OCR识别,提取文本和数字信息。以循环…

从0入门自主空中机器人-2-2【无人机硬件选型-PX4篇】

1. 常用资料以及官方网站 无人机飞控PX4用户使用手册(无人机基本设置、地面站使用教程、软硬件搭建等):https://docs.px4.io/main/en/ PX4固件开源地址:https://github.com/PX4/PX4-Autopilot 飞控硬件、数传模块、GPS、分电板等…

Artec Space Spider助力剑桥研究团队解码古代社会合作【沪敖3D】

挑战:考古学家需要一种安全的方法来呈现新出土的陶瓷容器,对比文物形状。 解决方案:Artec Space Spider, Artec Studio 效果:本项目是REVERSEACTION项目的一部分,旨在研究无国家社会中复杂的古代技术。研究团队在考古地…

IPv6 基础协议-NDP

IPv6 基础协议报文 何为基础协议?像v4中的icmp、arp、hdcp之类的 在v6中只需要NDP协议,他是通过ICMPv6报文完成的,她能够实现邻居发现、无状态地址检测、重复地址检测、PMTU等功能 RS(133)RA(134&#x…

数据库原理及应用(MySQL版-李月军)-习题参考答案

数据库原理及应用(MySQL版)-微课视频版 习题参考答案 习 题一 一.选择题 1、D 2、C 3、C 4、B 5、D 6、B 7、A 8、B 9、C 10、A 11、B 12、C 13、①A②B③C 14、①E②B 15、①B②C③B 16、B 17、A 18、D 二.填空题 1、文件…

用Python开启人工智能之旅(四)深度学习的框架和使用方法

第四部分:深度学习的框架和使用方法 用Python开启人工智能之旅(一)Python简介与安装 用Python开启人工智能之旅(二)Python基础 用Python开启人工智能之旅(三)常用的机器学习算法与实现 用Pyt…

洛谷 P1725:琪露诺 ← 单调队列+DP

【题目来源】https://www.luogu.com.cn/problem/P1725【题目描述】 在幻想乡,琪露诺是以笨蛋闻名的冰之妖精。 某一天,琪露诺又在玩速冻青蛙,就是用冰把青蛙瞬间冻起来。但是这只青蛙比以往的要聪明许多,在琪露诺来之前就已经跑到…

win11永久修改pdf默认打开方式

电脑总是重启或过一阵子就自动修改pdf文件打开方式为浏览器打开,按照传统方式 右键→属性,修改打开方式,不好使 得用更根本的方法!打开设置,找到 应用→默认应用 (或者 "winR"打开运行&#xff0…

解密MQTT协议:从QOS到消息传递的全方位解析

1、QoS介绍 1.1、QoS简介 使用MQTT协议的设备大部分都是运行在网络受限的环境下,而只依靠底层的TCP传输协议,并不 能完全保证消息的可靠到达。 MQTT提供了QoS机制,其核心是设计了多种消息交互机制来提供不同的服务质量,来满足…

跨语言数据格式标准化在 HarmonyOS 开发中的实践

文章目录 前言数据格式标准化的意义数据传递中的痛点标准化的优势 JSON 与 Protocol Buffers 的比较JSONProtocol Buffers HarmonyOS 跨语言数据传递示例示例代码:定义 Protocol Buffers 消息格式生成 Java 和 C 代码示例代码:Java 端序列化与传递数据C …

IPsec VPN配置实验(固定地址)

目录 实验需求 基础配置 配置第一阶段 IKE SA 配置第二阶段 IPsec SA 测试结果 清除IKE / IPsec SA命令 注意 就是IPsec的实验配置的话,它们两端的IP地址是固定的 那么就用第一阶段的主模式(Main Mode) 和第二阶段的快速模式&#xf…

Bert中文文本分类

这是一个经典的文本分类问题,使用google的预训练模型BERT中文版bert-base-chinese来做中文文本分类。可以先在Huggingface上下载预训练模型备用。https://huggingface.co/google-bert/bert-base-chinese/tree/main 我使用的训练环境是 pip install torch2.0.0; pi…

SpringBoot的pom.xml文件中,scope标签有几种配置?

1.compile(默认) 含义:表示该依赖在项目的所有阶段(编译、测试、运行)都需要。 当你依赖一个库,并且这个库是你项目的核心部分,比如 Spring Boot 的spring - boot - starter - web&#xff0c…

FPGA三模冗余TMR工具(二)

学术和商业领域有许多自动化的三模冗余TMR工具,本文介绍当前主流的基于寄存器传输级的三模冗余工具(Register-Transfer Level,RTL),基于重要软核资源的三模冗余工具,以及新兴的基于高层次综合的三模冗余工具…

STM32 I2C通信协议

单片机学习! 文章目录 目录 文章目录 前言 一、I2C通信 1.1 I2C总线 1.2 I2C通信线 1.3 同步半双工且数据应答 1.4 一主多从 二、硬件电路 2.1 I2C电路模型 2.2 I2C接线要求 2.3 I2C上拉电阻作用 三、I2C时序基本单元 3.1 起始终止条件 3.1.1 起始条件 3.1.2 终止条…

【开源】一款基于SpringBoot的智慧小区物业管理系统

一、下载项目文件 项目文件源码链接:https://pan.quark.cn/s/3998d958e182如出现网盘空间不够存的情况!!!解决办法是先用夸克手机app注册,然后保存上方链接,就可以得到1TB空间了!!&…