news 2026/9/24 22:28:41

纯前端实现实时3D人体姿态估计:MediaPipe BlazePose与TensorFlow.js实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
纯前端实现实时3D人体姿态估计:MediaPipe BlazePose与TensorFlow.js实战

在浏览器里做人体姿态估计,前几年基本还停留在调用远端API或者后端跑Python推理的阶段。今天这篇换个路子,咱们纯前端、纯JavaScript,直接调用MediaPipe的BlazePose模型,配合GHUM人体参数模型拿到的3D关键点,再用TensorFlow.js把整个推理链路在浏览器里跑起来。整套方案落地之后,摄像头对准人,页面上直接能看到一个带景深的3D人体骨架在转动,延迟低到可以实时交互。这篇文章适合对姿态检测有基础了解、想在Web端做落地验证或者做交互原型的开发者,我会把原理、选型、代码、踩坑一条龙讲清楚。

1. 核心概念拆解:BlazePose、GHUM、TensorFlow.js到底各管哪一段

1.1 BlazePose不是普通的关键点检测模型

很多人一听到姿态检测,第一反应就是OpenPose或者PoseNet。BlazePose从定位上就和它们不太一样,它是谷歌为移动端和浏览器实时推理专门设计的轻量级模型,普通人拿普通笔记本摄像头跑都能到30帧以上。

BlazePose的核心设计值得一说:它采用两阶段的检测-跟踪架构。第一阶段是人体检测器,找到画面里的人框;第二阶段才对框内的人做关键点回归。这么做的好处非常直接——关键点回归网络不需要在整张图上做滑窗扫描,计算量大幅下降。而跟踪机制进一步做了帧间复用,上一帧的人框位置经过光流和对齐后直接作为下一帧的候选框,省掉一大半重复检测的开销。

关键点数量上,BlazePose输出33个身体关键点,比COCO的17点多了将近一倍。多出来的点集中在面部轮廓、手掌、脚踝这些部位,尤其是面部和手部的关键点,为后续的表情捕捉、手势识别留了接口。这里要注意,多出来的点并非简单标注,而是跟GHUM模型一一对应,这也是它能够输出真正3D坐标的前提。

1.2 GHUM模型在3D关键点生成中的角色

GHUM是微软研究院提出的人体参数化模型,全称是Generative Human Model。它的特点是可微分、可学习,本身就是一个神经网络生成器,输入姿态参数和形状参数,输出人体网格顶点和关键点位置。

BlazePose的3D标注数据,官方给出的方案是把GHUM模型拟合到二维关键点数据上,用模型生成的三维关键点作为监督信号。也就是说,BlazePose训练时看到的3D标注不是手工标注的,而是GHUM这个参数化人体模型生成的。

用GHUM生成标注有一个很好的副产品:坐标系是对齐的。所有3D关键点使用统一的以髋部中心为原点的局部坐标系,X轴朝画面右侧,Y轴朝上,Z轴朝向观察者方向(也就是指向屏幕外,越接近摄像头Z值越大)。这就让模型学到的3D关键点天然带上了模型的先验约束,关节角度、肢体长度的合理性都有保证。

有了这层关系,我们在前端拿到33个3D关键点之后,不用再去绞尽脑汁换算坐标系或者做尺度归一化,直接使用GHUM坐标系的约定来处理就对了。髋部中心在数组索引里是第24个关键点(Index 24),这一点在后面的姿态角计算里会反复用到。

1.3 TensorFlow.js在链路里的定位

TensorFlow.js在这个方案里的角色比较微妙。它并不是唯一跑推理的引擎——MediaPipe的Tasks API默认自带基于WASM和WebGL的推理后端。那我们为什么还要扯上TensorFlow.js?

原因有两层。

第一层,MediaPipe底层依赖TFLite格式的模型,而TFLite Runtime的Web端实现跟TensorFlow.js共享大量基础设施。你在浏览器里用MediaPipe加载一个.task文件,本质上是TFLite模型在WebAssembly/WebGL后端上执行,这跟TensorFlow.js跑TFLite模型的机制是一脉相承的。

第二层,也是更实际的意义:当你需要把BlazePose的输出接入自定义神经网络,比如用关键点序列做动作分类、用3D坐标做异常检测,你就必须在TensorFlow.js里写模型推理了。MediaPipe只管输出关键点,而后续所有基于关键点的“智能化”处理,几乎都离不开TensorFlow.js或者ONNX Runtime Web这类工具。

