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

3D人物关系图开发实战:Three.js实现自动旋转可视化图谱(附完整代码)

3D人物关系图开发实战:Three.js实现自动旋转可视化图谱

  • 效果
  • 核心解析
    • 场景初始化
    • 自动旋转控制器
    • 节点创建(带图片和标签)
    • 关系连线
    • 动画循环
    • 数据格式说明
  • 代码

效果

在这里插入图片描述

本文将带您使用Three.js实现一个带自动旋转功能的3D人物关系图谱,核心功能包括:

  • ​三维空间布局​:人物节点环形排列
  • ​动态关系线​:带箭头的红色连线和悬浮关系标签
  • ​交互控制​:支持鼠标拖拽、缩放视角
  • ​自动旋转​:场景持续缓慢旋转,增强视觉效果
  • ​自适应窗口​:响应式布局适配不同屏幕

核心解析

场景初始化

// 创建基础Three.js场景
const scene = new THREE.Scene();
scene.background = new THREE.Color(0xf8f8f8);// 透视相机配置
const camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);
camera.position.set(0, 15, 30); // 初始视角// 渲染器配置
const renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

自动旋转控制器

const controls = new OrbitControls(camera, renderer.domElement);
controls.autoRotate = true;         // 启用自动旋转
controls.autoRotateSpeed = 1.0;     // 旋转速度
controls.enableDamping = true;      // 阻尼惯性效果
controls.dampingFactor = 0.05;     // 阻尼系数

节点创建(带图片和标签)

// 加载角色立绘
const textureLoader = new THREE.TextureLoader();
textureLoader.load(node.img, (texture) => {const sprite = new THREE.Sprite(material);sprite.scale.set(baseWidth, baseHeight, 1); // 保持图片比例
});// 创建信息标签
const canvas = document.createElement('canvas');
ctx.font = 'bold 24px "Microsoft YaHei"'; // 中文字体支持
ctx.fillText(node.name, 10, 30); // 绘制姓名

关系连线

const arrowHelper = new THREE.ArrowHelper(direction, sourcePos,length,0xDC143C, // 红色箭头headLength,headWidth
);

动画循环

function animate() {requestAnimationFrame(animate);controls.update(); // 持续更新控制器renderer.render(scene, camera);
}

数据格式说明

创建无名小村.json文件:

{"nodes": [{"id": 1,"name": "花四娘","img": "img/role1.png","description": "无名客栈的老板娘,有一手好厨艺,性格泼辣、刚柔并济。一个人苦苦经营无名客栈,据包打听说追她的人能排到无名小村村口,却不见有得她芳心的。"},{"id": 2,"name": "洪小七","img": "img/role1.png","description": "游荡在无名小村里的小乞丐,整日游手好闲,凭借着小偷小摸的本事,这才勉强过上饥一顿饱一顿的日子。"},{"id": 3,"name": "包打听","img": "img/role1.png","description": "无名小村里游手好闲的年轻人,平日里到处打听八卦,靠着打听到的小道消息和人换点小钱为生"},{"id": 4,"name": "白头翁","img": "img/role1.png","description": "年少时一心钻研学医,本想医术大成后救济天下人,奈何天赋不够,蹉跎半生仍旧只知皮毛,只能沦为乡里郎中,治一些风寒小病糊口。"},{"id": 5,"name": "王大锤","img": "img/role1.png","description": "无名小村的铁匠,力大如牛,有一手顶尖的打铁技巧。原先是琅琊剑阁大弟子,年轻时人称“玉面干将”,但是现在完全看不出来。因为某些事情离开剑阁,来到无名小村隐姓埋名。"},{"id": 6,"name": "刘十八","img": "img/role1.png","description": "无名小村的猎户,打猎技术高超。昔日是守卫楚襄城的杨将军部下,杨家军解散后逃到无名小村躲避,从此隐姓埋名,以打猎为生。"},{"id": 7,"name": "采石匠","img": "img/role1.png","description": "村里的采石匠,挖矿为生。"},{"id": 8,"name": "屠户","img": "img/role1.png","description": "卖肉的屠户,白白胖胖,营养过剩。"},{"id": 9,"name": "小花","img": "img/role1.png","description": "樵夫女儿,喜欢猜字谜。"},{"id": 10,"name": "小白","img": "img/role1.png","description": "樵夫的儿子,喜欢打猎。"},{"id": 11,"name": "小丫","img": "img/role1.png","description": "刘十八女儿,喜欢玩捉迷藏。"},{"id": 12,"name": "樵夫","img": "img/role1.png","description": "村里的樵夫,以砍伐木材为生。"},{"id": 13,"name": "村长","img": "img/role1.png","description": "一村之长,老秀才,守护着无名小村的秘密。"},{"id": 14,"name": "小宝","img": "img/role1.png","description": "村长三代,梦想是成为大侠。"},{"id": 15,"name": "货郎","img": "img/role1.png","description": "走南闯北,贩卖各种物品的货郎。"},{"id": 16,"name": "燕歌行","img": "img/role1.png","description": "在无名小村非要拉着收徒的怪老头,原本以为只是个不正经的老头,真实身份是老魔头楚狂生的师弟、九流门的真正创建者之一。因被仇家暗算导致武功尽失,经脉尽毁。如今已经治愈旧伤、功力恢复,准备去完成自己的毕生心愿。"}],"links": [{"source": 5,"target": 6,"relation": "不和"},{"source": 6,"target": 11,"relation": "父亲"},{"source": 6,"target": 8,"relation": "供货"},{"source": 1,"target": 5,"relation": "债主"},{"source": 3,"target": 1,"relation": "暗恋"},{"source": 13,"target": 14,"relation": "爷爷"},{"source": 12,"target": 9,"relation": "父亲"},{"source": 4,"target": 6,"relation": "救治"}]
}

