天天看點

來看看機智的前端童鞋怎麼防盜

很多開發的童鞋都是隻身混江湖、夜宿城中村,如果居住的地方安保欠缺,那麼出門在外難免擔心屋裡的财産安全。

事實上世面上有很多高大上的防盜裝置,但對于機智的前端童鞋來說,隻要有一台附帶攝像頭的電腦,就可以簡單地實作一個防盜監控系統~

純 JS 的“防盜”能力很大程度借助于 H5 canvas 的力量,且非常有意思。如果你對 canvas 還不熟悉,可以先點這裡閱讀我的系列教程。

來看看機智的前端童鞋怎麼防盜

step1. 調用攝像頭

我們需要先在浏覽器上通路和調用攝像頭,用來監控屋子裡的一舉一動。不同浏覽器中調用攝像頭的 API 都略有出入,在這裡我們以 chrome 做示例:

運作頁面後,浏覽器出于安全性考慮,會詢問是否允許目前頁面通路你的攝像頭裝置,點選“允許”後便能直接在 <video> 上看到攝像頭捕獲到的畫面了:

來看看機智的前端童鞋怎麼防盜
來看看機智的前端童鞋怎麼防盜

step2. 捕獲 video 幀畫面

光是開着攝像頭監視房間可沒有任何意義,浏覽器不會幫你對監控畫面進行分析。是以這裡我們得手動用腳本捕獲 video 上的幀畫面,用于在後續進行資料分析。

從這裡開始咱們就要借助 canvas 力量了。在 Canvas入門(五)一文我們介紹過 ctx.drawImage() 方法,通過它可以捕獲 video 幀畫面并渲染到畫布上。

我們需要建立一個畫布,然後這麼寫:

如上代碼所示,5秒後把視訊幀内容渲染到畫布上(下方右圖):

來看看機智的前端童鞋怎麼防盜
來看看機智的前端童鞋怎麼防盜

step3. 對捕獲的兩個幀畫面執行差異混合

在上面我們提到過,要有效地識别某個場景,需要對視訊畫面進行資料分析。

那麼要怎麼識别咱們的房子是否有人突然闖入了呢?答案很簡單 —— 定時地捕獲 video 畫面,然後對比前後兩幀内容是否存在較大變化。

我們先簡單地寫一個定時捕獲的方法,并将捕獲到的幀資料存起來:

如上代碼所示,畫布會每隔500毫秒捕獲并渲染一次 video 的幀内容(夭壽哇,做完這個動作不小心把餅幹灑了一地。。。\("▔□▔)/):

來看看機智的前端童鞋怎麼防盜

留意這裡我們使用了 canvas.toDataURL 方法來儲存幀畫面。

來看看機智的前端童鞋怎麼防盜

接着就是資料分析處理了,我們可以通過對比前後捕獲的幀畫面來判斷攝像頭是否監控到變化,那麼怎麼做呢?

熟悉設計的同學肯定常常使用一個圖層功能 —— 混合模式:

來看看機智的前端童鞋怎麼防盜

當有兩個圖層時,對頂層圖層設定“內插補點/Difference”的混合模式,可以一目了然地看到兩個圖層的差異:

來看看機智的前端童鞋怎麼防盜

“圖A”是我去年在公司樓下拍的照片,然後我把它稍微調亮了一點點,并在上面畫了一個 X 和 O 得到“圖B”。接着我把它們以“內插補點”模式混合在一起,得到了最右的這張圖。

在CSS3中,已經有 blend-mode 特性來支援這個有趣的混合模式,不過我們發現,在主流浏覽器上,canvas 的 globalCompositeOperation 接口也已經良好支援了圖像混合模式:

于是我們再建多一個畫布來展示前後兩幀差異:

效果如下(夭壽啊,做完這個動作我又把雪碧灑在鍵盤上了。。。(#--)/ ):

來看看機智的前端童鞋怎麼防盜

可以看到,目前後兩幀差異不大時,第三個畫布幾乎是黑乎乎的一片,隻有當攝像頭捕獲到動作了,第三個畫布才有明顯的高亮内容出現。

是以,我們隻需要對第三個畫布渲染後的圖像進行像素分析——判斷其高亮門檻值是否達到某個指定預期:

注意這裡我們使用了 count *= 3 來放大差異高亮像素的亮度值,不然得出的數值實在太小了。我們運作下頁面(圖檔較大加載會有點慢):

來看看機智的前端童鞋怎麼防盜

經過試(xia)驗(bai),個人覺得如果 calcDiff() 傳回的比值如果大于 0.20,那麼就可以定性為“一間空屋子,突然有人闖進來”的情況了。

來看看機智的前端童鞋怎麼防盜

step4. 上報異常圖檔

當上述的計算發現有狀況時,需要有某種途徑通知我們。有錢有精力的話可以部署個郵件伺服器,直接發郵件甚至短信通知到自己,but 本文走的吃吐少年路線,就不搞的那麼高端了。

那麼要如何簡單地實作異常圖檔的上報呢?我暫且想到的是 —— 直接把問題圖檔發送到某個站點中去。

這裡我們選擇部落格園的“日記”功能,它可以随意上傳相關内容。

糾正上述p.s.内容~ 後續發現 formData.append 支援第三個參數作為 filename 屬性,是以其實是可以轉 blob 上傳的。

我們在管理背景建立日記時,通過 Fiddler 抓包可以看到其請求參數非常簡單:

來看看機智的前端童鞋怎麼防盜

進而可以直接構造一個請求:

當然如果請求頁面跟部落格園域名不同,是無法發送 cookie 導緻請求跨域而失效,不過這個很好解決,直接修改 host 即可(怎麼修改就不介紹了,自行百度吧)。

我這邊改完 host,通過 http://i.cnblogs.com/h5monitor/final.html 的位址通路頁面,發現攝像頭竟然失效了~

通過谷歌的文檔可以得知,這是為了安全性考慮,非 HTTPS 的服務端請求都不能接入攝像頭。不過解決辦法也是有的,以 window 系統為例,打開 cmd 指令行面闆并定位到 chrome 安裝檔案夾下,然後執行:

此舉将以沙箱模式打開一個獨立的 chrome 程序,并對指定的站點去掉安全限制。注意咱們在新開的 chrome 中得重新登入部落格園。

這時候便能正常通路攝像頭了,我們對代碼做下處理,當差異檢測發現異常時,建立一份日記,最小間隔時間為5秒(不過後來發現沒必要,因為部落格園已經有做了時間限制,差不多10秒後才能釋出新的日記):

執行效果:

來看看機智的前端童鞋怎麼防盜

日記也是妥妥的出來了:

來看看機智的前端童鞋怎麼防盜

點開就能看到異常的那張圖檔了:

來看看機智的前端童鞋怎麼防盜

要留意的是,部落格園對日記釋出數量是有做每日額度限制來防刷的,達到限額的話會導緻當天的随筆和文章也無法釋出,是以得謹慎使用:

來看看機智的前端童鞋怎麼防盜
來看看機智的前端童鞋怎麼防盜

不過這種形式僅能上報異常圖檔,暫時無法讓我們及時收悉告警,有興趣的童鞋可以試着再寫個 chrome 插件,定時去拉取日記清單做判斷,如果有新增日記則觸發頁面 alert。

另外我們當然希望能直接對闖入者進行警告,這塊比較好辦 —— 搞個警示的音頻,在異常的時候觸發播放即可:

最後說一下,本文代碼均挂在我的github上,有興趣的童鞋可以自助下載下傳。共勉~

來看看機智的前端童鞋怎麼防盜