所以我的理解是:MediaPipe负责把关键点“抠”出来,TensorFlow.js负责干活。前端处理的整个闭环,就是这两者配合完成的。

2. 技术选型:为什么不用Python服务器方案

2.1 纯前端方案和传统服务器的核心差异

早期做姿态检测,常规套路是前端把视频帧上传到服务器,Python端用OpenCV加MediaPipe处理,再把关键点JSON返回给前端。这一套逻辑简单,但有几个痛点很难绕过去。

首先是延迟。一帧图像从编码、上传、推理到返回,至少需要80到120毫秒的往返时间,这还建立在服务器性能充沛的前提下。对于实时交互应用,比如体感游戏、健身计数、手势控制,这个延迟是会直接让用户觉得“不跟手”的。

其次是服务器成本。视频帧率30帧每秒,每一帧都上传,带宽和GPU的消耗是很可观的。如果并发用户一多,服务器就得不断扩容,成本压力比开发压力大得多。

纯前端方案的优势就在这里体现出来了。模型文件一次加载后缓存在浏览器里,之后的每一帧推理都在本地完成。整个推理过程零网络请求,延迟只取决于本机算力,帧率稳定后体感上是即时响应的,尤其适合做面向普通用户的Web应用。

2.2 MediaPipe Tasks API和旧版JavaScript解决方案的取舍

MediaPipe以前在浏览器端的方案需要手工搭配模型文件和算子库,配置过程非常容易踩坑,版本之间兼容性问题也多,甚至不同浏览器表现不一致的情况都有。我早期用旧方案做项目的时候,光是解决wasm加载失败就折腾了好几天。

现在官方主推MediaPipe Tasks Vision API,整个体验好了不止一个档次。这个API把模型加载、预处理、推理、后处理封装成了一个高层接口,我们只需要提供模型地址和配置项,PoseLandmarker对象就自动处理了所有细节。

Tasks API带来一个特别实际的好处:模型和运行时完全解耦。你可以把.tflite格式的模型文件放到自己的CDN上,或者干脆用官方托管的地址,换模型不需要改任何逻辑代码。这跟直接在GitHub仓库里找现成代码库相比,可维护性强太多。

所以我的建议是:新项目一律使用Tasks Vision API。如果你在网上翻到教你用旧版的教程,除非是维护老项目,否则可以直接跳过。

3. 实操:纯前端3D姿态检测的完整实现

3.1 搭建最小工程并加载PoseLandmarker

工程方面不用复杂框架,我直接用Vite打底建一个原生JavaScript项目,能省去不少配置时间。

参考资料:初始化项目后,安装依赖就一个包需要处理:

npm init -y npm install @mediapipe/tasks-vision npm install three # 3D可视化会用

然后就是一个HTML文件加一个JavaScript入口文件就能撑起整个应用。页面里需要有视频元素用来承载摄像头画面,一个Canvas用来叠加2D骨架,另一个Canvas用来给Three.js画3D骨架。

加载模型的核心代码长这样:

import { FilesetResolver, PoseLandmarker } from "@mediapipe/tasks-vision"; const vision = await FilesetResolver.forVisionTasks( "https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@latest/wasm" ); const poseLandmarker = await PoseLandmarker.createFromOptions(vision, { baseOptions: { modelAssetPath: "https://storage.googleapis.com/mediapipe-models/pose_landmarker/pose_landmarker_lite/float16/1/pose_landmarker_lite.task", delegate: "GPU" }, runningMode: "VIDEO", numPoses: 1, minPoseDetectionConfidence: 0.5, minPosePresenceConfidence: 0.5, minTrackingConfidence: 0.5 });

这里有两个参数值得单独解释。第一个是delegate字段,MEDIAPIPE官方在浏览器端支持CPU和GPU两种委托,默认建议GPU。GPU的WebGL后端推理速度通常比CPU快一到两倍,但GPU的精度普遍比CPU低一点,关键点在画面里大量遮挡的时候偶尔会出现跳变。实测下来我的建议是,演示项目用GPU没问题,如果做动作识别这种对关键点稳定性要求高的场景,CPU反而更稳。