代码

<!DOCTYPE html>
<html lang="zh-cn">
<head><meta charset="UTF-8"><title>3D人物关系图(自动旋转版)</title><style>body { margin: 0; }canvas { display: block; }</style><!-- importmap 配置 --><script type="importmap">{"imports": {"three": "./js/three.js/build/three.module.js","three/addons/": "./js/three.js/examples/jsm/"}}</script>
</head>
<body>
<script type="module">
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';fetch('无名小村.json').then(response => response.json()).then(data => {const scene = new THREE.Scene();scene.background = new THREE.Color(0xf8f8f8);const camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);const renderer = new THREE.WebGLRenderer({antialias: true});renderer.setSize(window.innerWidth, window.innerHeight);renderer.toneMapping = THREE.NoToneMapping;renderer.outputColorSpace = THREE.SRGBColorSpace;document.body.appendChild(renderer.domElement);// 控制器配置(新增自动旋转参数)const controls = new OrbitControls(camera, renderer.domElement);controls.autoRotate = true;         // 启用自动旋转controls.autoRotateSpeed = 1.0;      // 旋转速度(默认1.0)controls.enableDamping = true;       // 启用阻尼惯性controls.dampingFactor = 0.05;       // 阻尼系数controls.minDistance = 15;          // 最小缩放距离controls.maxDistance = 50;          // 最大缩放距离// 调整初始摄像机位置(新增斜视角)camera.position.set(0, 15, 30);      // x, y, z坐标controls.update();// 节点布局(简单环形)const radius = 10;const nodeMeshes = {};data.nodes.forEach((node, i) => {const angle = (i / data.nodes.length) * Math.PI * 2;const x = radius * Math.cos(angle);const y = radius * Math.sin(angle);const z = (Math.random() - 0.5) * 5;node.position = {x, y, z};// 立绘图片节点const textureLoader = new THREE.TextureLoader();textureLoader.load(node.img, (texture) => {texture.colorSpace = THREE.SRGBColorSpace;const material = new THREE.SpriteMaterial({map: texture,transparent: true,premultipliedAlpha: false,blending: THREE.NormalBlending,depthWrite: false,depthTest: true,sizeAttenuation: true,color: 0xffffff});material.toneMapped = false;const sprite = new THREE.Sprite(material);sprite.position.set(x, y, z);// --- 根据图片实际尺寸计算缩放比例 ---const image = texture.image;if (image) {const aspectRatio = image.naturalWidth / image.naturalHeight;// 定义一个基础高度(例如,所有立绘在场景中的基础高度为 4 个单位)const baseHeight = 4;// 根据宽高比计算宽度const baseWidth = baseHeight * aspectRatio;sprite.scale.set(baseWidth, baseHeight, 1);} else {// 如果图片尺寸信息获取失败,使用默认值sprite.scale.set(3, 4, 1);}// --- 缩放计算结束 ---scene.add(sprite);nodeMeshes[node.id] = sprite;});// 节点标签const canvas = document.createElement('canvas');canvas.width = 256;canvas.height = 128;const ctx = canvas.getContext('2d');ctx.clearRect(0, 0, canvas.width, canvas.height);ctx.fillStyle = 'rgba(200,220,255,0.8)';ctx.fillRect(0, 0, canvas.width, canvas.height);// 名称ctx.font = 'bold 24px "Microsoft YaHei", "微软雅黑", sans-serif';ctx.fillStyle = 'black';ctx.fillText(node.name, 10, 30);// 描述ctx.font = 'bold 16px "Microsoft YaHei", "微软雅黑", sans-serif';const description = node.description || "暂无人物介绍";const maxWidth = 240;const lineHeight = 20;let textY = 60;for (let i = 0; i < description.length; i += 20) {const chunk = description.substr(i, 20);ctx.fillText(chunk, 10, textY);textY += lineHeight;if (textY > canvas.height - 10) break;}const labelTexture = new THREE.CanvasTexture(canvas);const labelMaterial = new THREE.SpriteMaterial({map: labelTexture,transparent: true,depthTest: false,depthWrite: false});const labelSprite = new THREE.Sprite(labelMaterial);labelSprite.scale.set(5, 3, 1);// 将 y + 3.5 修改为 y - 3.5 (或其他负值)labelSprite.position.set(x, y - 3.5, z);scene.add(labelSprite);});// 绘制连线和关系标签data.links.forEach(link => {const sourceNode = data.nodes.find(n => n.id === link.source);const targetNode = data.nodes.find(n => n.id === link.target);// 确保节点和位置存在if (!sourceNode || !sourceNode.position || !targetNode || !targetNode.position) {console.warn('Skipping link due to missing node or position:', link);return;}const sourcePos = new THREE.Vector3(sourceNode.position.x, sourceNode.position.y, sourceNode.position.z);const targetPos = new THREE.Vector3(targetNode.position.x, targetNode.position.y, targetNode.position.z);// --- 绘制带箭头的连线 ---const direction = new THREE.Vector3().subVectors(targetPos, sourcePos);const length = direction.length(); // 获取向量长度,即连线长度direction.normalize(); // 标准化方向向量// 定义箭头参数const arrowColor = 0xDC143C;const headLength = 1; // 箭头头部长度,可调整const headWidth = 0.5; // 箭头头部宽度,可调整// 创建 ArrowHelperconst arrowHelper = new THREE.ArrowHelper(direction,  // 箭头方向(标准化向量)sourcePos,  // 箭头起点length,     // 箭头总长度(从起点到终点)arrowColor, // 箭头颜色headLength, // 箭头头部长度headWidth   // 箭头头部宽度);scene.add(arrowHelper);// --- 箭头连线结束 ---// --- 添加关系标签 ---const relationText = link.relation || ''; // 获取关系文本,如果不存在则为空if (relationText) {const canvas = document.createElement('canvas');const context = canvas.getContext('2d');// 增大字体大小const fontSize = 24; // <--- 增大字体context.font = `bold ${fontSize}px Arial`;const textWidth = context.measureText(relationText).width;// 根据文本内容调整Canvas大小,并增加更多边距const padding = 20; // <--- 增加边距canvas.width = textWidth + padding * 2;canvas.height = fontSize + padding; // 上下边距可以少一点// 重新设置字体和样式context.font = `bold ${fontSize}px Arial`; // <--- 保持一致context.fillStyle = 'rgba(0, 0, 0, 0.7)';context.fillRect(0, 0, canvas.width, canvas.height);context.fillStyle = 'white';context.textAlign = 'center';context.textBaseline = 'middle';// 绘制文本位置也要相应调整context.fillText(relationText, canvas.width / 2, canvas.height / 2);const texture = new THREE.CanvasTexture(canvas);// 可以尝试不同的过滤方式,但通常提高分辨率效果更好// texture.minFilter = THREE.LinearFilter;// texture.magFilter = THREE.LinearFilter; // 或者 THREE.NearestFilter 看效果const spriteMaterial = new THREE.SpriteMaterial({map: texture,transparent: true,depthTest: false,depthWrite: false,sizeAttenuation: true // 确保 Sprite 大小随距离变化});const sprite = new THREE.Sprite(spriteMaterial);// 计算标签位置(线段中点稍微偏移一点)const midPoint = new THREE.Vector3().addVectors(sourcePos, targetPos).multiplyScalar(0.5);midPoint.y += 0.5; // 稍微向上偏移sprite.position.copy(midPoint);// 可能需要重新调整 scaleFactor 以匹配新的 Canvas 尺寸和字体大小const scaleFactor = 0.05; // <--- 可能需要减小 scaleFactorsprite.scale.set(canvas.width * scaleFactor, canvas.height * scaleFactor, 1.0);scene.add(sprite);}// --- 关系标签结束 ---});// 渲染循环(新增自动旋转逻辑)function animate() {requestAnimationFrame(animate);controls.update(); // 必须调用才能启用自动旋转renderer.render(scene, camera);}animate();// 窗口大小自适应window.addEventListener('resize', () => {camera.aspect = window.innerWidth / window.innerHeight;camera.updateProjectionMatrix();renderer.setSize(window.innerWidth, window.innerHeight);});});
</script>
</body>
</html>

