文章目录一、效果1.1、原视频1.2、效果视频1.3、静图效果二、简介三、环境准备3.1、安装依赖3.2、YOLOv8 类别说明四、核心解析4.1、检测目标过滤4.2、类型映射适配你 Vue 前端4.3、3D 坐标映射4.4、性能优化五、使用方法六、完整源码与我之前写的这篇文章呼应【Web】使用Vue3开发3D游戏九纹理视觉效果一、效果1.1、原视频路况1.2、效果视频路况识别效果1.3、静图效果二、简介在行车记录仪路况分析、道路障碍物检测、智能驾驶仿真场景中行人、车辆识别是最基础也是最核心的能力。本文基于 YOLOv8 实现本地 MP4 视频实时检测精准区分行人、轿车、摩托车、货车、巴士等交通参与者同时适配 Vue3 PlayCanvas 3D 前端 数据协议输出标准化障碍物类型可直接对接 3D 场景做障碍物映射非常适合做仿真项目、机器狗路况感知、Web3D 可视化开发。三、环境准备3.1、安装依赖运行pipinstallultralytics opencv-python websocketsultralyticsYOLOv8 官方库一行加载模型、推理opencv-python视频读取、画面绘制、编码推流websockets向前端实时推送视频流 障碍物数据3.2、YOLOv8 类别说明YOLOv8 预训练模型自带 80 个类别路况常用关键类别类别ID 对应物体0行人 person1自行车2轿车car3摩托车5巴士公交车7卡车货车业务规则所有车辆统一归类为 car 类型 1行人固定 type0完美适配你 Vue3 前端 mapTypeToModel 映射规则consttypeMap{0:person,1:car};四、核心解析只检测行人 全部车辆过滤无关物体绘制矩形框标记目标适配前端协议人type0所有车type1WebSocket 同时推送 视频画面 3D 障碍物坐标优化帧率、控制 CPU 占用不卡顿服务器固定端口 9090兼容你现有 Vue 前端连接4.1、检测目标过滤只保留路况有效目标ifcls_idnotin[0,1,2,3,5,7]:continue排除猫、狗、椅子等无关物体减少无效计算、降低 CPU。4.2、类型映射适配你 Vue 前端ifcls_id0:obj_type0# 行人 → personelse:obj_type1# 所有车辆 → car完美对应前端consttypeMap{0:person,1:car}4.3、3D 坐标映射根据画面中目标左右位置归一化映射为 3D 场景左右偏移前后固定实现视频里人 / 车往左 → 3D 障碍物往左视频里人 / 车往右 → 3D 障碍物往右4.4、性能优化压缩视频分辨率推理大幅降 CPU控制检测间隔不无限死循环占用资源异常连接捕获不抛崩溃错误视频播放完毕自动循环无需手动重启五、使用方法把行车记录仪路况视频命名为 test.mp4放在同目录安装依赖后直接运行python3 mp4_websocket_stream.pyVue3 前端直接连接 ws://ip:9090自动接收实时摄像头画面行人 / 车辆 3D 障碍物数据自动渲染对应模型适配场景Web3D 智能驾驶仿真机器狗 / 无人车路况感知可视化行车记录仪视频 AI 分析PlayCanvas Vue3 前后端联合开发路口行人车辆检测统计六、完整源码importasyncioimportwebsocketsimportjsonimportbase64importcv2importthreadingimporttimefromultralyticsimportYOLO# 配置 VIDEO_PATH./test.mp4WEBSOCKET_HOST0.0.0.0WEBSOCKET_PORT9090JPEG_QUALITY60MOVE_SCALE2.5DETECT_INTERVAL0.05# latest_frame_bytesNoneobstacle_list[]# 加载YOLO模型modelYOLO(yolov8n.pt)defvideo_loop():globallatest_frame_bytes,obstacle_list capcv2.VideoCapture(VIDEO_PATH)fpscap.get(cv2.CAP_PROP_FPS)or25whileTrue:ret,framecap.read()ifnotret:cap.set(cv2.CAP_PROP_POS_FRAMES,0)continue# 降低分辨率省CPUsmall_framecv2.resize(frame,(640,360))h,wsmall_frame.shape[:2]obs[]# YOLO推理resultsmodel(small_frame,conf0.5,verboseFalse,imgsz320)forresultinresults:forboxinresult.boxes:cls_idint(box.cls[0])# 只检测 人 车ifcls_idnotin[0,1,2,3,5,7]:continue# 画框x1,y1,x2,y2map(int,box.xyxy[0])cv2.rectangle(small_frame,(x1,y1),(x2,y2),(0,255,0),2)# 计算3D坐标cx(x1x2)/2norm_x(cx-w/2)/(w/2)# # 前端要求人0车1# ifcls_id0:obj_type0# 人else:obj_type1# 所有车辆统一为 car# 你的正确坐标完全不动obs.append({track_id:int(box.id[0])ifbox.idisnotNoneelse100,type:obj_type,x:10,y:-norm_x*MOVE_SCALE,z:5.0,width:0.6,height:1.7,length:0.6,heading:0.0})obstacle_listobs# 修复这里cv2.imencodeok,jpegcv2.imencode(.jpg,small_frame,[cv2.IMWRITE_JPEG_QUALITY,JPEG_QUALITY])ifok:latest_frame_bytesjpeg.tobytes()time.sleep(DETECT_INTERVAL)asyncdefsend_client(websocket):globallatest_frame_bytes,obstacle_listtry:whileTrue:iflatest_frame_bytes:b64base64.b64encode(latest_frame_bytes).decode()awaitwebsocket.send(json.dumps({msg:{data:b64}}))awaitwebsocket.send(json.dumps({msg:{objs:obstacle_list}}))awaitasyncio.sleep(0.05)except:passasyncdefhandle_conn(websocket):try:awaitsend_client(websocket)except:passasyncdefmain():threading.Thread(targetvideo_loop,daemonTrue).start()asyncwithwebsockets.serve(handle_conn,WEBSOCKET_HOST,WEBSOCKET_PORT):print(✅ 启动成功人0车1端口9090正常)awaitasyncio.Future()if__name____main__:asyncio.run(main())