第二个是modelAssetPath,我上面用的是官方托管地址里的lite版本。如果追求更高精度,同一路径下还有full版本,代价是加载体积和推理时间都翻倍。做Web端交互优先选lite,因为抖动和延迟对体验的伤害远大于那么一点精度。

3.2 打开摄像头并进入实时检测循环

摄像头捕获直接用浏览器原生方法:

const video = document.getElementById("video"); const stream = await navigator.mediaDevices.getUserMedia({ video: { width: 640, height: 480, facingMode: "user" } }); video.srcObject = stream; await video.play();

注意,PoseLandmarker的runningMode选择的是VIDEO模式,对应的检测接口是detectForVideo,它要求传入一个带时间戳的VideoFrame对象。跟detect(针对静态图像)不同,VIDEO模式内部会利用帧间跟踪信息,让关键点的连续性提升很多。

检测循环用requestAnimationFrame驱动,每次取视频当前帧做推理:

function loop() { if (video.readyState >= 2) { const now = performance.now(); const results = poseLandmarker.detectForVideo(video, now); draw2DSkeleton(results); draw3DSkeleton(results); } requestAnimationFrame(loop); } loop();

这里有一个特别容易翻车的点:detectForVideo的第二个参数时间戳必须是递增的,否则内部跟踪逻辑会重置。很多人直接用Date.now()转毫秒,结果发现模型一会有一会没有,就是时间戳抖动导致的。用performance.now()就不会有这个问题,它天然单调递增。

拿到了results之后,我们关心的结构在results.landmarks里。这是一个数组,每个元素是33个关键点的列表(因为设了numPoses: 1,数组长度为1)。每个关键点对象有x、y、z、visibility四个属性,前三个是归一化坐标,范围0到1,visibility是可见性置信度。

3.3 把关键点画成2D骨架并计算关节角度

在把3D可视化之前,先画2D骨架能帮我们快速验证检测链路是不是通的。绘制每个关键点很简单,但连线才是骨架的精髓。MediaPipe官方给了一个连接关系表:比如点11是左肩,点13是左手肘,点15是左腕,它们之间的连线就是手臂。

我项目中用的核心连接关系简化版:

const CONNECTIONS = [ [11, 12], [11, 13], [13, 15], // 左臂 [12, 14], [14, 16], // 右臂 [11, 23], [12, 24], // 躯干 [23, 24], // 髋部 [23, 25], [25, 27], // 左腿 [24, 26], [26, 28] // 右腿 ];

画线的时候,别忘了缩放:

function draw2DSkeleton(results) { const ctx = canvas2d.getContext("2d"); ctx.clearRect(0, 0, canvas2d.width, canvas2d.height); const landmarks = results.landmarks[0]; if (!landmarks) return; CONNECTIONS.forEach(([i, j]) => { const a = landmarks[i]; const b = landmarks[j]; ctx.beginPath(); ctx.moveTo(a.x * canvas2d.width, a.y * canvas2d.height); ctx.lineTo(b.x * canvas2d.width, b.y * canvas2d.height); ctx.stroke(); }); landmarks.forEach((p) => { ctx.beginPath(); ctx.arc(p.x * canvas2d.width, p.y * canvas2d.height, 4, 0, Math.PI * 2); ctx.fillStyle = "#00ffcc"; ctx.fill(); }); }

这个阶段如果骨架能跟着人动,说明链路已经通了,下一步才是重头戏——3D可视化。

顺便讲讲关节角度计算,因为姿态检测最终一定会落到“这个人手臂抬了多少度”“膝盖弯曲是否标准”这类问题上。角度计算的原理是三维向量夹角,用点积公式:

function angle3D(a, b, c) { const v1 = { x: a.x - b.x, y: a.y - b.y, z: a.z - b.z }; const v2 = { x: c.x - b.x, y: c.y - b.y, z: c.z - b.z }; const dot = v1.x * v2.x + v1.y * v2.y + v1.z * v2.z; const len1 = Math.hypot(v1.x, v1.y, v1.z); const len2 = Math.hypot(v2.x, v2.y, v2.z); return Math.acos(dot / (len1 * len2)) * 180 / Math.PI; }

以肘关节为例,b点是肘部(关键点13),a点是肩膀(关键点11),c点是手腕(关键点15),三者的三维坐标代入这个函数,就能算出肘关节的弯曲角度。这就是后面做深蹲计数、开合跳判定的基础。

这里有一个我对新手的建议:做动作识别前先花时间校准动作。不同人的肢干比例不一样,直接用关键点坐标判断动作幅度有时候会误判。比如浅蹲和深蹲的区分,基于髋关节和膝关节的角度阈值来做判断,比基于像素位移可靠得多。

3.4 用Three.js绘制3D骨架

3D可视化的思路是把关键点的归一化坐标映射到Three.js的三维空间里,然后用线段把关键点连起来。这里有个细节需要注意:2D画布坐标系是原点在左上角,Y轴向下;而3D渲染里我们通常希望Y轴向上,所以渲染前要做一次坐标翻转。

我的做法是写一个简单的转换函数:

function landmarksToVector3(lm, scale = 3) { return new THREE.Vector3( (lm.x - 0.5) * scale, (0.5 - lm.y) * scale, lm.z * scale ); }

把归一化坐标以0.5为中心平移到原点,然后把Y轴方向翻转,Z轴直接放大使用。scale可以根据场景大小调,我这里取3表示半米范围,基本能容纳一个成人。

然后用三种Three.js元素来呈现骨架:关键点用小SphereGeometry球体,连接线用BufferGeometry的线段,为了好看我还会给左右肢体用不同颜色。

const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera(50, canvas3d.clientWidth / canvas3d.clientHeight, 0.1, 100); camera.position.set(0, 0, 5); const renderer = new THREE.WebGLRenderer({ canvas: canvas3d, antialias: true }); renderer.setSize(canvas3d.clientWidth, canvas3d.clientHeight); const group = new THREE.Group(); scene.add(group); function update3DSkeleton(results) { // 清空旧骨架 while (group.children.length) group.remove(group.children[0]); const landmarks = results.landmarks[0]; if (!landmarks) return; // 绘制关键点 landmarks.forEach((lm) => { const sphere = new THREE.Mesh( new THREE.SphereGeometry(0.05, 8, 8), new THREE.MeshBasicMaterial({ color: 0x00ffcc }) ); sphere.position.copy(landmarksToVector3(lm)); group.add(sphere); }); // 绘制连接线 const points = CONNECTIONS.map(([i, j]) => { return [ landmarksToVector3(landmarks[i]), landmarksToVector3(landmarks[j]) ]; }); points.forEach(([a, b]) => { const geometry = new THREE.BufferGeometry().setFromPoints([a, b]); const line = new THREE.Line(geometry, new THREE.LineBasicMaterial({ color: 0xffaa00 })); group.add(line); }); }

渲染循环里别忘了调用renderer.render,这样整个3D骨架就能实时转动了。再加上OrbitControls插件,还可以在页面上拖拽旋转视角,从不同方向观察姿态。这对做动作评估特别有用,因为正面看不清的角度,转到侧面一眼就能看出来问题。

4. 常见问题与排查技巧实录

4.1 模型加载慢或者加载失败

模型文件本身有5MB左右,托管在Google的存储空间上。国内部分地区访问这个地址偶尔会超时或者速度很慢,这是很多人碰到的第一个坎。

我的解决方案是把模型下载下来放在自己服务器或者CDN上。MediaPipe允许你传入任何可访问的URL作为modelAssetPath,所以完全可以把.task文件部署到自己的静态资源目录里。需要注意两点:一是要配置正确的CORS头,否则浏览器跨域请求会被拦截;二是尽量用HTTPS,因为getUserMedia在非安全上下文下会被禁用。

排查的时候先看Network面板,确认.task文件是否返回200。如果返回200并且Content-Length符合预期但加载还是失败,多半是CORS配置问题,在CORS响应头里加入Access-Control-Allow-Origin: *基本就能解决。

4.2 帧率低和丢帧问题

帧率低的原因通常有三类。第一类是视频流分辨率太高,把640x480的画面直接喂进去就行,画面细节对姿态估计的帮助有限,但计算量会成倍增加。第二类是同时跑了2D绘制和3D渲染,Three.js的渲染其实也吃性能,可以考虑降低canvas3d的分辨率或者降低渲染帧率,比如每两帧推理一次、每帧都渲染。

第三类是我踩过的一个坑:在GPU delegate模式下,移动端的某些GPU驱动对WebGL的支持有兼容性问题,导致推理速度反而比CPU慢。遇到这个情况就切换delegate到CPU,两行代码的事,但很多人卡了很久没方向。

4.3 关键点抖动怎么平滑

姿态估计输出的关键点帧与帧之间有抖动是很正常的,尤其是手和脚这些运动幅度大的部位。直接拿原始坐标去做角度计算,角度值会跳来跳去,根本没法用。

目前我在项目里用的是一阶指数移动平均(EMA)做轻量平滑。原理很简单:当前帧的坐标由上一帧的坐标和当前帧的原始值按权重混合得到。

const smooth = {}; function smoothLandmark(idx, raw, alpha = 0.4) { if (!smooth[idx]) { smooth[idx] = { x: raw.x, y: raw.y, z: raw.z, visibility: raw.visibility }; } else { smooth[idx].x += alpha * (raw.x - smooth[idx].x); smooth[idx].y += alpha * (raw.y - smooth[idx].y); smooth[idx].z += alpha * (raw.z - smooth[idx].z); } return smooth[idx]; }

alpha取0.3到0.5之间比较合适。alpha太小响应慢,动作反射弧太长;alpha太大又起不到平滑作用。对于需要实时反馈的场景,我试下来0.35左右是手感最好的。

如果对平滑质量要求更高,可以考虑One Euro Filter这种更专业的自适应低通滤波器,它对低频运动保留细节、对高频抖动抑制明显,效果比EMA好一个档次,但实现复杂度也高不少。

4.4 画面里多个人只检测到一个

PoseLandmarker默认可以设置numPoses大于1来检测多人姿态。但要注意两点:首先numPoses增大会让推理时间增加,因为模型需要在画面里寻找多个目标;其次人数的跟踪逻辑在浏览器端还是有瓶颈,实测达到3人以上,帧率就会明显下降。

实际项目里如果是固定场景、固定机位,我更建议把区域裁切好,一次只处理一个人,精度和帧率都能保住。

5. 应用落地与自定义模型的扩展思考

5.1 从Demo到实用产品需要跨过哪些坎

3D姿态检测在网页里跑通之后,能玩的方向非常多。我自己做过或者见过做得比较好的几个方向:

健身动作计数是门槛最低的落地场景。拿到关键点之后计算关节角度,用角度的时间序列做波峰检测或者状态机切换,就能实现深蹲、俯卧撑、引体向上的自动计数。再加上一个动作标准度评分,利用角度偏差或者关键点轨迹跟标准模板进行比对,整个产品的体验就立起来了。

康复训练评估是另一个很有价值的方向。传统康复训练需要治疗师全程陪护,通过网页姿态检测可以做一个居家康复辅助工具,给出关节活动度报告、左右侧对称性分析,还能记录一段时间内的恢复趋势。

体感交互类应用也值得提一下。这一点在展厅、游戏行业已经有成熟实践,用身体控制屏幕上的人物或者菜单,本质上就是把手柄摇杆映射成髋关节或手腕的位移。

5.2 Model Maker能不能自定义姿态模型

很多人搜到MediaPipe Model Maker,第一反应是能不能用它训练自己的姿态检测模型。这里我直接说结论:目前Model Maker的官方支持范围是图像分类、目标检测、文本分类、文本问答和推荐器,并不包含姿态估计模型的自定义训练。

那想要自定义姿态模型怎么办?目前业内比较现实的路径有三条。

第一条是训练一个关键点之后的分类器,而不是训练姿态模型本身。也就是说,用BlazePose输出关键点坐标作为特征,喂给一个你自己用TensorFlow.js或TensorFlow训练的小型MLP或者LSTM网络,用来识别自定义动作。这条路非常推荐,因为特征维度只有33乘3等于99维,数据量不需要很大,普通笔记本电脑就能训练。我做过一个“摔倒检测”的分类器,就是基于关键点速度、加速度和角度特征训练出来的,精度很理想。

第二条是知识蒸馏。如果你想让自己定义的姿态检测模型直接跑在浏览器上,可以用TensorFlow训练一个大模型,再用蒸馏技术把知识迁移到一个小模型,最后通过TensorFlow.js的Converter把模型转成Web格式。这个路线技术含量高不少,优点是完全脱离MediaPipe的桎梏,模型可以完全为自己定制。

第三条是找现成的高精度姿态模型然后微调,比如COCO-WholeBody数据集上训练过的模型,在整脸和手部关键点的覆盖度上更有优势。

这里我的个人建议是:绝大多数业务场景,直接用BlazePose输出的关键点就已经够了。姿态估计只是上游信号,真正的产品竞争力在关键点之后的理解和应用层。把精力花在动作语义建模和交互体验上,收益远大于从头训练一个姿态模型。

5.3 模型量化与部署优化方向

如果将来要做大规模用户侧的部署,模型体积和推理速度都需要进一步优化。MediaPipe的PoseLandmarker本身提供了不同的量化版本,我有次测试时在移动端用int8量化版本,模型体积能压到2MB以内,推理速度提升了30%以上,精度损失在可接受范围内。

TensorFlow.js也有自己的优化手段:开启WebGL后端、使用模型转换工具做图优化、避免在每一帧推理时重复创建对象,都是能实打实看到性能提升的操作。

另外一个容易被忽略的点是缓存策略。模型文件是静态的,完全可以设置HTTP缓存,让二次访问直接走本地缓存,加载时间从秒级降到毫秒级。配合Service Worker做离线缓存,整个应用甚至可以做到断网可用。

前端姿态检测这条路走到现在,已经没有明显的技术瓶颈了。模型在浏览器里跑,摄像头直接访问,关键点实时输出,3D渲染即时呈现,整条链路都是通的。剩下的事情,就是看我们怎么把这个能力用出花来了。

最后分享一个小经验:我在实际开发里发现,无论检测效果多么丝滑,永远不要忘了给用户一个“检测失败”的兜底提示。光线太暗、人离镜头太远、身体被遮挡,这些情况都会让关键点的可信度下降。与其硬着头皮给出错误的姿态数据,不如在界面里结合每个关键点的visibility字段做一个置信度指示。这个细节看着不起眼,但对产品的专业感提升立竿见影。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/24 22:28:40

AI绘画制作微信表情包全流程:提示词技巧、审核规则与变现思路

直接上手先说结论:用AI做微信表情包这件事,真不是智商税,只要你愿意花两三个周末研究提示词和平台规则,完全能做出能过审、能上架、能被人下载的成品。至于月入过万,我劝你先把它当成“目标”,而不是“承诺…

作者头像 李华
网站建设 2026/9/24 22:28:09

Vue+Node.js+微信小程序校园跑腿点餐系统全栈开发实战

几周前帮朋友捣鼓了一个校园跑腿点餐的小项目,前后端加小程序端折腾了大概三天。最近后台数据涨得不错,顺手把整套实现思路整理出来。这篇文章不会讲太多花哨的架构设计,全是实际能跑通的代码路径和踩坑记录,希望对正在做类似毕业…

作者头像 李华
网站建设 2026/9/24 22:27:55

OnchainOS:给 AI Agent 一个可信的链上运行环境

大概从去年年底开始,我身边越来越多的技术朋友开始讨论一个话题:AI Agent 到底什么时候能真正"自主干活"而不是只会写周报。大家发现,模型本身已经够聪明了,卡住的往往是工程化——Agent 做着做着状态丢了,多…

作者头像 李华
网站建设 2026/9/24 22:27:32

谷物害虫目标检测:687张YOLO标注数据集训练与避坑实战

简介:谷物害虫目标检测数据集面向粮仓存储环境中的常见害虫自动检测需求,适用于农业AI开发者、智能仓储系统研发人员以及目标检测入门学习者。整包共1376个文件,包含687张实拍害虫图像与687份对应的YOLO格式标注txt,同时附有1个ya…

作者头像 李华
网站建设 2026/9/24 22:27:32

OpenCV实现视频车辆测速:检测、标定与跟踪实战

简介:面向视频车辆测速这一具体任务,一套基于Python与OpenCV的实践资源,适配计算机视觉入门者、智能交通方向学生及有课程设计需求的开发者,覆盖车辆检测、目标跟踪与速度估算的完整流程,可与B站配套演示视频配合学习。…

作者头像 李华
网站建设 2026/9/24 22:27:21

Windows原生部署DeepSeek:Ollama+环境变量+GGUF模型实战指南

1. 项目概述:为什么要在Windows上跑DeepSeek?这不是“能用就行”的事DeepSeek系列模型——尤其是DeepSeek-V2、DeepSeek-Coder、DeepSeek-MoE这些开源大模型——最近半年在开发者圈子里热度飙升。不是因为它们参数量最大,而是因为实测下来&am…

作者头像 李华