相关文章:

3D人物关系图开发实战:Three.js实现自动旋转可视化图谱(附完整代码)

3D人物关系图开发实战&#xff1a;Three.js实现自动旋转可视化图谱 效果核心解析场景初始化自动旋转控制器节点创建&#xff08;带图片和标签&#xff09;关系连线动画循环数据格式说明 代码 效果 本文将带您使用Three.js实现一个带自动旋转功能的3D人物关系图谱&#xff0c;核…...

文件操作-

1. 为什么使⽤⽂件&#xff1f; 如果没有⽂件&#xff0c;我们写的程序的数据是存储在电脑的内存中&#xff0c;如果程序退出&#xff0c;内存回收&#xff0c;数据就丢失了&#xff0c;等再次运⾏程序&#xff0c;是看不到上次程序的数据的&#xff0c;如果要将数据进⾏持久化…...

硬件零基础入门(尚硅谷)

1 一个碳原子有一个自由电子。所以能够导电。 金刚石四个都是都弄成共价键了&#xff0c;所以没有自由电子不能自由电子。 2 新的电子进来&#xff0c;因为互斥电荷进行了定向运动&#xff0c;产生了能量。两边电子平衡就停止了。所以电池的负极有电子。 电荷就是质子和电…...

【Ai零件】高德开放平台MCP的API-key注册

