项目定位:最小可行性实验,不是成熟产品,更不是动物医疗、情绪或语言诊断系统。
@矽递科技SeeedStudio
话题标签:#Jetson暑期训练营
摘要
本项目在一块 Jetson Orin Nano 8GB 开发板上,利用一枚固定为 640×480 的 USB 摄像头和一台 reSpeaker 声学采集器,搭建了一个全本地运行的“本地宠物行为观察器”。它完成的不是“翻译动物语言”,而是把真实设备采集到的视觉候选、声学候选、声源方向、照护记录和本地大模型建议组织成一个能被网页直接查看的闭环。
核心流程为:USB 摄像头取流 → FFmpeg 推送到本机 RTSP → TensorRT YOLO 检出猫/狗类别候选 → 稳定状态记录器写入视觉证据;与此同时 reSpeaker 采集六通道音频与 DoA 方位 → 本地 YAMNet 输出声学事件候选 → 将两类时间相近、类别相符的证据交给规则层融合 → 写入 SQLite 历史库与当前状态 JSON → 本地 Qwen 模型给出受约束 JSON 格式的简短建议 → Flask 网页展示实时画面、方位、历史与建议。
项目时间和资源都非常有限,只有上述三类硬件,且没有真实动物测试对象、稳定的真实饲养环境、动物行为学标注、动物语言模型或生理传感器。因此本项目的结论仅是:在有限设备条件下,已经完成了一条可重复操作、可在网页看到实时结果的最小技术链路。它不能证明“识别了宠物的真实情绪、语言、健康或需求”。
视频链接在文章末尾结语部分。
1. 研究背景:为什么先做一个“最小能跑通”的观察器
宠物观察类项目很容易一开始就许下过大的目标,例如“听懂宠物在说什么”“判断是否生病”“自动给出喂养决策”。这些目标同时依赖可靠的动物声学模型、个体身份识别、动作/姿态模型、长周期行为标注、环境与生理数据,以及专家知识。仅凭一块边缘板、一枚低分辨率摄像头和麦克风阵列,无法严谨地完成上述任务。
因此本项目把目标主动收缩为四个可检验的问题:
- USB 摄像头能否稳定把现场画面送入 Jetson,并在本机持续产生猫/狗类别检测?
- reSpeaker 能否稳定采到多通道声音,并给出可显示的方向角?
- 声音候选与视觉候选能否按时间窗口、类别和置信度进行保守融合,而不是只看其中一路?
- 这些结果能否落到本地文件/数据库,并由本地网页直接展示给不会使用终端的普通用户?
这四个问题都得到相应实验和截图证据支持。它们构成后续扩展的底座:以后即使更换模型、加入行为学分析或健康传感器,也不必重做采集、时序对齐、数据归档和网页交互。
1.1 实验条件与边界
| 项目 | 实验条件 | 能支持的最小验证 | 不能推出的结论 |
|---|---|---|---|
| 边缘算力 | Jetson Orin Nano 8GB,JetPack 环境 | 本地视频、声学、规则和 LLM 的协同运行 | 不代表达到成熟产品吞吐或长期稳定性 |
| 视觉输入 | 固定 USB 摄像头,640×480 | 画面采集、RTSP、YOLO 猫/狗类别候选 | 不代表高精度个体识别、姿态或行为识别 |
| 声学输入 | reSpeaker Flex XVF3800,多通道采集与 DoA | 音频窗口采集、方向角、YAMNet 事件候选 | 不代表距离、精确声源位置或动物语言理解 |
| 推理模型 | YOLO TensorRT 引擎、YAMNet TFLite、本地 Qwen | 本地类别候选、受约束建议 JSON | 不代表医学/行为学专家结论 |
| 数据条件 | 控制样本、演示音频、有限真实设备联调 | 数据链路和网页功能验证 | 没有真实动物长期测试,不能评估真实准确率 |
1.2 总体数据流
USB 摄像头 ──> FFmpeg / RTSP ──> YOLO TensorRT ──> visual_latest.json ──> 稳定视觉状态 / 带框 JPEG │ reSpeaker 六通道音频 ──> WAV + DoA ──> YAMNet ──> 事件分段 ───────────────┤ v 声视融合规则 + SQLite │ 照护记录 ────────────────────────────┤ v 本地 Qwen:受约束 JSON 建议 │ v Flask 网页:实时画面、方位、历史、建议这里有一个必须坚持的原则:YOLO 输出的是“画面中存在猫/狗类别候选”;YAMNet 输出的是“声音在通用 AudioSet 标签上接近某个动物相关事件”;两者融合后也只是“同一时间段存在同类候选证据”。它们都不能自动升级为“同一只宠物发出了这个声音”或“宠物现在有某种需求”。
2. 硬件、软件与官方学习资料
本项目使用 Jetson 作为边缘端,而不是把视频和声音上传到云端。JetPack 提供 Jetson Linux、CUDA/TensorRT 等计算机视觉与 GPU 加速基础;NVIDIA 的 Jetson Orin Nano 入门资料也说明了其面向边缘 AI 和本地推理的使用方式。Jetson Orin Nano 入门指南、JetPack 官方说明。
视觉模型使用 Ultralytics YOLO 的 TensorRT 引擎。Ultralytics 官方文档说明engine格式用于 NVIDIA TensorRT 推理,适合在 NVIDIA GPU 上部署检测任务。Ultralytics TensorRT 集成文档。
声学模型使用 YAMNet。它是基于 MobileNet_v1 的通用音频事件分类模型,训练于 AudioSet 的 521 类标签;因此它适合提供“候选标签”,不适合作为宠物语言翻译器。TensorFlow Hub YAMNet 官方教程。
reSpeaker 使用 XVF3800 系列 USB 麦克风阵列。官方资料提供 2 通道与 6 通道固件,项目选择多通道采集以保留 DoA 相关信息。reSpeaker XVF3800 文档、reSpeaker Flex 文档。
本地建议调用 Ollama 的/api/chat;官方 API 支持消息数组,并可要求format: "json"返回 JSON,正好用于把生成结果限制为网页可以可靠读取的结构。Ollama Chat API。
2.1 实际项目文件职责
远端项目目录为/home/syc/projects/pet-observer。下表只列核心实现,不把 Python 环境、模型和日志目录混在一起。
| 文件 | 作用 |
|---|---|
pet_observer/collector.py | 采集 reSpeaker 六通道 WAV、DoA 样本、RMS 等元数据 |
pet_observer/yamnet_infer.py | 运行本地 YAMNet TFLite,输出声学候选窗口 |
pet_observer/segment_events.py | 合并重叠候选窗口,生成更适合展示的事件段 |
pet_observer/visual_worker.py | 从 RTSP 读帧,运行 YOLO,仅保留猫/狗类别候选 |
pet_observer/visual_state_recorder.py | 通过滑动窗口与连续命中条件,把瞬时检测变为稳定视觉证据 |
pet_observer/visual_frame_renderer.py | 将最新检测框画到 JPEG,供网页显示 |
pet_observer/fuse_modalities.py | 按时间、物种和阈值融合声学与视觉证据,写 SQLite 和当前状态 JSON |
pet_observer/local_advisor.py | 汇总照护记录与事件历史,调用本地 Qwen,保存建议 JSON |
pet_observer/history_webapp.py | Flask API 与网页;展示当前状态、历史、方位、实时画面和建议 |
scripts/run_live_visual_monitor.sh | 实时视觉总控,当前 YOLO 阈值为 0.50、上限 10 FPS |
scripts/run_live_audio_fusion.sh | 实时声学采集、YAMNet、分段和融合;真实数据写入data/live/ |
scripts/run_live_monitor.sh | 启动视觉、声学和 JPEG 渲染三个后台子流程 |
3. 视觉流水级推流实现:USB 摄像头到 YOLO 检测
3.1 为什么不让 YOLO 直接独占 USB 摄像头
最开始若让某一个 Python 进程直接打开/dev/video0,网页预览、调试工具和 YOLO 进程会争用同一设备,也不利于之后替换检测模型。因此本项目先将 USB 摄像头转成 Jetson 本地 RTSP 流,再由多个消费者读取同一个地址。
实际链路为:USB 摄像头输出 MJPEG → FFmpeg 编码 H.264 并发布到本机 MediaMTX →rtsp://127.0.0.1:8554/cam1→ YOLO 与 JPEG 渲染器分别取流。
图 1 不是普通的命令截图:它同时给出 RTSP 来源、video_connected: true、640×480 帧尺寸、TensorRT 引擎路径和狗类别候选。它对应本节的结论是“视觉输入已到达模型并写出结构化 JSON”。
启动 MediaMTX 后,实际使用的推流命令如下:
ffmpeg-fv4l2-input_formatmjpeg-framerate15-video_size640x480\-i/dev/video0-an-c:vlibx264-presetultrafast-tunezerolatency\-pix_fmtyuv420p-g15-frtsp-rtsp_transporttcp\rtsp://127.0.0.1:8554/cam1v4l2是 Linux 视频设备接口;FFmpeg 官方设备文档将它列为输入设备接口,并说明视频尺寸、帧率等由设备能力决定。FFmpeg Devices 文档。本项目将摄像头固定为 640×480,是硬件与现有画面条件下的明确限制,而非为了宣称高分辨率能力。
3.2 YOLO TensorRT 推理与类别筛选
YOLO 不需要识别“豆豆是谁”,只承担 COCO 猫/狗类别检测。visual_worker.py加载/home/syc/yolo/yolo_test/yolo11n.engine,推理时只选择猫、狗类别,并把框坐标、类别、置信度和时间写入data/vision/visual_latest.json。
当前实时视觉脚本的关键调用为:
/home/syc/yolo/yolo_test/.yolo_test/bin/python\pet_observer/visual_worker.py\--rtsp-url rtsp://127.0.0.1:8554/cam1\--model/home/syc/yolo/yolo_test/yolo11n.engine\--profiledata/vision/pet_profile.json\--outputdata/vision/visual_latest.json\--confidence0.50--max-fps10这里的“宠物名”来自单宠物人工配置关联,而不是 ReID 或个体身份识别。报告中保留这一点,是为了避免把dog类别框误写成“已经识别出某一只真实宠物”。
图 2 对应“持续运行”而非“单帧成功”:终端连续出现detections=1 saved=visual_latest.json,说明消费者持续从 RTSP 读取并覆盖最新状态。
3.3 稳定状态记录器:为什么不能只看单帧
单帧检测会有抖动、失焦、短暂遮挡和 RTSP 丢帧。为此visual_state_recorder.py不把每一帧都立即升级为视觉证据,而是在窗口内累计命中次数。典型验证命令为:
python pet_observer/visual_state_recorder.py\--inputdata/vision/visual_latest.json\--state-output data/vision/visual_state.json\--dbdata/pet_observer.db\--confidence0.65--window-size5--required-hits3--heartbeat-s2它解决的问题不是“提高模型准确率”,而是把“偶然一帧有框”与“连续一段时间有稳定类别候选”区分开。截图中可看到稳定记录器输出visual_pet_present_candidate,也可看到在检测帧连续为 0 时,状态退回no_stable_visual_pet_candidate。
图 3 放在状态记录器介绍之后,是为了说明失败并非“没有运行 YOLO”:截图中先出现较高检测分数,但连续命中窗口不足,最终状态仍回落。
图 4 是图 3 的对照实验。使用静止视频帧,画面稳定后,命中计数达到要求,状态记录器连续输出visual_pet_present_candidate。
3.5 视觉环节的失败记录与解决办法
失败 1:SSH 中使用autovideosink没有出现可见画面,并出现 GL/GBM 崩溃。
原因是通过 Windows PowerShell SSH 启动的 Jetson 进程没有把 Jetson 本地图形窗口转发到 Windows;日志中虽然能看到 RTSP 已连接,但图形显示端失败。解决方法不是继续依赖远端弹窗,而是:Windows 端用 VLC/FFplay 打开 RTSP,或在项目中直接由 YOLO 读 RTSP 并写带框 JPEG 给网页。网页链路不依赖autovideosink。
失败 2:摄像头画面模糊、640×480 且目标不稳定,状态记录器不确认。
截图显示它不是“模型完全失效”,而是连续命中数不足。当前视觉采集对象是在平板电脑上播放的动物音频影像,视频分辨率、摄像头采集分辨率、采集距离与角度、平板电脑屏幕亮度与反射环境光等现实问题均会造成实验捕获视觉数据严重失真,解决方式是保留稳定状态记录器、提高现场画面稳定性,使用静止暂停的稳定视频帧、合理的采集角度与距离完成路径可达性验证实验,并将“视觉证据”措辞限制为候选。未来可升级摄像头、曝光/对焦、检测模型与行为模型。
4. YAMNet 本地部署:把声音变成“候选事件”,而不是动物语言
4.1 YAMNet 的作用和局限
YAMNet 输入音频波形,输出 521 类通用声音事件分数。它不是专门为本项目宠物、品种、个体或情绪训练的模型。也就是说,Bark、Dog、Animal等标签的含义是“模型认为这个音频窗口与某些 AudioSet 类别相近”,不是“已经确定宠物在表达饥饿、焦虑或疾病”。
项目选择本地 TFLite 版本,模型与类别映射保存在:
models/yamnet.tflite models/yamnet_class_map.csv单条音频推理的实际命令模式如下:
python pet_observer/yamnet_infer.py\--wav"$(ls-tdata/controls/dog_phone_0deg/*_6ch.wav|head-n1)"\--threshold0.050.05是候选收集阈值,不是最终告警阈值。较低阈值的目的是宁可保留候选,后续再通过事件分段、双流融合和网页显示门槛进行保守筛选。
4.2 音频采集、YAMNet、事件分段
实时声学链路每轮采集 20 秒:
python pet_observer/collector.py\--duration-s20\--output-dir data/live/audio_visual python pet_observer/yamnet_infer.py\--wavdata/live/audio_visual/<时间戳>_6ch.wav\--threshold0.05python pet_observer/segment_events.py\--yamnet-json data/live/audio_visual/<时间戳>_6ch_yamnet.json采集器同时保存原始六通道 WAV、元数据 JSON 和 DoA 样本。segment_events.py将相邻/重叠候选窗口合并为可展示事件段,避免网页把同一段连续声音拆成大量几百毫秒卡片。
4.3 正负控制样本的意义
截图正负样本结果测试.png表明项目没有只拿“狗叫”样本自证成功,而是分别采集了:
data/controls/dog_phone_0deg/ data/controls/no_pet_control/狗叫手机播放样本中,YAMNet 可出现Bark、Whimper (dog)、Howl等候选;无宠物控制样本中也可能出现动物相关候选。这一现象非常关键:通用声学模型在有限环境下会有误报,不能把一次标签出现当成真实宠物状态。因此该项目后来要求视觉佐证,并保留“低置信候选”“待人工确认”等状态,而不是直接输出结论。
图 5 上半部分是播放犬吠音频的实时采集结果,下方是无声采集结果。上半部分的左侧能看到狗叫播放时出现的动物相关候选,右侧无宠物样本也会产生候选;这正是后续必须进行声视融合、不能让 YAMNet 单独告警的实证原因。
5. reSpeaker 设备测试与声源方位(DoA)
5.1 为什么要单独验证 DoA
多通道麦克风的价值不只是“录到声音”,还可以从不同麦克风的到达时间差估计一个方向角。这个方向角在网页上显示为声源方位图,可帮助用户知道候选声音大致来自前、后、左或右。
项目通过 XVF3800 控制接口查询DOA_VALUE。实际使用的命令形态为:
sudo/home/syc/projects/pet-observer/.pet-observer/bin/python\/home/syc/projects/pet-observer/tools/python_control/xvf_host.py\DOA_VALUE--vid0x2886--pid0x001e采集器会连续输出DOA_VALUE: [角度, 1]。项目侧对原始角度施加了校准偏移:
project_doa_deg = (raw_doa_deg + 3) % 360校准偏移的作用是对齐本项目定义的“前方 0°”;它不是通用常数,换安装方向、麦克风位置或场地后都应重新验证。
5.2 四方向验证
| 截图文件名 | 截图中的主要读数 | 说明 |
|---|---|---|
DOA角度0测试.png | DOA_VALUE在 0° 附近变化 | 前方声源的方向读数可用 |
DOA角度90测试.png | 读数从 0° 附近向约 85°/86°变化 | 右侧方向变化符合预期 |
DOA角度180测试.png | 读数约 172°~174° | 后方方向读数接近目标方向 |
DOA角度270测试.png | 读数约 265°~271° | 左侧方向读数接近目标方向 |
这些截图支持“该装置能够输出与人为摆放方向大致对应的方位角”。它们不支持“可以测距离”“可以精确定位到某个坐标”“复杂房间内抗反射可靠”的结论。网页中也明确注明:reSpeaker DoA 只提供方向,不提供可靠距离。
图 6~图 9 组成同一组四方向实验,四张图按顺序依次为0°,90°,180°,270°方向测试;每张图的读数均有小幅波动,但分别落在对应象限附近。
5.3 reSpeaker 环节的失败记录与解决办法
DoA 本身没有被当作独立的宠物判据。其原因是角度在播放声音、反射、背景噪声和安装偏差下会变化;截图中同一方向也存在读数波动。因此系统保留多次样本、环形平均和校准角度,只把结果作为声学候选的辅助字段显示和记录。
6. 双流融合:从“两个候选”到“保守的声视佐证”
6.1 融合规则
fuse_modalities.py读取一份*_events.json与 SQLite 中的稳定视觉记录,并在给定时间窗口内寻找“同类视觉证据”。核心输入与输出如下:
输入:声学事件的时间段、候选物种、YAMNet 置信度、DoA;稳定视觉记录的时间、物种、置信度、框坐标 规则:高于声学门槛 + 在时间窗口内找到同物种、足够稳定的视觉记录 输出:audio_visual_corroborated / high_confidence_audio_needs_confirmation / low_confidence_audio_candidate / no_acoustic_event实时运行时使用:
python pet_observer/fuse_modalities.py\--events-json data/live/audio_visual/<时间戳>_6ch_events.json\--dbdata/pet_observer.db\--outputdata/state/current_monitoring.json\--audio-high-confidence0.40\--visual-min-confidence0.65\--window-s8其中 0.40、0.65 和 8 秒是当前 MVP 的工程门槛,不是由动物学实验标定出的科学阈值。应在未来拥有真实标注数据后重新估计。
6.2 融合实验截图解读
图 10 视觉声学双流测试展示了视觉状态记录器持续给出狗类别及约 0.9 的置信度,同时另一终端开始 20 秒声学窗口并运行 YAMNet。截图中可以看到大量候选窗口,这正说明“有许多候选”不能直接等于“有许多真实事件”。
双流测试实验的作用是说明两个流并非轮流手工执行:左侧持续更新视觉候选,右侧在相同阶段运行采集、YAMNet 和事件分段。
图11 双流融合监测实验测试成功,显示yolo检测结果与声学检测结果成功识别并保存到本地json文件。展示了一个较完整的融合结果:声学字段为Bark、置信度 0.5859、DoA 1.9°;视觉字段为dog、人工关联名“豆豆”、置信度 0.8589;最终状态为audio_visual_corroborated。该结果支持时间窗内同类证据链已接通;它仍需要人工确认,不能证明声音和画面一定来自同一只真实动物。
图12 正式规则测试成功,融合结果写入data/state/current_monitoring.json,并打印规则阈值与当前状态,说明结果不只停留在终端文字,而是成为网页和后续 LLM 都能读取的本地状态文件。
6.3 为什么融合比单模态更合理
单看画面,可能拍到宠物但没有声音;单看声音,可能是手机播放、电视、噪声或模型误报。双流融合并没有消灭误报,但至少加入了“同一时间段、同一类别”的约束。对资源有限的 MVP 来说,这是比“任一路触发就告警”更诚实的中间方案。
7. 双流信息输入本地 LLM:让模型生成建议,而不是替模型做事实判断
7.1 输入给 LLM 的是什么
本地 LLM 不直接读取原始视频,也不替代 YOLO/YAMNet。它读取的是已经结构化的摘要,例如:
宠物名、物种、距上次投喂时间、近 24 小时事件数、事件类型统计、 最长事件、近 7 天覆盖天数、照护记录是否足够、当前声视状态与限制说明。这一步的作用是把多份结构化记录转成通俗的、可读的简短提示;它不应被描述为“AI 诊断宠物”。
7.2 受约束 JSON 的验证
截图验证模型能返回受约束 JSON.png显示本地服务127.0.0.1:11434接收到/api/chat请求,请求设置:
{"model":"voice-mot-qwen3b:latest","stream":false,"think":false,"format":"json","options":{"temperature":0}}系统提示要求仅输出summary、suggestions等合法 JSON,且明确“不提供医疗诊断”。本次验证拿到了合法 JSON 响应。这很重要:网页和数据库依赖稳定结构,若模型任意输出散文或代码块,后续程序就难以可靠读取。
图13 本地LLM模型按 JSON 约束返回结果
一个可复用的最小请求示例:
curl-shttp://127.0.0.1:11434/api/chat\-H"Content-Type: application/json"\-d'{ "model":"voice-mot-qwen3b:latest", "stream":false, "think":false, "format":"json", "options":{"temperature":0}, "messages":[ {"role":"system","content":"只输出合法 JSON,且不提供医疗诊断。"}, {"role":"user","content":"事实:过去24小时存在声学候选。请给出谨慎的照护建议。"} ] }'7.3 历史记录与建议的分层
截图信息传入到Qwen3B并在本地写入json.png显示:先导入事件 JSON,再运行local_advisor.py,最后把建议保存到data/advice/<时间>_advice.json。模型输出中包含“数据质量/尚未接入摄像头确认”之类的限制语,说明提示词没有把候选硬包装成诊断。
图14 事件摘要传入 Jetson 本地 Qwen 并保存为本地建议 JSON 文件
截图历史数据不足.png显示当 7 天观测天数不足 3 天时,程序明确返回“无法形成历史基线或规律比较”,并把建议限制为核对投喂计划、观察饮水与环境。这正是本项目应有的保守行为。
图15 历史状态不足时返回信息不足提示而非强行给规律性结论或建议
模拟历史记录写入.png与写入五天虚拟历史.png的作用只是验证 SQLite 历史查询、跨天统计和网页显示逻辑。截图中数据明确含TEST_ONLY/“虚拟记录”字样。这些记录不能被当成真实宠物历史,更不能用它们证明建议有效。
图16 TEST_ONLY 照护记录写入 SQLite
图17 TEST_ONLY 跨五天历史数据用于查询逻辑验证
7.4 LLM 环节的失败记录与解决办法
失败:直接让模型自由回答,难以被网页稳定解析。
解决:请求format: "json"、设置低温度、在 system prompt 中约束字段,并在 Python 中解析/保存 JSON。失败时网页显示生成失败,而不是把不可解析内容混入历史库。
失败:历史太短时仍强行让模型给规律性结论。
解决:在进入模型前计算事件覆盖天数、投喂记录是否存在等数据质量字段;不足时提示“信息不足”,只允许输出保守建议。
8. 网页验证结果:普通用户只看网页,不再操作业务终端
网页由history_webapp.py提供,监听 5000 端口。普通用户打开:
http://192.168.55.1:5000/页面提供“开始实时监测”“停止监测”按钮。点击开始后,网页服务在后台启动现有的视觉、JPEG 渲染和声学融合进程;用户不必记忆采集、推流、YAMNet 或融合命令。维护人员仍需保留脚本和日志,便于故障恢复与复现实验。
8.1 当前网页的三层展示
- 当前状态层:融合状态、最新声学候选、视觉证据、距上次投喂时间与简短提示。
- 实时观察层:带 YOLO 框的最新画面、DoA 方位图、历史事件列表。
- 建议层:自动显示保守的简短建议;只有用户主动点击时才请求本地 LLM 生成详细建议。
这个交互策略符合当前能力边界:实时部分负责“持续监测与更新状态”;详细建议则由用户主动触发,避免把有限证据包装成持续的自动决策。
8.2 双阈值与 10 FPS 显示策略
本轮真实联调后,网页显示策略被明确为:
只有当 YOLO 置信度 > 0.50 且当前声学候选置信度 > 0.40 时, “最新 YOLO 检测画面”才替换为新画面。 YOLO 最大推理频率:10 FPS JPEG 渲染间隔:0.1 秒 网页轮询间隔:100 ms这里的“10 FPS”是当前脚本参数和进程核验结果,不等于已完成端到端性能基准测试。它只说明系统尝试以该上限运行;若要形成性能结论,还需要记录连续运行时长、P50/P95 延迟、GPU/内存/功耗和掉帧率。
8.3 真实网页联调截图
网页实时监测成功运行.png是本项目的最终网页证据。截图中可见:
- 顶部状态显示“本地实时监测”和“实时监测运行中”。
- 页面有开始/停止按钮,符合普通用户只看网页的目标。
- 实时画面内有狗类别检测框;左下是声源方位;右侧为可滚动历史。
- 历史卡片同时显示声学标签、置信度、方位、时间与视觉候选信息。
- 页面把限制写在文字中:YOLO 为类别检测、宠物名是人工关联、DoA 不提供可靠距离。
图 18 网页验证结论,它把前文的视觉、DoA、融合历史和建议汇聚为普通用户实际看到的界面。
网页实现的样式调试过程不作为本报告的失败记录。它是交互层迭代,不改变视觉、声学、融合和本地 LLM 的实验结论。
9. 实验环境与设备
图19 音视频画面与respeaker、USB摄像头位置关系说明
_图20 respeaker与固定摄像头放置与位置关系。respeaker面向画面正左方为0°采集方向,按照逆时针顺序依次为90°采集方向、180°采集方向、270°采集方向。后续采用桌面书立架固定摄像头。
图21 实验平台环境全景图。画面中间主屏为pet-observer监测网页,画面右手边屏幕使用视觉流水线将USB摄像头采集画面推流给管道gstreamer实时监测摄像头采集情况,根据采集画质与稳定性及时调整实验设备摆放位置与角度。
Ps:斯是陋室,惟吾德馨,工位玩jetson,学习入我心,谈笑有同门,往来无论文😭
10. 最终结果、不能得出的结论与下一步
10.1 已完成并有证据支持的结果
- USB 摄像头成功通过本地 RTSP 被 YOLO TensorRT 消费,能够持续产出猫/狗类别候选。
- 低质量或不稳定画面会导致稳定状态失败;稳定状态记录器能区分短暂检测与连续候选。
- reSpeaker 能采集六通道音频,并在四个方向测试中输出与人为摆放方向大致对应的 DoA 读数。
- YAMNet 在本地 TFLite 环境运行并产出候选事件;控制样本显示它会误报,因此不能单独作为宠物状态结论。
- 声学候选、视觉证据、时间窗口、SQLite 历史和当前状态 JSON 已经完成融合闭环。
- 本地 Qwen 已通过受约束 JSON 输出验证,可以读取结构化摘要并生成谨慎建议。
- 网页端可以启动实时监测并显示实时画面、方位、历史和建议;真实联调已确认数据来自
data/live/,而不是TEST_ONLY目录。
10.2 当前不能声称的内容
- 不能声称系统能翻译动物语言、识别情绪、疾病或真实需求。
- 不能声称 YOLO 检出了“豆豆本人”;它只检出了猫/狗类别,姓名来自人工关联。
- 不能声称 DoA 提供了可靠距离或精确坐标。
- 不能声称 YAMNet 的
Bark/Dog标签证明现场真实宠物在叫;手机播放和控制样本已经说明需要保守处理。 - 不能用虚拟历史记录证明长期规律或建议有效。
- 不能将当前 10 FPS 参数写成完整端到端性能结论;还没有系统化性能基准。
10.3 下一步可扩展方向
- 动物语言与情绪模型:引入经过动物声学数据训练、可解释且有评测集的模型,并保留不确定性。
- 行为学模型:升级摄像头和数据集,加入姿态、轨迹、进食/饮水/休息等动作,而非只做猫狗类别检测。
- 生理状态监测:接入可穿戴设备、体重、饮水、活动量、温湿度等传感器,构建比“单次声音”更可靠的状态证据。
- 定位能力:若需要位置而非方向,可研究多麦克风阵列、多摄像头、UWB 或毫米波雷达;这不是当前 DoA 的自然推论。
- 长期评测:建立真实动物、真实环境和人工标注的长期数据集,报告召回率、误报率、事件延迟、端到端 P50/P95、功耗和稳定性。
- 产品化:配置开机自启动、健康检查、数据清理策略、权限控制与隐私说明,避免依赖维护人员手工登录 Jetson。
结语
本地宠物行为观察器当前最符合逻辑的形态,不是“自动判断宠物真实需求并替人作决定”,而是:自动监测并更新当前候选状态,积累可追溯的本地历史;在用户主动提出需求时,再由本地 LLM 基于这些有限证据给出简短、保守且明确带限制的建议。
对于资源有限的学习项目,这条路线比夸大模型能力更有实际价值:它已经把采集、推理、融合、历史、网页交互和本地建议连接起来,同时把每个模块不能做什么写清楚,为后续真正接入动物行为、语言和生理模型留下了可实验扩展点。
小红书文章链接:Jetson + ReSpeaker:本地Ai宠物观察助手 宠物不会说… https://xhslink.cn/o/Ak4AvqMSyXJ
直达【小红书】探索笔记全文~
附:维护人员已验证的实时网页部署命令
普通用户不需要执行本节命令,只需打开网页并点击“开始实时监测”。以下内容用于维护、复现和故障恢复。
scp"D:\Project\Jetson Orin Nano\pet_observer_history_webapp.py""syc@192.168.55.1:/home/syc/projects/pet-observer/pet_observer/history_webapp.py.new"scp"D:\Project\Jetson Orin Nano\pet_observer_run_live_audio_fusion.sh""syc@192.168.55.1:/home/syc/projects/pet-observer/scripts/run_live_audio_fusion.sh.new"scp"D:\Project\Jetson Orin Nano\pet_observer_run_live_visual_monitor.sh""syc@192.168.55.1:/home/syc/projects/pet-observer/scripts/run_live_visual_monitor.sh.new"scp"D:\Project\Jetson Orin Nano\pet_observer_run_live_monitor.sh""syc@192.168.55.1:/home/syc/projects/pet-observer/scripts/run_live_monitor.sh.new"ssh syc@192.168.55.1"set -eu; cd /home/syc/projects/pet-observer; ./.pet-observer/bin/python -m py_compile pet_observer/history_webapp.py.new; bash -n scripts/run_live_audio_fusion.sh.new; bash -n scripts/run_live_visual_monitor.sh.new; bash -n scripts/run_live_monitor.sh.new; echo syntax-ok"ssh syc@192.168.55.1'set -eu; cd /home/syc/projects/pet-observer; curl -fsS -X POST http://127.0.0.1:5000/api/live/stop >/dev/null || true; sleep 2; stamp=$(date +%Y%m%d_%H%M%S); cp -p pet_observer/history_webapp.py "pet_observer/history_webapp.py.bak_$stamp"; mv pet_observer/history_webapp.py.new pet_observer/history_webapp.py; mv scripts/run_live_audio_fusion.sh.new scripts/run_live_audio_fusion.sh; mv scripts/run_live_visual_monitor.sh.new scripts/run_live_visual_monitor.sh; mv scripts/run_live_monitor.sh.new scripts/run_live_monitor.sh; chmod 755 scripts/run_live_audio_fusion.sh scripts/run_live_visual_monitor.sh scripts/run_live_monitor.sh; pids=$(fuser -n tcp 5000 2>/dev/null || true); if [ -n "$pids" ]; then kill $pids; fi; sleep 2; nohup ./.pet-observer/bin/python pet_observer/history_webapp.py --events-json data/tests/feeding_due_dog/20260826_151415_6ch_events.json --host 0.0.0.0 --port 5000 > logs/history_webapp_live.log 2>&1 &'ssh syc@192.168.55.1'curl -fsS -X POST http://127.0.0.1:5000/api/live/start'成功判据:/api/live-status返回running: true、视觉与声学新鲜状态为真;网页http://192.168.55.1:5000/能看到实时按钮、带框画面、声源方位和从data/live/写入的历史记录。