家裡沒人怎麼防火防盜?裝上這段自動看家程序
假期馬上就要到了,不少朋友即將出門旅遊或探親訪友。即使沒有強迫症的你,也許在鎖門離開的一瞬間,心裡也會泛起一絲淡淡的擔憂:離開家這麼長時間,如何才能確保家裡一切安好?
長時間家裡沒人,最主要的威脅來自兩個:一個是小偷,另一個是火災。防盜防火防閨蜜雖然是永恆的主題,但所有措施都是在出門以前做的,究竟效果如何?
最好是能有一個裝備,在主人不在家時實時監控家裡。一旦有問題,迅速通知主人,同時報警。
1. 監控系統
1.1 市面上的監控系統
針對這個問題,網上有不少現成的監控系統。原理大概是:通過探測器監測家裡的情況,一旦發現異常時,報警器通過網路將報警信息推送到主人的手機或電腦。
探測器的類型主要有兩種:
(1) 紅外探測器
世間萬物包括你、我還有小偷的身體,無時無刻都在向外發射著紅外線。
紅外線有個規律,就是溫度越高的物體,向外發射的紅外線強度越大。
因此,如果把紅外線探測器裝在門的上面或對面。當有小偷經過的時候,它就能探測到紅外線強度異常增大,據此判定有小偷闖入。
(2) 門磁探測器
門磁探測器由兩個部分組成,一部分安裝在門上,另一部分安裝在門框上。如果小偷打開了門,探測器的兩部分會被分離開,據此判定有小偷闖入。
這些報警器在一定程度上能監控小偷和火災,但它們問題在於:
(1) 紅外線感測器是利用人體溫度和環境溫度差值來判斷的,因此對溫度非常敏感。想想在炎熱的夏天,空氣的溫度幾乎都是30幾度,已經非常接近人體溫度,這對於紅外線感測器而言是一個挑戰。
(2) 無論是紅外線感測器還是門磁感測器,它們都安裝在固定的位置(門和窗戶對面或者旁邊)。對於有上進心的小偷而言,你覺得他們不會網購這個、拆開仔細研究清楚嗎?訓練有素的小偷能迅速找到這些監控設備,可能只需要花幾秒鐘就把警報聲消除了。
因此,我們需要想其他的辦法來解決這些問題。
1.2 我們的監控系統
好消息是:這一切都可以通過Matlab編程來實現!而且無需購買上面的感測器,只需要在天橋上的地攤買個攝像頭即可。
工作原理如下:程序通過調用攝像頭,對門和窗自動定時拍照。每拍一張照片,就和前一張照片對比,判斷門窗是否被打開、家裡是否有賊闖入或火情。一旦探測出異常情況,立刻給主人發送報警郵件,並播放警報,趕走小偷。
如果你買一個針孔攝像頭,藏到衣櫃邊上對著門窗,那麼即使是訓練有素的小偷進來了,也無法迅速消除攝像頭,警報聲會一直持續。而且,攝像頭對溫度並不敏感。
我們把程序起個名字叫doggy,doggy實現監控的流程圖如下:
如果想用Matlab編程實現上面這些功能,至少要解決下面幾個難點:(1) 如何調用攝像頭自動定時拍照?
(2) 如何通過對比兩張照片,判斷家裡是否有賊闖入?
(3) 判斷出有賊之後,如何給主人發送報警郵件?
(4) 如何自動播放警報?
(5) 如果小偷對報警聲音根本不care,是否有其它辦法?
下面一一解釋如何實現,沒時間看原理的同學,可以直接跳到第6部分的使用方法。
2. 定時自動拍照
定時自動拍照由一個主程序doggy.m和一個拍照函數takephotos.m組成。
其中主程序doggy.m的代碼為:
--------------------------------------------------------------------------
%清除所有變數
clear
clc
%建立圖片存儲文件夾
if exist(doggyphoto,dir)~= 7
mkdir([cd,/doggyphoto])
end
directory=[cd,/doggyphoto/];
%設置一個監控界面
hf = figure(Units, Normalized, Menubar, None,NumberTitle, off, Name, 監控系統);
ha = axes(Parent, hf, Units, Normalized, Position, [0.125 0.2 0.75 0.75]);
axis off
axis equal
%設置兩個按鈕
hb1 = uicontrol(Parent, hf, Units, Normalized,Position, [0.3 0.05 0.15 0.1], String, 測試攝像頭, Callback, [imaqhwinfo;...
obj = videoinput(winvideo);...
set(obj, FramesPerTrigger, 1);...
set(obj, TriggerRepeat, Inf);...
objRes = get(obj, VideoResolution);...
nBands = get(obj, NumberOfBands);...
hImage = image(zeros(objRes(2), objRes(1), nBands));...
preview(obj, hImage);]);
hb2 = uicontrol(Parent, hf, Units, Normalized,Position, [0.6 0.05 0.15 0.1], String, 開始監控, Callback, takephotos(directory,obj););
--------------------------------------------------------------------------
這段程序分為四個部分:
第一部分:清除所有變數,避免其它變數影響監控系統的運行;
第二部分:新建一個文件夾doggyphoto用於待會拍照存儲照片,如果這個文件夾已存在就不用新建了。
第三部分:設置一個監控界面;
第四部分:設置兩個按鈕,其中一個是按鈕是用來測試攝像頭的,另一個按鈕則是開始監控的。
在第四部分需要調用一個函數takephotos,源程序是:
--------------------------------------------------------------------------
function takephotos(directory,obj)
escapetime=30; %從點擊開始監控到鎖門後離開的時間內,攝像頭不監控,單位:秒
daynum=3; %一共打算出去幾天?單位:天
timestep=2; %每隔多少秒拍一次照片?單位:秒
photonum=round(daynum*24*3600/timestep);
i=0;
whilephotonum>0
while escapetime>0
disp([The monitoring system will start to workin num2str(escapetime) seconds, please leave quickly.]);
escapetime=escapetime-1;
pause(1);
ifescapetime==0
disp([The monitoring system will start to worknow.]);
end
end
photonum=photonum-1;
i=i+1;
filename=[num2str(i)];
frame = getsnapshot(obj);%抓圖
imwrite(frame,[directory,filename,.jpg]);%存圖
disp([Take the num2str(i) photos.]);
if(i>1 &&comparephotos(i,i-1)>0)
sentemail();
playalarm();
disp([Something wrong in the room!]);
end
pause(timestep);
end
clear i;%清除局部變數
delete(obj);%關閉攝像頭
--------------------------------------------------------------------------
在這個函數中要設置幾個參數:
(1) 從主人點擊「開始監控」的按鈕,到鎖門後離開這段時間內,攝像頭應該不監控。否則,監控程序把主人也當做小偷了……這段時間可長可短,取決於每個人動作快慢。這裡doggy默認給了主人30秒鐘,需要更長時間可手動修改。
escapetime=30; %從點擊開始監控到鎖門後離開的時間內,攝像頭不監控,單位:秒
(2) 主人打算一共出去多少天?doggy需要在這段時間內工作,默認是3天,同樣的可手動修改這個參數。
daynum=3; %一共打算出去幾天?單位:天
(3) 每隔多少秒拍照一次?如果拍的太頻繁,照片佔用的硬碟空間可能非常大,硬碟會被爆掉的。而如果兩次拍照之間間隔時間太久,小偷進來把門又關好了,兩次照片一摸一樣,監控程序無法判斷異常情況。默認是2秒,可手動修改。
timestep=2; %每隔多少秒拍一次照片?單位:秒
通過Matlab內置函數getsnapshot函數拍照,然後通過內置函數imwrite函數存儲,之後調用comparephotos函數判斷是否有人闖入或是否有火災,如果判斷有異常情況,通過sentemail函數給主人發郵件,並且通過playalarm播放警報。
3. 判斷是否有人闖入或火災
這項功能是通過comparephotos.m完成的,源代碼如下:
--------------------------------------------------------------------------
function theif=comparephotos(i,j)
name1=[num2str(i) .jpg];
name2=[num2str(j) .jpg];
img1=imread(name1,jpg);
img2=imread(name2,jpg);
diffvalue=mean(mean(mean(abs(double(img1)-double(img2)))))%計算兩張圖的差值
Threshold=5; %設置報警的閾值
ifdiffvalue>Threshold %如果兩張圖片差異過大,認為有賊闖入或有火警
theif=1;
else
theif=0;
end
--------------------------------------------------------------------------
這個函數首先調用內置函數imread讀取兩張圖片,然後繼續對比。
在Matlab中,照片是以數組的形式存儲的。因此,通過對比兩個數組的差值就能判斷兩張圖片的區別。
正常情況下,攝像頭拍攝的兩張相近的圖片應該是差別不大;如果差值過大,則說明有異常情況。
測試結果如下:
(1) 正常情況下
第2秒的圖片:
第4秒的圖片:
由於沒有人闖入,也沒有火情,兩張圖片應該是一模一樣的。
兩個數組相減之後,差值為0。如果把這個差值的數組再顯示,應該一張全黑的照片:
(2) 如果第二張照片中放了一個異物(記事本,請忽略本人的玉手^_^)
第2秒的照片:
第4秒的照片:兩個數組相減之後,沒有異物的地方差值為0,有異物的地方差值不為0,所以差值的數組再顯示就是這樣的:
看,沒有異物的地方是全黑的,有異物的地方就被檢測出來了。
(3)由於一天內不同時刻,室外的光線並不一樣,所以前後兩張照片並不是完全一模一樣,即相減後的數組再顯示不是全黑的,而是接近於全黑的有一定噪音的圖片:
所以這裡需要有個參數,來調控報警的閾值。
Threshold=5; %設置報警的閾值
這個參數反映了前後兩張圖片的差異程度。
如果Threshold設置為0,那麼只要兩張圖片有一絲不同,doggy就會馬上報警,真正可以實現連一隻蚊子、一隻跳蚤都不讓飛進來。
但實際上,我們並不需要doggy這麼敏感。否則,由於室外的光線的不同而導致前後兩張照片並不是完全一模一樣,也會引起誤報警。
這個參數和不同房子的窗戶大小、位置相關。一般而言,通過測試後發現設置Threshold為5,可以很好的過濾掉誤報警。
4. 發送郵件
我們不希望外出時,家裡有任何情況發生,但一旦有情況,讓doggy給我們立刻發一封郵件,源代碼文件名叫sentemail.m,代碼如下:
--------------------------------------------------------------------------
function sentemail()
mail = xxxxxxxxx@qq.com; %可以使用qq郵箱
password = xxxxxx; %輸入郵箱的密碼
setpref(Internet,E_mail,mail);
setpref(Internet,SMTP_Server,smtp.qq.com); %此處郵箱伺服器與上面一致
setpref(Internet,SMTP_Username,mail);
setpref(Internet,SMTP_Password,password);
props = java.lang.System.getProperties;
props.setProperty(mail.smtp.auth,true);
props.setProperty(mail.smtp.socketFactory.class, javax.net.ssl.SSLSocketFactory);
props.setProperty(mail.smtp.socketFactory.port,465);
subject=Alarm; %郵件標題
content=Dear Master, there is something wrong in our house!; %郵件內容
sendmail(xxxxxxxxx@qq.com,subject,content); %需要發送到的郵箱地址
--------------------------------------------------------------------------
在這一塊需要注意的是:
(1) 密碼要使用明碼,很坑爹是不是?別忘了上個月我們說過可以用pcode給程序加密。
(2) Matlab可以在郵件裡面發送附件。然而,它發送郵件是通過Java介面,速度比較慢,所以不推薦添加太大的附件,以免發送失敗。這裡為了保險起見,乾脆不發附件好了。
(3) Matlab只能發送不需要authentication的郵箱地址,如果使用出現錯誤,請把POP3後者SMTP服務打開。以qq郵箱為例,需要在設置裡面打開如下許可權:
5. 自動播放警報
通知了主人之後,接下來就是該發出聲音趕走小偷了,函數文件名是playalarm.m,源代碼如下:
--------------------------------------------------------------------------
function playalarm()
[y,fs]=wavread(Alarm.wav); %保證wav文件在當前工作目錄
sound(y, fs);
--------------------------------------------------------------------------
(1) 警報聲
最常用的聲音是警車的聲音。
報警器的聲音會讓一些有賊心沒賊膽的人退散,而且能夠引起周邊鄰居注意。
(2) 恐怖片
對於等級比較高的小偷而言,這種報警聲音或許早已經被免疫了。
這時不如換成恐怖片的聲音,比警車的聲音更有效果。
友情提醒:此恐怖片聲音非常驚悚,切勿在深夜一個人點開。
[這裡貼不了音頻文件,想聽的同學去我的微信公眾號吧
http://mp.weixin.qq.com/s?__biz=MzI1NTI4OTIxMA==&mid=2247484111&idx=1&sn=72ef7934b6c4da9c56f426865f0bff96#rd
]
1:24 驚悚聲音,慎入 來自科學計算編點程
對於盜賊而言,其實是需要很強的心理素質的。
尤其是進屋的前幾秒種,是最緊張和防禦狀態最充分的時候。
他會仔細檢查看有沒有情況,一旦發現這個房間裡面沒有威脅,他會稍微放鬆一點。
所以這段驚悚的聲音,最前面7秒沒有聲音,是為了給盜賊充分的時間放鬆。
等他開始放鬆的時候,再突然聽到驚悚的聲音才能達到最好的效果。
(3) 聲音飄忽的感覺
光播放恐怖片的音樂,也許對於膽大的盜賊來說根本無所謂,甚至只能當做他們飯後的茶資。
那我們就加點立體效果,即聲音飄忽不定的感覺。
原理是這樣的:人可以判斷聲源的位置,是因為聲源到兩隻耳朵的距離一般不同,聲音傳到兩隻耳朵的時刻、強弱及其他特徵也就不同。
那麼,如果我們通過左聲道和右聲道放出來的恐怖片聲音強度或時刻不一樣,盜賊就會感覺恐怖聲的發出位置是在飄忽不定的,更具有驚悚效果。
下面,我們改變兩個聲道聲音的強度:
--------------------------------------------------------------------------
function playalarm2()
[y,fs]=wavread(kb.wav);
left=y(:,1); % 左聲道
right=y(:,2); % 右聲道
x=1:length(left);
y(:,1)=left.*sin(2*pi().*x/length(left)*5);
y(:,2)=left.*(1-sin(2*pi().*x/length(left)*5));
wavwrite(y,fs,kb2);
--------------------------------------------------------------------------
比起上面的那個,能明顯感覺到這次聲源在左右移動。(每篇推送只能插入一段音頻,所以這段飄忽的音頻無法插入,需要試聽的給後台留言)
然而,這個聲音仍然只在盜賊的正前方,能不能有辦法讓盜賊認為聲源在左右上下移動,甚至跳到他背後呢?
答案當然是可以的了啦!當兩個波形具有180°相位差且分別位於兩個聲道時,只要兩個聲道不被融合在一起,我們可以明顯感覺到聲源跑到後面去了。
不過限於時間和篇幅,這裡無法繼續展開討論,下次找機會專門做個Matlab處理立體聲的專題吧。
(4) 增加次聲波
只有恐怖片聲音的刺激,也許還是不能完全克制住盜賊的貪慾。
能否讓聽到立體聲恐怖片的盜賊,除了在心理上不舒服之外,身體也產生不舒服的感覺呢?
接下來,隆重推出另一個大殺器——次聲波。
什麼是次聲波?人耳朵能聽到的聲音的頻率是20到2萬赫茲。頻率小於20赫茲的聲波叫做次聲波。
某些頻率的次聲波由於和人體器官的振動頻率相近甚至相同,容易和人體器官產生共振,對人體有很強的傷害性,危險時可致人死亡。
當然,通過matlab程序生成的次聲波,經過音響播放出來其實功率很小,並不足以傷害到盜賊。但是至少會讓盜賊感覺到有點不舒服。
更重要的是,這個聲音盜賊是聽不到的。
也就是說,站在盜賊的角度,他無法聽到聲音,只能感受到難受。再配上恐怖片的驚悚的立體音效,效果達到了。
生成次聲波的源代碼如下:
--------------------------------------------------------------------------
function createisound()
f=10;%頻率10赫茲
w=2*pi()*f;
t=[0:0.0001:30];%步進0.0001秒
y=sin(w*t);
--------------------------------------------------------------------------
這樣,就得到了一個頻率為10赫茲,時間為30秒的次聲波。
(5) 高分貝DJ
如果盜賊油鹽不進,對警車聲和恐怖片聲音都免疫。
我們還有最後一招,但也是最沒有辦法的辦法:把音量調到最大,播放下面高分貝DJ,把鄰居們都吵醒吧。
他們會怒氣沖沖找你算賬,然後在無意中把小偷逼走。
6. 使用方法
好了,原理以及講清楚,下面講如何使用這個監控系統。
6.1 搭建監控系統
(1) 材料準備
材料只需要:
一台裝有Matlab的電腦
一個攝像頭
一個音響(最好有低音炮,效果更佳)
把電腦、攝像頭和音響都藏在隱蔽的位置。音響最好對稱的放在房間的兩個角落。
(2) 參數設置
將所有代碼拷到電腦上,一共有六個文件:
doggy.m,
takephotos.m,
comparephotos.m,
sentemail.m,
playalarm.m,
playalarm2.m,
每個文件對應的功能見下圖:
通過doggy.m調用takephotos.m進行拍照,然後調用comparephotos.m判斷是否有人闖入或是否有火災,如果判斷有異常情況,通過sentemail.m函數給主人發郵件,並且通過playalarm.m和playalarm2.m播放警報。
需要設置的參數有:
(1) takephotos.m中escapetime參數:從主人點擊「開始監控」的按鈕,到鎖門後離開這段時間內,攝像頭應該不監控。
(2) takephotos.m中daynum參數:主人打算一共出去多少天?
(3) takephotos.m中timestep=2參數:每隔多少秒拍照一次?
(4) comparephotos.m中Threshold=5:設置報警的閾值。
(3) 開始監控
參數設置好以後,在主程序里運行doggy回車,彈出如下界面:
點左下方的「測試攝像頭」,看攝像頭是否正常工作。
然後點右下方的「開始監控」之後,程序開始倒計時:
主人在這個時間內,離開鎖門準備去外面度假咯。
接下來,是程序每隔幾秒鐘給門和窗照相,
然後對比前後兩張照片判定是否有人闖入。
6.2 盜賊的體驗
我們希望報警程序永遠不要被激活。但是萬一被激活,它是這樣防禦盜賊的:
首先,盜賊進了門,開始判斷家裡是否有報警器或者其它威脅什麼的。
等待了幾秒鐘,發現沒什麼不對勁,開始準備搜東西。
正在他準備開始搜的時候,天上傳來一道驚悚的聲音。
冷靜了幾秒,他馬上識別這是房子的主人在播放恐怖片呢,心裡想:小樣,給我玩這套。
但接下來,他驚喜的發現這個驚悚的聲音開始飄忽移動,慢慢移動到他背後。
這時候,他已經萌生了退意。
再接下來,次聲波開始發射,他感覺到除了心裡不舒服之外,身體也有些不太舒服。
算了吧,放棄吧。大部分盜賊決定放棄了。
然而,還有少部分盜賊是盜墓出身,根本不care。
好吧,這個時候開始播放超大音量DJ。
鄰居們,請你們快怒氣沖衝到我房子里吧!趕走盜賊就靠你們了。
恩,請提醒我現在不是在寫惡搞的劇本,而是在認真嚴肅的寫推送。
7. 寫在最後
7.1 改進方案
其實這個程序還有很多地方可以改進,比如:
(1) 自動定時拍攝的照片的解析度其實可以調整的更高一些,這樣可以更準確的進行判斷是否有人闖入。
(2) 報警或者恐怖片的立體聲還可以做的更逼真,當然這要考慮到左右兩個聲道聲音的延遲以及相位差。
(3) 可以調用多個攝像頭,從多角度對門進行防禦。
7.2 防盜意識
相比於在家安裝監控系統,更重要的是平時要加強安全意識。
比如在外面吃飯時財別外漏,在公共場合聊天時別說自己家有多少家財。
不怕賊偷,就怕賊惦記。監控系統永遠只是防禦的最後一環。
就像足球比賽一樣,監控系統只是守門員而已。足球最好控制在前場隊員手裡,才能遠離失敗。如果老是讓自己的足球守門員抵禦對方的前鋒,不停的撲球,遲早是會被進球。
(END)
如果對科學計算(尤其是Matlab使用中)的經驗、教訓或者好玩的東西感興趣,可以關注我的公眾號「科學計算編點程(kexuebc)」。
定期推送科學計算和工程計算編程相關的最新技術動態、基礎知識、實用技巧歸納和應用案例。
作者保留版權,若要轉載請聯繫作者授權。
推薦閱讀:
※數學研究與時間長短有關係嗎?
※學生的paper導師掛一作兼通訊是什麼心態?
※作為一名博士一年級的新生,有一個牛逼的導師和一群牛逼的師兄師姐是怎樣的體驗?
※為什麼研究重點都集中在腫瘤呢?
※金屬材料方面發一區論文是什麼水平?有多難發?