前言 基本操作文档&#xff0c;为n8n等平台&#xff0c;调用高德MCP服务做准备&#xff0c;本文记录其API-Key的生成步骤。 操作步骤 高德开发平台官网&#xff1a;https://lbs.amap.com/ 完成后&#xff0c;进入控制台界面: 创建新应用 进入【应用管理】&#xff0c;点击页…...

安卓基础(startActivityForResult和onActivityResult)

onActivityResult 方法有三个参数&#xff1a; requestCode&#xff1a;启动 Activity 时传入的请求码&#xff0c;用于区分不同的启动请求。resultCode&#xff1a;返回结果的状态码&#xff0c;通常为 RESULT_OK 或 RESULT_CANCELED。data&#xff1a;一个 Intent 对象&…...

安卓基础(悬浮窗)

悬浮窗 import android.app.Service; import android.content.Context; import android.graphics.PixelFormat; import android.os.IBinder; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.WindowManager…...

《windows GCC 版本升级到9以上》

《windows GCC 版本升级到9以上》 在 Windows 系统上升级 GCC 到 9 以上版本通常有两种主流方案:MinGW-w64 和 WSL(Windows Subsystem for Linux)。以下是具体操作步骤: 方案一:使用 MinGW-w64(原生 Windows 环境) 步骤 1:安装 MSYS2 MSYS2 是 Windows 上的软件分发…...

LeetCode —— 102. 二叉树的层序遍历

&#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️Take your time ! &#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️…...

Python面向对象编程实战:从类定义到高级特性的进阶之旅(2/10)

