PySide(PyQT)使用场景(QGraphicsScene)进行动态标注的一个demo
用以标注图像的一个基本框架demo
import sys
from PySide6.QtWidgets import QApplication, QGraphicsView, QGraphicsScene, QMainWindow, QLabel, QGraphicsPixmapItem
from PySide6.QtGui import QPixmap, QPainter, QTransform
from PySide6.QtCore import Qt, QPointF, Slot, Signalclass ImageViewer(QGraphicsView):mouse_pos = Signal(int, int) # 原图像素坐标信号def __init__(self, image_path, parent=None):super(ImageViewer, self).__init__(parent)# 场景的初始化def init_scene():# 设置场景self.scene = QGraphicsScene(self)self.setScene(self.scene)# 设置渲染提示self.setRenderHint(QPainter.Antialiasing) # 开启抗锯齿self.setRenderHint(QPainter.SmoothPixmapTransform) # 开启平滑缩放# 设置缩放锚点self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse) # 转换时以鼠标为中心self.setResizeAnchor(QGraphicsView.AnchorUnderMouse) # 缩放时以鼠标为中心# 创建基础的显示内容pixmap = QPixmap(image_path)self.pixmap_item = QGraphicsPixmapItem(pixmap)self.scene.addItem(self.pixmap_item)# 标记点的数量self.mark_count = 0# 遮罩的数量self.mask_count = 0init_scene()self.mouse_pos.connect(self.update_mouse_position)def add_mark(self, pixmap, pos=(0, 0), scale=1.0):"""添加标记到场景:param pixmap: 图像数据:param pos: 坐标:param scale: 缩放比例:return: None"""# 加载图像pixmap_item = QGraphicsPixmapItem(pixmap) # 创建图形项mark_x = pos[0] - pixmap.width() / 2 * scalemark_y = pos[1] - pixmap.height() / 2 * scalepixmap_item.setPos(mark_x, mark_y) # 设置位置if scale != 1.0: # 设置比例pixmap_item.setScale(scale)self.scene.addItem(pixmap_item)self.mark_count += 1def add_mask(self):"""添加遮罩:return:"""passdef remove_mark(self):"""删除一个标记:return: None"""if self.mark_count > 0:self.scene.removeItem(self.scene.items()[0])self.mark_count -= 1def remove_mask(self):"""删除一个遮罩:return: None"""if self.mask_count > 0:self.scene.removeItem(self.scene.items()[0])self.mask_count -= 1def remove_all_marks(self):"""删除所有标记:return:"""while self.mark_count > 0:self.scene.removeItem(self.scene.items()[0])self.mark_count -= 1# # 使用变换矩阵(如果需要)def transform(self, t):# self.transform = t# self.pixmap_item.setTransform(self.transform)pass# 处理滚轮事件以实现缩放def wheelEvent(self, event):factor = 1.001 ** event.angleDelta().y() # 滚轮每滚动一格,缩放比例变化self.scale(factor, factor)# 处理鼠标单击事件以显示原图像素坐标def mousePressEvent(self, event):super(ImageViewer, self).mousePressEvent(event)scene_pos = self.mapToScene(event.position().toPoint()) # 记录当前鼠标在场景中的位置pixmap_rect = self.pixmap_item.boundingRect() # 记录图像的边界矩形# 如果鼠标在图像边界矩形内,则显示像素坐标if pixmap_rect.contains(scene_pos):pos = self.pixmap_item.mapFromScene(scene_pos) # 计算图像坐标x, y = pos.x(), pos.y()print(f"鼠标在图像内,坐标为: ({x}, {y})")if event.button() == Qt.LeftButton: # 左键if event.modifiers() == Qt.ShiftModifier: # Shift 键self.remove_mark() # 删除标记else:self.add_mark(pixmap_mark, (x, y), 0.6) # 添加标记elif event.button() == Qt.RightButton: # 右键if event.modifiers() == Qt.ShiftModifier: # Shift 键self.remove_all_marks() # 删除所有标记else:self.add_mark(pixmap_unmark, (x, y), 0.6) # 添加标记@Slot()def update_mouse_position(self, x, y):pass# 更新状态栏显示# self.status_bar.showMessage(f"原图像素坐标: ({x}, {y})")class MainWindow(QMainWindow):def __init__(self, image_path):super(MainWindow, self).__init__()self.setGeometry(100, 100, 800, 600)# 创建状态栏self.status_bar = self.statusBar()# 创建 ImageViewer 实例self.image_viewer = ImageViewer(image_path, self)self.setCentralWidget(self.image_viewer)if __name__ == "__main__":app = QApplication(sys.argv)# 生成标记图像pixmap_mark = QPixmap("mark.png") # 标记图像(前景)pixmap_unmark = QPixmap("un_mark.png") # 未标记图像(背景)image_path = "IMG_PP.jpg" # 基础图像路径# 创建主窗口window = MainWindow(image_path)window.show()sys.exit(app.exec())
截图:

相关文章:
PySide(PyQT)使用场景(QGraphicsScene)进行动态标注的一个demo
用以标注图像的一个基本框架demo import sys from PySide6.QtWidgets import QApplication, QGraphicsView, QGraphicsScene, QMainWindow, QLabel, QGraphicsPixmapItem from PySide6.QtGui import QPixmap, QPainter, QTransform from PySide6.QtCore import Qt, QPointF, S…...
w206基于Spring Boot的农商对接系统的设计与实现
🙊作者简介:多年一线开发工作经验,原创团队,分享技术代码帮助学生学习,独立完成自己的网站项目。 代码可以查看文章末尾⬇️联系方式获取,记得注明来意哦~🌹赠送计算机毕业设计600个选题excel文…...
C++类和对象进阶:拷贝构造函数深度详解
拷贝构造函数 拷贝构造函数前言引入拷贝构造函数特征拷贝构造函数建议参数加上const 拷贝构造函数参数传值会引发无穷递归的解释内置类型传参拷贝自定义类型传参拷贝详细解释 编译器生成的默认拷贝构造函数默认构造函数做了什么?深拷贝与浅拷贝简单实现一个深拷贝。…...
docker搭建redis-cluster
两台服务器,并且想要搭建 Redis 集群。根据你的命令,Redis 集群将会运行在 Docker 容器中,而你使用的镜像是 redis-cluster:4.0,并且设定了 CLUSTER_ANNOUNCE_IP 环境变量来指定 Redis 实例的 IP 地址。 为了在两台服务器上搭建 …...
深入了解 Oracle 正则表达式
目录 深入了解 Oracle 正则表达式一、正则表达式基础概念二、Oracle 正则表达式语法(一)字符类(二)重复限定符(三)边界匹配符(四)分组和捕获 三、Oracle 正则表达式函数(…...
傅里叶公式推导(三)
文章目录 周期 2L周期T 周期 2L 周期 T 2 L T2L T2L 的傅里叶变换 即 f ( t ) f ( t 2 L ) f(t) f(t2L) f(t)f(t2L) xt2 π \pi π 2 L 2L 2L 原公式 f ( x ) a 0 2 ∑ n 1 ∞ [ a n cos n x b n sin n x ] a 0 1 π ∫ − π π f ( x ) d x a n 1 π ∫…...
像取快递一样取文件?
看到一个很有意思的项目,像我们做软件分享的感觉会有用,就是现在服务器费用太贵了,如果自建的话感觉不是很值得。 FileCodeBox FileCodeBox 是一个轻量级的文件分享系统,它基于匿名口令分享文本和文件,无需注册登录&…...
【CXX】1 CXX主要概念概览
本文描述了CXX(一个用于在Rust和C之间进行桥接的库)中的关键概念,特别是FFI(外部函数接口)边界所涉及的三种主要类型:共享结构体、不透明类型和函数。 一、示例代码 #[cxx::bridge] mod ffi {// 任何共享…...
PyQT项目如何在Linux中自启显示界面
可以通过systemd服务启动PyQt程序 1. 创建服务文件: 在 /etc/systemd/system/ 目录下创建一个新的服务文件。例如,如果您的程序名为 my_program.py,可以创建一个名为 my_program.service 的文件: sudo nano /etc/systemd/system…...
【信息系统项目管理师-案例真题】2019下半年案例分析答案和详解
更多内容请见: 备考信息系统项目管理师-专栏介绍和目录 文章目录 试题一【问题 1】(6 分)【问题 2 】(8 分)【问题 3 】(11 分)试题二【问题 1】(5分)【问题 2】 (14 分)【问题 3 】(6 分)试题三【问题 1】(8 分)【问题 2 】(6 分)【问题 3】 (8 分)【问题 4 …...
DeepSeek 助力 Vue 开发:打造丝滑的返回顶部按钮(Back to Top)
前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏关注哦 💕 目录 Deep…...
【前端开发学习笔记15】Vue_8
手动添加Pinia到Vue项目: 在实际开发中,Pinia配置可在项目创建时自动添加。初次学习从零开始: 1. 用Vite创建空的Vue3项目,命令为npm create vuelatest。 2. 按官方文档将pinia安装到项目中。 import { createApp } from vue im…...
deepin linux UOS AI 使用 deepseek-r1 30B
我们用 ollama 下载 deepseek-r1 3B 执行命令: $ ollama pull models/unsloth/DeepSeek-R1-Distill-Qwen-32B-GGUF 下载完成后 我们就要重新更改目录和文件了 deepseek-r1/gguf (这是目录结构) 然后我把 gguf文件 更名成 DeepSeek-R1.gguf (就是目录下最大的那个文件) …...
通过docker启用rabbitmq插件
创建文件,docker-compose.yml services:rabbitmq:image: rabbitmq:4.0-managementports:- "5672:5672"- "15672:15672"volumes:- ./data/rabbitmq/data:/var/lib/rabbitmq # 持久化数据- ./data/rabbitmq/plugins/rabbitmq_delayed_message_ex…...
对比 LVS 负载均衡群集的 NAT 模式和 DR 模式,比较其各自的优势 与基于 openEuler 构建 LVS-DR 群集
一、 对比 LVS 负载均衡群集的 NAT 模式和 DR 模式,比较其各自的优势 NAT 模式 部署简单:NAT 模式下,所有的服务器节点只需要连接到同一个局域网内,通过负载均衡器进行网络地址转换,就可以实现负载均衡功能。不需要对…...
C++17 中 std::lcm:从入门到精通
文章目录 一、引言二、std::lcm 的基本概念三、入门示例四、计算多个整数的最小公倍数五、std::lcm 的实现原理六、在实际项目中的应用七、注意事项八、总结 一、引言 在 C 编程中,处理数学运算时,计算最小公倍数(Least Common Multiple&…...
html 点击弹出视频弹窗
一、效果: 点击视频按钮后,弹出弹窗 播放视频 二、代码 <div class="index_change_video" data-video-src="</...
docker安装mongo,导入、导出数据
1、docker安装mongo docker pull mongo docker run -d -p 27017:27017 --name mongodb mongodocker update mongodb --restartalways ## 开机自启动-d:表示以后台模式运行容器。 -p 27017:27017:将容器内部的 MongoDB 默认端口 27017 映射到宿主机的 27…...
代码随想录算法【Day44】
Day44 1143.最长公共子序列 class Solution { public:int longestCommonSubsequence(string text1, string text2) {vector<vector<int>> dp(text1.size() 1, vector<int>(text2.size() 1, 0));for (int i 1; i < text1.size(); i) {for (int j 1; …...
项目总结:java agent的使用
测试团队会做java agent的事,实现测试模拟,各种数据采集等等工作,而这些不需要开发改代码来做到,只需要挂载下agent。 目录 javaagent认识和例子代码例子:java.lang.instrument自定义实现一个javaagentagent jar测试 回…...
使用 LangChain 对接硅基流动(SiliconFlow)API:构建一个智能对话系统
文章目录 什么是硅基流动(SiliconFlow)?LangChain 简介在 LangChain 中对接硅基流动步骤 1:安装必要的库步骤 2:设置 API 密钥步骤 3:编写代码代码解析步骤 4:运行代码如何扩展和改进总结 在现代…...
如何借助NoETL指标平台实现数据分析、决策的提效?
通常,企业通过明确分析目标、定位所需分析的数据,再通过多渠道汇集销售数据、客户反馈、市场调研等信息,经过数据清洗、缺失值处理及格式标准化等手段,运用描述性统计、回归分析、聚类分析及关联规则挖掘等多样分析方法࿰…...
Java--IO流详解 (上)--字符流
目录 IO流的概念 字符流 输入流 Reader核心方法 1.close() 2.mark(int readAheadLimit) 3.markSupported() 4.read() 5.read(char[] cbuf) 6.read(char[] cbuf, int off, int len) 7.read(CharBuffer target) 8.ready() 9.reset() 10.skip(long n) Reader 的常用…...
大模型语言简介
大模型语言能做什么 信息提取 将长段文字中的信息抽取出来并且以结构化的方式输出。相比起传统NLP的方式,大模型在泛化能力上有非常大的提升,并且开发成本要低2个数量级。应用场景包括:论文论点论据提取、用户画像提取、舆情分析、病例结构…...
手动配置IP
手动配置IP,需要考虑四个配置项: 四个配置项 IP地址、子网掩码、默认网关、DNS服务器 IP地址:格式表现为点分十进制,如192.168.254.1 子网掩码:用于区分网络位和主机位 【子网掩码的二进制表达式一定是连续的&#…...
Golang 进阶训练营
一、Golang 的 slice、map、channel 1.1 slice vs array a : make([]int, 100) //切片 b : [100]int{} //数组array需指明长度,长度为常量且不可改变 array长度为其类型中的组成部分(给参数为长度100的数组的方法传长度为101的会报错) array在…...
2-使用wifidog实现portal
wifidog是openwrt上面实现portal认证的一个开源工具,从网关端到服务器都帮你搭建好,通过学习wifidog的原理,后面就可以改造成自己需要的逻辑。 1. openwrt安装wifidog 添加源 vim 14.07/feeds.conf.defaultsrc-git wifidog https://github.c…...
Spring Boot + ShardingSphere 踩坑记
最近在准备秋招,偷了个轮子项目之后想改个分表,于是有了这篇文章。 省流:请使用shardingsphere-jdbc 5.5.2,并根据官方5.5.2版本文档进行配置,不要使用starter。此外,如果希望使用INTERVAL分片算法&#x…...
AI时代前端开发的创造力:解放还是束缚?
在人工智能(AI)快速发展的时代,AI技术的影响已经渗透到各个领域,从医疗保健到金融服务,再到创意产业。AI工具的出现,为前端开发带来了前所未有的效率提升,但也引发了人们对创造力的担忧…...
有哪些免费的SEO软件优化工具
随着2025年互联网的不断发展,越来越多的企业意识到在数字营销中,网站的曝光度和排名至关重要。无论是想要提高品牌知名度,还是想要通过在线销售增加收益,SEO(搜索引擎优化)都是一项不可忽视的关键策略。而要…...
