为了防止狗上沙发,写了一个浏览器实时识别目标功能 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
xiaowoli
V2EX    分享创造

为了防止狗上沙发,写了一个浏览器实时识别目标功能

  •  11
     
  • /div>   xiaowoli 2024-03-15 16:32:36 +08:00 7679 次点击
    这是一个创建于 594 天前的主题,其中的信息可能已经有所发展或是发生改变。

    网页调用摄像头识别物体后做成行为

    背景

    家里有一条狗,很喜欢乘人不备睡沙发,恰好最近刚搬家 + 狗迎来了掉毛期 不想让沙发上很多毛。所以希望能识别到狗,然后播放“gun 下去”的音频。

    需求分析

    • 需要一个摄像头
      • 利用 chrome 浏览器可以调用手机摄像头,获取权限,然后利用 video 将摄像头的内容绘制到 video 上。
    • 通过摄像头实时识别画面中的狗
      • 利用 tensorflow 和预训练的 COCO-SSD MobileNet V2 模型进行对象检测。
      • 将摄像头的视频流转化成视频帧图像传给模型进行识别
    • 录制一个音频
      • 识别到目标(狗)后播放音频
    • 需要部署在一个设备上
      • 找一个不用的旧手机,Android 系统
      • 安装 termux 来实现开启本地 http 服务

    技术要点

    1. 利用浏览器 API 调用手机摄像头,将视频流推给 video

      const stream = await navigator.mediaDevices.getUserMedia({ // video: { facingMode: "environment" }, // 摄像头后置 video: { facingMode: "user" }, }); const videoElement = document.getElementById("camera-stream"); videoElement.srcObject = stream; 
    2. 加载模型,实现识别

      let dogDetector; async function loadDogDetector() { // 加载预训练的 SSD MobileNet V2 模型 const model = await cocoSsd.load(); dogDetector = model; // 将加载好的模型赋值给 dogDetector 变量 } 
    3. 监听 video 的播放,将视频流转换成图像传入模型检测

      videoElement.addEventListener("play", async () => { requestAnimationFrame(processVideoFrame); }); async function processVideoFrame() { if (!videoElement.paused && !videoElement.ended) { canvas.width = videoElement.videoWidth; canvas.height = videoElement.videoHeight; ctx.drawImage(videoElement, 0, 0, canvas.width, canvas.height); // 获取当前帧图像数据 const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); // 对帧执行预测 let predictiOnClasses= ""; const predictiOns= await dogDetector.detect(imageData); // 处理预测结果,比如检查是否有狗被检测到 for (const prediction of predictions) { predictionClasses += `${prediction.class}\n`; // 组装识别的物体名称 if (prediction.class === "dog") { // 播放声音 playDogBarkSound(); } } nameContainer.innerText = predictionClasses.trim(); // 移除末尾的换行符 requestAnimationFrame(processVideoFrame); } } 
    4. 播放音频

      async function playDogBarkSound() { if (playing) return; playing = true; const audio = new Audio(dogBarkSound); audio.addEventListener("ended", () => { playing = false; }); audio.volume = 0.5; // 调整音量大小 await audio.play(); } 
    5. 手机开启本地 http 服务

      • 安装 termux
      • 安装 python3
      • 运行 python3 -m http.server 8000
    6. 将项目上传到 termux 的目录

      • 直接用 termux 打开文件
      • 访问 http://localhost:8000

    项目代码(改为 html 文件后)

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" cOntent="width=device-width, initial-scale=1.0" /> <title>Mobile Dog Detector</title> <script src="https://cdn.jsdelivr.net/npm/@tensorflow/[email protected]/dist/tf.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/[email protected]/dist/coco-ssd.min.js"></script> <style> #camera-stream { width: 200px; height: auto; } #name { height: 200px; overflow-y: auto; font-family: Arial, sans-serif; } </style> </head> <body> <video id="camera-stream" autoplay playsinline></video> <div id="name" style="height: 200px"></div> <script> let playing = false; let dogDetector; async function loadDogDetector() { // 加载预训练的 SSD MobileNet V2 模型 const model = await cocoSsd.load(); dogDetector = model; // 将加载好的模型赋值给 dogDetector 变量 console.log("dogDetector", dogDetector); startCamera(); } // 调用函数加载模型 loadDogDetector(); async function startCamera() { const stream = await navigator.mediaDevices.getUserMedia({ // video: { facingMode: "environment" }, // 摄像头后置 video: { facingMode: "user" }, }); const nameCOntainer= document.getElementById("name"); const videoElement = document.getElementById("camera-stream"); videoElement.srcObject = stream; const canvas = document.createElement("canvas"); const ctx = canvas.getContext("2d"); videoElement.addEventListener("play", async () => { requestAnimationFrame(processVideoFrame); }); async function processVideoFrame() { if (!videoElement.paused && !videoElement.ended) { canvas.width = videoElement.videoWidth; canvas.height = videoElement.videoHeight; ctx.drawImage(videoElement, 0, 0, canvas.width, canvas.height); const imageData = ctx.getImageData( 0, 0, canvas.width, canvas.height ); let predictiOnClasses= ""; const predictiOns= await dogDetector.detect(imageData); for (const prediction of predictions) { predictionClasses += `${prediction.class}\n`; if (prediction.class === "dog") { // 修改为检测到狗时播放声音 playDogBarkSound(); } } nameContainer.innerText = predictionClasses.trim(); requestAnimationFrame(processVideoFrame); } } async function playDogBarkSound() { if (playing) return; playing = true; const audio = new Audio("./getout.mp3"); audio.addEventListener("ended", () => { playing = false; }); audio.volume = 0.5; // 调整音量大小 await audio.play(); } } </script> </body> </html> 

    实现效果

    效果很好,用旧手机开启摄像头后,检测到狗就播放声音了。

    但是,家里夫人直接做了一个围栏晚上给狗圈起来了

    实现总结

    该方案通过以下步骤实现了一个基于网页的实时物体检测系统,专门用于识别画面中的狗并播放特定音频以驱赶它离开沙发。具体实现过程包括以下几个核心部分:

    • 调用摄像头:

    使用浏览器提供的 navigator.mediaDevices.getUserMedia API 获取用户授权后调用手机摄像头,并将视频流设置给 video 元素展示。

    • 加载物体检测模型:

    使用 TensorFlow.js 和预训练的 COCO-SSD MobileNet V2 模型进行对象检测,加载模型后赋值给 dogDetector 变量。 处理视频流与图像识别:

    监听 video 元素的播放事件,通过 requestAnimationFrame 循环逐帧处理视频。 将当前视频帧绘制到 canvas 上,然后从 canvas 中提取图像数据传入模型进行预测。 在模型返回的预测结果中,如果检测到“dog”,则触发播放音频函数。

    • 播放音频反馈:

    定义一个异步函数 playDogBarkSound 来播放指定的音频文件,确保音频只在前一次播放结束后才开始新的播放。

    • 部署环境准备:

    使用旧 Android 手机安装 Termux ,创建本地 HTTP 服务器运行项目代码。 上传项目文件至 Termux 目录下并通过访问 localhost:8000 启动应用。

    通过以上技术整合,最终实现了在旧手机上部署一个能够实时检测画面中狗的网页应用,并在检测到狗时播放指定音频。

    41 条回复    2024-03-19 13:19:38 +08:00
    xieqiqiang00
        1
    xieqiqiang00  
       2024-03-15 16:36:34 +08:00 via Android
    这个需求用 techable machine 上传几张图也可以实现
    blackcellcode
        2
    blackcellcode  
       2024-03-15 16:40:17 +08:00
    结果笑了哈哈
    hinataharuki
        3
    hinataharuki  
       2024-03-15 16:41:37 +08:00   10
    女:什么花里胡哨的
    woody3rd
        4
    woody3rd  
       2024-03-15 16:42:04 +08:00
    真会玩啊
    cat
        5
    cat  
       2024-03-15 16:42:23 +08:00
    [但是,家里夫人直接做了一个围栏晚上给狗圈起来了]
    Seven711
        6
    Seven711  
       2024-03-15 16:45:10 +08:00
    哈哈哈哈,整的花里胡哨的
    netnetuser
        7
    netnetuser  
       2024-03-15 16:48:17 +08:00
    想法挺好的。实际上,有些狗狗很聪明,就 OP 狗狗生活的环境,狗狗可以越狱的方式就有 2 个:
    1.跳上窗边走出来;
    2.直接跳过围栏。

    我在 Youtube 上看狗狗视频,嚓...他们有着强烈的外逃行动力,围栏难不倒他们的。
    zmQAQ
        8
    zmQAQ  
       2024-03-15 16:53:08 +08:00
    nb
    zoezz
        9
    zoezz  
       2024-03-15 16:54:30 +08:00
    够硬核 v 站需要这种帖子
    wesleywaters
        10
    wesleywaters  
       2024-03-15 16:56:13 +08:00
    结局很欢乐
    Felldeadbird
        11
    Felldeadbird  
       2024-03-15 17:28:03 +08:00
    硬核终究败给现实。
    rewluck
        12
    rewluck  
       2024-03-15 17:33:18 +08:00
    狗子挺好看,op 够硬核,夫人很现实
    ltmst
        13
    ltmst  
       2024-03-15 17:39:55 +08:00   1
    狗狗对于这围栏的态度
    就相当于
    你老婆对于你开发这套东西的态度
    不能说一点用没有吧
    gamexg
        14
    gamexg  
       2024-03-15 17:49:37 +08:00
    另外狗对于这种声音可能并不在意,至少我家的就是这样.
    人在家不敢上沙发,但是家里没人有时候就会上沙发.
    通过监控/扫地机器人喊话毫无效果,它根本不会理.
    但是你回家的话,它听到声音就会自己下来.
    meetqyx
        15
    meetqyx  
       2024-03-15 17:56:30 +08:00
    好好好,真会玩。
    luzemin
        16
    luzemin  
       2024-03-15 18:15:25 +08:00
    赛博手工耿
    qsgy123456
        17
    qsgy123456  
       2024-03-15 19:54:44 +08:00
    想在衣领别个摄像头。识别到熟人的时候提示你相关资料。 感觉销售可以用
    zhilincom
        18
    zhilincom  
       2024-03-15 20:46:54 +08:00
    围栏??这直接可以跳过去的吧。
    miaomiao888
        19
    miaomiao888  
       2024-03-15 20:54:45 +08:00
    别把狗子吓坏了,怎么主子的声音像鬼魂一样时刻环绕在耳边
    NeroKamin
        20
    NeroKamin  
       2024-03-15 21:07:28 +08:00
    哈哈哈哈好有意思
    aitianci
        21
    aitianci  
       2024-03-15 21:25:58 +08:00
    可以给狗加个放电脖圈,接近沙发一米内就电一下
    wonderfulcxm
        22
    wonderfulcxm  
       2024-03-15 21:45:44 +08:00 via iPhone
    结局略显意外
    Atma
        23
    Atma  
       2024-03-15 22:20:11 +08:00 via Android
    你是真的,哈哈哈
    dyv9
        24
    dyv9  
       2024-03-15 22:52:46 +08:00 via Android
    活在你家,做狗也不开心,既然都是不开心下辈子还是做人吧,至少想结婚或想嫖总有一个可以,做狗就没机会。
    keepRun
        25
    keepRun  
       2024-03-16 02:57:33 +08:00 via Android
    angry41
        26
    angry41  
       2024-03-16 11:14:08 +08:00
    @qsgy123456 #17 我记得房产销售大厅的摄像头都带这个功能,还上过 315 ,大数据会识别你之前在哪家看过哪家房子,心里价位大概多少
    hanguofu
        27
    hanguofu  
       2024-03-16 11:54:34 +08:00
    厉害~~ 请问 ”使用 TensorFlow.js 和预训练的 COCO-SSD MobileNet V2 模型进行对象检测“ 这个拿来就可以用了吗 ?具体怎样训练才能识别 狗 啊?
    ohayoo
        28
    ohayoo  
       2024-03-16 14:01:23 +08:00
    程序员的欢乐世界
    lxcForPHP
        29
    lxcForPHP  
       2024-03-16 16:13:39 +08:00
    @qsgy123456 今年老回家过年,遇到很多能喊出我名字来(小时候的邻居和家族的人),但是我却没有多少印象,愣在那里也不知道喊人家啥,场面尴尬的很。所以就萌生了一个想法,能不能自己维护一个资料库,然后能通过啥智能设备来自动查询相关资料
    keepfun
        30
    keepfun  
       2024-03-18 09:39:37 +08:00
    高阶程序员 我等只能望洋兴叹
    uyoungco
        31
    uyoungco  
       2024-03-18 11:34:37 +08:00   1
    @hanguofu 别人训练好的,你输入图形他会给你图像中的信息,比如 人、狗之类的
    huangz003
        32
    huangz003  
       2024-03-18 14:57:46 +08:00
    圈起来,小狗怎么上厕所
    xiaowoli
        33
    xiaowoli  
    OP
       2024-03-18 16:09:46 +08:00
    @huangz003 只有晚上关起来 我家狗一天就出去尿一次 够了
    xiaowoli
        34
    xiaowoli  
    OP
       2024-03-18 16:10:53 +08:00
    @netnetuser 老哥,最新消息,我家狗看了你的回复已经学会越狱了。。。
    xiaowoli
        35
    xiaowoli  
    OP
       2024-03-18 16:12:06 +08:00
    @hanguofu 直接用我那个代码就已经可以识别了 现成的模型库
    netnetuser
        36
    netnetuser  
       2024-03-18 16:32:05 +08:00
    @xiaowoli 我觉得可以记录下狗狗越狱整个过程(偷 拍),然后让大家一起欢乐。
    LavaC
        37
    LavaC  
       2024-03-19 09:26:40 +08:00
    突然想起那个买了体重秤放床垫下的玩法
    jiandandkl
        38
    jiandandkl  
       2024-03-19 10:19:03 +08:00
    太好玩了,想知道狗听到播放的 gun 下去会听话的 gun 下去吗?
    janda
        39
    janda  
       2024-03-19 10:33:27 +08:00
    有意思
    DavidA
        40
    DavidA  
       2024-03-19 10:57:54 +08:00
    幽默
    lefer
        41
    lefer  
       2024-03-19 13:19:38 +08:00
    @xieqiqiang00 #1 太厉害了。竟然是谷歌的项目。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     956 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 45ms UTC 22:21 PVG 06:21 LAX 15:21 JFK 18:21
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86