摘要&#xff1a;本文介绍面向对象编程基础概念&#xff0c;包括类与对象、封装、继承和多态等。以Python语言为例&#xff0c;详细讲述了类的定义与使用、构造函数与析构函数、类的访问控制等。面向对象编程通过将数据和操作封装在一起&#xff0c;提高代码的模块化和可维护性…...

【AI论文】DeepCritic:使用大型语言模型进行有意识的批判

摘要&#xff1a;随着大型语言模型&#xff08;LLMs&#xff09;的快速发展&#xff0c;对其输出提供准确的反馈和可扩展的监督成为一个紧迫而关键的问题。 利用LLM作为评判模型来实现自动化监督是一种有前景的解决方案。 在这项工作中&#xff0c;我们专注于研究和提高LLM的数…...

硬件工程师面试常见问题(12)

第五十六问&#xff1a;PCI总线基本知识 关于PCI总线的描述,错误的是:&#xff08;A&#xff09;(4分) A.PCI总线是一个16位宽的总线。 B.PCI的地址线与数据线是复用的。 C.PCI是一种独立于处理器的总线标准,可以支持多种处理器。 D.PCI支持即插即用功能。 解释&#xff1a; …...

大数据Spark(五十八):Spark Pi介绍

文章目录 Spark Pi介绍 Spark Pi介绍 Spark Pi是Apache Spark官方提供的一个示例程序&#xff0c;该案例使用 Spark 进行分布式计算&#xff0c;通过蒙特卡罗方法估算圆周率&#xff08;π&#xff09;的值&#xff0c;其估算π原理如下&#xff1a; 上图中&#xff0c;正方形…...

深入理解 HttpExchange_Java 中构建 HTTP 服务的基础组件

1. 引言 1.1 Java 中的轻量级 HTTP 服务需求 随着微服务、工具类应用和嵌入式系统的兴起,开发者对轻量级 HTTP 服务的需求日益增长。相比引入庞大的框架(如 Spring Boot),使用 JDK 原生 API 构建 HTTP 服务成为一种快速、低依赖的替代方案。 JDK 提供了 com.sun.net.htt…...

MaC QT 槽函数和Lambda表达式

在C Qt框架中&#xff0c;槽函数&#xff08;Slot&#xff09;是一种特殊的成员函数&#xff0c;用于响应信号&#xff08;Signal&#xff09;的触发&#xff0c;从而实现对象间的通信和事件处理。 #include<QMessageBox>//包含槽函数的头文件 //定义槽函数 响应特定的信…...

JMM 与 JVM 运行时数据区有什么区别和联系?

JMM&#xff08;Java Memory Model&#xff09;和 JVM 运行时数据区&#xff08;JVM Runtime Data Areas&#xff09;是 Java 内存管理中的两个不同但密切相关的概念。 1. JVM 运行时数据区 (JVM Runtime Data Areas) 是什么&#xff1f; JVM 运行时数据区是 JVM 在程序执行过程…...

LeetCode Hot100题解

目录 一、数组 & 字符串 1. 两数之和&#xff08;简单&#xff09; 2. 删除有序数组中的重复项&#xff08;简单&#xff09; 3. 移除元素&#xff08;简单&#xff09; 4. 合并两个有序数组&#xff08;简单&#xff09; 5. 买卖股票的最佳时机&#xff08;简单&…...

基于Jenkins的DevOps工程实践之Jenkins共享库

文章目录 前言Jenkins共享库结构1、共享库演示2、知识点补充3、实践使用共享库格式化输出日志4、groovy基础语法4.1、 什么是 Groovy&#xff1f;4.2、groovy特点4.3、运行方法4.4、标识符4.5、基本数据类型4.5.1、string类型4.5.2、list类型 4.6、函数使用4.7、正则表达式 5、…...

【安装指南】Docker 安装最新版 Nginx 并进行项目的编排

目录 一、Nginx 的介绍 1.1 开源版 Nginx​ ① 访问路由​ ② 反向代理​ ③ 负载均衡​ ④ 内容缓存​ ⑤ 可编程​ 1.2 商业版 Nginx Plus​ ① 负载均衡​ ② 动态管理​ ③ 安全控制​ ④ 状态监控​ ⑤ Kubernetes Ingress Controller​ ⑥ 流媒体​ 1.3 扩…...

MFC自定义控件开发与使用指南

MFC自定义控件开发与使用指南 1. 概述 MFC(Microsoft Foundation Classes)框架提供了丰富的内置控件,但在实际开发中,我们常常需要创建自定义控件来满足特定的界面需求。本文将详细介绍如何在MFC中开发自定义控件,并以CCustomTextControl为例,展示自定义控件的实现和使…...

Learning vtkjs之PolyDataNormals

法线可视化 介绍 polydata法线可视化 效果 核心代码 主要流程 const fullScreenRenderer vtkFullScreenRenderWindow.newInstance({background: [0, 0, 0],rootContainer: vtkContainerRef.current,});const renderer fullScreenRenderer.getRenderer();const renderWind…...

DeepSeek辅助学术写作之提交和出版以及评审过程分析提示词分享祝你顺利毕业~

目录 1.提交和出版 2.评审过程 大家好这里是AIWritePaper官方账号&#xff0c;官网&#x1f449;AIWritePaper~ 宝子们可以使用小编精选的“ChatGPT研究论文提示词”集合来创建研究论文。利用DeepSeek的智能回应生成详尽有效的内容&#xff0c;这样可以加快研究论文的策划、创…...

基于机器学习的心脏病数据分析与可视化(百度智能云千帆AI+DeepSeek人工智能+机器学习)健康预测、风险评估与数据可视化 健康管理平台 数据分析与处理

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…...

Kubernetes(k8s)学习笔记(四)--入门基本操作

本文通过kubernetes部署tomcat集群&#xff0c;来学习和掌握kubernetes的一些入门基本操作 前提条件 1.各个节点处于Ready状态&#xff1b; 2.配置好docker镜像库(否则会出现ImagePullBackOff等一些问题)&#xff1b; 3.网络配置正常(否则即使应用发布没问题&#xff0c;浏…...

在Java项目中实现本地语音识别与热点检测,并集成阿里云智能语音服务

引言 随着语音交互技术的发展&#xff0c;如何高效地处理用户的语音输入成为许多应用的重要课题。本文将详细介绍如何在一个Java项目中同时实现&#xff1a; 基于Vosk的本地语音识别&#xff1a;无需调用云端API即可完成语音到文本的转换。本地热点语音内容识别&#xff1a;对…...

C++八股--5--设计模式--适配器模式,代理模式,观察者模式

3. 观察者模式&#xff08;也叫做观察者-监听者模式&#xff0c;发布-订阅模式&#xff09; 主要关注对象的一对多关系&#xff0c;也就是多个对象都依赖于一个对象&#xff0c;当该对象状态改变时&#xff0c;其余对象都能得到对应的通知 如&#xff1a;一组数据&#xff08;数…...

Ubuntu下安装Node.js

一、引言 Ubuntu下安装Node.js主要有两种方式&#xff1a;通过apt安装和通过源码安装。本文主要讲解通过apt安装Node.js的方法。 二、通过apt安装Node.js 安装Node.js&#xff1a; apt install nodejs 我之前已经安装过了&#xff0c;所以提示&#xff1a;“nodejs 已经是最…...

用单目相机和apriltag二维码aruco实现单目定位

目录 一、核心流程与代码框架 1. ‌环境准备‌ 2. ‌ArUco定位实现 3. ‌AprilTag定位实现&#xff08;需额外安装Apriltag库&#xff09; 二、关键优化点 1‌.亚像素角点优化 2‌ 多标签联合定位 三、性能指标&#xff08;实测&#xff09; 四、常见问题 ‌检测失败…...

AIGC算力消耗白皮书:Stable Diffusion vs Midjourney的架构成本差异

引言&#xff1a;文生图模型的算力经济学悖论 当Midjourney单日处理超过4000万张图像请求时&#xff0c;其云服务算力成本却低于Stable Diffusion开源方案的37%。这揭示了一个核心矛盾&#xff1a;开源模型的架构自由度与闭源系统的商业优化之间存在根本性博弈。本文基于H800 …...

介绍 PHP-FPM 和 Python WSGI

我来详细介绍 PHP-FPM 和 Python WSGI&#xff0c;它们是现代Web开发中替代传统CGI的高性能解决方案&#xff0c;分别针对PHP和Python优化。 1. PHP-FPM&#xff08;FastCGI Process Manager&#xff09; 是什么&#xff1f; PHP-FPM 是PHP的 FastCGI 进程管理器&#xff0c;…...

赛季7靶场 -- Checker --User flag

本系列仅说明靶场的攻击思路&#xff0c;不会给出任何的详细代码执行步骤&#xff0c;因为个人觉得找到合适的工具以实现攻击思路的能力也非常重要。root要逆向&#xff0c;没做了&#xff0c;但是user flag也有借鉴意义&#xff0c;关于2FA的绕过我们有必要了解 1.首先Nmap扫描…...

【c语言】数据在内存中的存储

一、 大小端字节序 大端字节序&#xff1a;数据的低字节内容存放在内存的高地址处&#xff0c;数据的高字节内容存放在内存的低地址处&#xff0c;对于0x11223344 小端字节序&#xff1a;数据的低字节内容存放在内存的低地址处&#xff0c;数据的高字节内容存放在内存的高地…...

【Unity】XLua访问C#文件

创建NPC.cs&#xff1a; public class NPC { public string name; public int age; public void Say() { Debug.Log("Say:我是未被修改的"); } public static void Say() { Debug.Log("Static Say:我是未被修改的"); } public void Say2(int a) { Debug.Lo…...

Python实例题:Python获取房天下数据

目录 Python实例题 题目 实现思路 代码实现 代码解释 get_fangtianxia_data 函数&#xff1a; 主程序&#xff1a; 运行思路 注意事项 Python实例题 题目 Python获取房天下数据 实现思路 请求网页&#xff1a;使用 requests 库向房天下二手房页面发送请求&#xf…...

Milvus(12):分析器

1 分析器概述 在文本处理中&#xff0c;分析器是将原始文本转换为结构化可搜索格式的关键组件。每个分析器通常由两个核心部件组成&#xff1a;标记器和过滤器。它们共同将输入文本转换为标记&#xff0c;完善这些标记&#xff0c;并为高效索引和检索做好准备。 在 Milvus 中&a…...

小程序滚动条隐藏(uniapp版本)

单独指定页面隐藏&#xff08;找到对应的scroll-view&#xff09; <style> /* 全局隐藏滚动条样式 */ ::-webkit-scrollbar { display: none; width: 0; height: 0; color: transparent; background: transparent; } /* 确保scroll-view组件也隐藏滚动条 */ …...

在 Trae CN IDE 中配置 Python 3.11的指南

在 Trae CN IDE 中配置 Python 3.11的指南 下载 python 3.11 安装 Python 3.11 首先&#xff0c;我们需要确保安装了 Python 3.11。可以从Python 官方网站下载适合你操作系统的版本。 链接 如果你已经安装了 Python 3.11&#xff0c;可以通过以下命令确认&#xff1a; 文…...

AI 大模型常见面试题(及内容解析)

大模型领域包含许多专业术语&#xff0c;以下是一些关键术语的解释&#xff1a; 人工智能&#xff08;AI&#xff09;&#xff1a;是指使计算机系统能够模拟人类智能行为&#xff0c;以执行任务、解决问题和学习的科学和技术。 大型语言模型&#xff08;LLM&#xff09;&#…...

QT —— QWidget(1)

QT —— QWidget&#xff08;1&#xff09; QWidget是啥通俗解释&#xff1a;QWidget 是什么&#xff1f;1. QWidget 能干什么&#xff1f;2. 举个栗子 &#x1f330;3. QWidget 的特点4. 和“控件”是什么关系&#xff1f;5. 什么时候用 QWidget&#xff1f;6. 总结 QWidget 核…...

with的用法

Python SQLite 操作详解 本文档详细解释了使用 Python 操作 SQLite 数据库时涉及的关键概念和代码实践&#xff0c;包括 with 语句、事务处理、批量插入以及相关的优化建议。 一、with 语句的作用&#xff08;自动关门的保险库&#xff09; with sqlite3.connect(city_1301.d…...

Go反射-通过反射调用结构体的方法(带入参)

使用反射前&#xff0c;我们需要提前做好映射配置 papckage_struct_relationship.go package reflectcommonimport (api "template/api" )// 包名到包对象的映射 var structMap map[string]func() interface{}{"template/api": func() interface{} { re…...

C++/SDL 进阶游戏开发 —— 双人塔防(代号:村庄保卫战 19)

&#x1f381;个人主页&#xff1a;工藤新一 &#x1f50d;系列专栏&#xff1a;C面向对象&#xff08;类和对象篇&#xff09; &#x1f31f;心中的天空之城&#xff0c;终会照亮我前方的路 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 文章目录 二…...

使用 Selenium 爬取动态网页数据 —— 实战与坑点详解

本文记录了笔者在爬取网页数据过程中遇到的各种技术挑战&#xff0c;包括页面动态渲染、JavaScript 注入等问题&#xff0c;并最终给出一个可运行的完整方案。 文章目录 网页获取不到数据&#x1f680; 尝试用 Selenium 渲染页面 网页获取不到数据 某网页数据依赖大量 JavaSc…...

强化学习--2.数学

强化学习--数学 1、概率统计知识1.1 随机变量与观测值1.2 概率密度函数&#xff08;PDF&#xff09;1.3 期望1.4 随机抽样 2、数据期望E3、正态分布4、条件概率1. **与多个条件相关**&#xff08;依赖所有前置条件&#xff09;2. **仅与上一个条件相关**&#xff08;马尔可夫性…...

rails 8 CSS不起效问题解决

很久没用rails了&#xff0c;最近打算重新复习一下。在配置好环境后&#xff0c;创建了项目&#xff0c;通过脚手架创建了数据库表&#xff0c;和相关的文件。但我发现却没有生成相应的CSS文件&#xff0c;可能是rails8 取消了吧。于是自己手动创建了相应的css文件。但是刷新页…...

双指针算法详解(含力扣和蓝桥杯例题)

目录 一、双指针算法核心概念 二、常用的双指针类型&#xff1a; 2.1 对撞指针 例题1&#xff1a;盛最多水的容器 例题2&#xff1a;神奇的数组 2.2 快慢指针&#xff1a; 例题1&#xff1a;移动零 例题2&#xff1a;美丽的区间&#xff08;蓝桥OJ1372&#xff09; 3.总…...

C 语言字符输入:掌握 getchar 和 scanf 的用法与陷阱

各类资料学习下载合集 ​​https://pan.quark.cn/s/8c91ccb5a474​​ C 语言字符输入:掌握 getchar 和 scanf 的用法与陷阱 你好!在 C 语言编程中,与用户进行交互最基本的方式就是通过标准输入和标准输出。我们之前探讨了如何使用 ​​printf​​ 和 ​​putchar​​ 进行…...

算法笔记。质数筛算法

题目&#xff1a; 给定一个正整数 n&#xff0c;请你求出 1∼n 中质数的个数。 输入格式 共一行&#xff0c;包含整数 n。 输出格式 共一行&#xff0c;包含一个整数&#xff0c;表示 1∼n 中质数的个数。 数据范围 1≤n≤106 输入样例&#xff1a; 8输出样例&#xf…...

C语言中memmove和memcpy

1、memmove()函数 void *memmove(void *str1, const void *str2, size_t n); 将str2所指向的存储区的前n个字节复制到str1所指向的存储区。 memmove()允许“str1和str2所指向的存储区重叠”。通过检查地址关系&#xff0c;自动选择复制方向&#xff08;从前往后或从后往前&a…...

GESP2024年6月认证C++八级( 第三部分编程题(2)空间跳跃)

参考程序&#xff1a; #include <cstdio> #include <vector> #include <queue> #include <utility> #include <cstring> using namespace std;// 定义一个结构体&#xff0c;用于 Dijkstra 优先队列中的节点 struct Node {int v, w; // v 表示图…...

使用DeepSeek定制Python小游戏——以“俄罗斯方块”为例

前言 本来想再发几个小游戏后在整理一下流程的&#xff0c;但是今天试了一下这个俄罗斯方块的游戏结果发现本来修改的好好的的&#xff0c;结果后面越改越乱&#xff0c;前面的版本也没保存&#xff0c;根据AI修改他是在几个版本改来改去&#xff0c;想着要求还是不能这么高。…...