第6章 樹莓派攝像頭操作

6.1樹莓派基本操作

目前提供了三個應用程式,分別為:raspistill、raspivid、raspistillyuv。其中 raspistill 和 raspistillyuv 非常相似,並且都是用於捕捉影象,而 raspivid 用於捕捉視訊。
所有應用程式均基於命令列方式執行,通過 OpenMAX 的 mmal API 進行編寫。OpenMAX 的 mmal API 提供了更易使用的系統元件。注意,mmal 是一個由 Broadcom 為 Videocore 4 系統定製的 API。
應用程式使用了四個 OpenMAX(mmal)元件:camera(攝像)、preview(預覽)、encoder(編碼)、null_sink。所有應用程式均使用了攝像元件,raspistill 使用了影象編碼元件,raspivid 使用了視訊編碼元件,raspistillyuv 沒有使用編碼元件,而是直接將 YUV 或 RGB 從攝像元件輸出到檔案。
預覽顯示為可選引數,但是可以用於全屏或輸出到指定的顯示器顯示區域進行顯示。如果預覽被禁用,那麼 null_silk 元件將會對預覽幀進行“吸收”。這是由於儘管不需要攝像頭生成供顯示所用的的預覽幀,但是仍需要使用它們進行曝光計算和白平衡設定的緣故。
此外,還可以省略檔名引數,這樣既可以直接預覽顯示而不寫入檔案,或者直接輸出到標準輸出裝置上。命令列幫助可以通過直接輸入應用程式名稱獲得。

6.1.1安裝攝像頭硬體

警告:攝像頭對靜電非常敏感。如果您在安裝攝像頭電路板時沒有防靜電手環,可以嘗試觸控一下水龍頭、金屬水槽或其它類似的東西即可。
攝像頭電路板與 Raspberry Pi 通過一條 15 芯的排線進行連線。僅有兩個連線座需要連線,排線需要安裝到攝像頭電路板和 Raspberry Pi 上。您需要正確安裝,否則攝像頭無法工作。對於攝像頭電路板,排線末端的藍色標記應該背對著電路板。而 Raspberry Pi 部分,藍色標記應該正對著網路介面方向。
儘管兩部分連線座不盡相同,但它們的工作方式很相似。對於 Raspberry Pi,拉起連線座兩端的卡扣。它應該很容易拉起,並能夠輕微活動。把排線完全插入到連線座中,並保證豎直,然後輕輕按下兩端的卡扣。攝像頭電路板方面,也需要您將卡扣向電路板相反方向拉開,然後輕輕插入排線,最後將卡扣推回。攝像頭電路板的連線座與 Pi 上的區別就在這裡。

6.1.2安裝攝像頭軟體

執行下文介紹的命令列進行下載並安裝最新的核心,GPU 韌體及應用程式。您需要連線到網際網路才可以實現以下操作。

$sudo apt-get update
$sudo apt-get upgrade

接下來,您首先需要在 Raspberry Pi 的 raspi-config 程式中啟用攝像頭的支援。
1)連線攝像頭與樹莓派
2)修改樹莓派配置,開啟攝像頭模組。

sudo raspi-config

這裡寫圖片描述
圖1
將游標移動到攝像頭選項(Camera option)處,並選擇啟用(Enable)。在退出 raspi-config 時會要求您重新啟動。啟用選項是為了確保重啟後 GPU 韌體能夠正確執行(包括攝像頭驅動和調節電路),並且 GPU 從主記憶體劃分到了足夠的記憶體使攝像頭能夠正確執行。
這裡寫圖片描述
圖2
測試系統已經完成安裝並正常工作,可嘗試以下命令:

$raspistill -v -o test.jpg

這將顯示來自攝像頭 5 秒鐘的預覽影象,並且拍攝一張照片,然後儲存為檔案 test.jpg,同時顯示出需要相關資訊。

6.1.3通用命令列引數

 預覽視窗
–preview, -p 預覽視窗設定 <‘x,y,w,h’>
允許使用者在螢幕上定義預覽視窗的大小和位置。注意,這將在所有其它視窗/影象的上層顯示。
–fullscreen, -f 全屏預覽模式
強制預覽螢幕全屏顯示。注意,這將會保留輸入影象的長寬比例,所以可能會在影象的邊緣出現填充條。
–nopreview, -n 不顯示預覽視窗
完全禁用預覽視窗。注意,儘管預覽視窗被禁用,但攝像頭仍然在進行處理,所以會繼續消耗資源。
–opacity, -op 設定預覽視窗透明度
設定預覽視窗的透明度。0 為完全透明,255 為完全不透明。
 攝像頭控制引數
–sharpness, -sh 設定影象銳度(-100 – 100)
設定影象的銳度,預設為 0。
–contrast, -co 設定影象對比度(-100 – 100)
設定影象的對比度,預設為 0。
–brightness, -br 設定影象亮度(0 – 100)
設定影象的亮度,預設為 50。0 為最暗,100 為最亮。
–saturation, -sa 設定影象飽和度(-100 – 100)
設定影象色彩飽和度。預設為 0。
–ISO, -ISO 設定捕捉 ISO
為捕捉影象設定 ISO。範圍為 100 到 800。
–vstab, -vs 開啟視訊穩定
僅用於視訊模式,用於開啟視訊穩定。
–ev, -ev 設定曝光補償
設定影象的曝光補償。範圍為 -10 到 10,預設為 0。
–exposure, -ex 設定曝光模式
可能用到的引數為:
auto – 使用自動曝光模式
night – 夜間拍攝模式
nightpreview -夜間預覽拍攝模式(暫且這麼稱呼)
backlight – 逆光拍攝模式
spotlight – 聚光燈拍攝模式
sports – 運動拍攝模式(高速快門等)
snow – 雪景優化拍攝模式
beach – 海灘優化拍攝模式
verylong – 長時間曝光拍攝模式
fixedfps – 幀約束拍攝模式
antishake – 防抖模式
fireworks – 煙火優化拍攝模式
注意,不是所有的設定都會在對攝像頭進行微調時得到相應作用。
–awb, -awb 設定自動白平衡
可能用到的引數為:
off – 關閉白平衡測算
auto – 自動模式(預設)
sun – 日光模式
cloud – 多雲模式
shade – 陰影模式
tungsten – 鎢燈模式
fluorescent – 熒光燈模式
incandescent – 白熾燈模式
flash – 閃光模式
horizon – 地平線模式
–imxfx, -ifx 設定影象特效
設定應用於影象上的特效
可能用到的引數為:
none – 無特效(預設)
negative – 反色影象
solarise – 曝光過度影象
posterize – 色調影象
whiteboard – 白板特效
blackboard – 黑板特效
sketch – 素描風格特效
denoise – 降噪影象
emboss – 浮雕影象
oilpaint – 油畫風格特效
hatch – 草圖特效
gpen – 馬克筆特效
pastel – 柔化風格特效
watercolour – 水彩風格特效
film – 膠片顆粒風格特效
blur – 模糊影象
saturation – 色彩飽和影象
colourswap – 暫未可用
washedout – 暫未可用
posterise – 暫未可用
colourpoint – 暫未可用
colourbalance – 暫未可用
cartoon – 暫未可用
–colfx, -cfx 設定色彩特效
指定影象 U 和 V 通道的引數(範圍 0 到 255)。例如:–colfx 128:128 將得到一張單色影象。
–metering, -mm 設定測光模式
為預覽和捕捉指定測光模式
可能用到的引數為:
average – 全畫面平衡測光
spot – 點測光
backlit – 模擬背光影象
matrix – 陣列測光
–rotation, -rot 設定影象旋轉(0 – 359)
對取景器和最終得到的影象進行旋轉。可以接受 0 以上任何值,但由於硬體限制,只支援 0、90、180、270 度。
–hflip, -hf 設定水平翻轉
水平翻轉預覽和儲存的影象。
–vflip, -vf 設定垂直翻轉
垂直翻轉預覽和儲存的影象。
–roi, -roi 設定感測器感光區域
允許指定用於預覽和捕捉的源所使用的感測器區域。該功能中 x 和 y 引數指定了坐上角的座標,以及定義了寬度和高度值,並且所有值都為標準化座標(0.0 到 1.0)。那麼,感光區域設定為橫向和縱向都為一半,並且寬度和高度都為感測器的四分之一時,可以寫為:
-roi 0.5,0.5,0.25,0.25
–shutter, -ss 設定快門速度
設定快門的速度為指定的值(單位為微秒)。據當前的考證,目前未定義時,快門速度上限大約為 330000us(330ms 或 0.33s)。

6.1.4應用程式專有設定

 raspistill
–width, -w 設定影象寬度
–height, -h 設定影象高度
–quality, -q 設定 JPEG 品質,品質為 100 時幾乎等同於未壓縮。75 相對是比較好的選擇。
–raw, -r 向 JPEG 後設資料中新增 RAW 資訊,該引數將從攝像頭獲取到的 RAW 資訊插入到 JPEG 後設資料中。
–output, -o 輸出檔名,指定輸出的檔名。如果不指定,將不儲存到檔案。如果檔名為“-”,將輸出傳送至標準輸出裝置。
–latest, -l 連結最後一幀到檔名,基於該名稱做一個指向最後一幀的檔案系統連結。
–verbose, -v 在執行過程中輸出詳細資訊,在程式執行過程中,輸出除錯/詳細資訊。
–timeout, -t 獲取圖片前的時間,程式將執行指定的時長,然後進行獲取操作(前提是 output 已指定)。如果未指定,將設定為 5 秒。
–timelapse, -tl 間隔拍攝模式,指定多次拍攝之間所間隔的毫秒值。注意,您需要在檔名中加入 %04d 做為畫面計數。
-t 30000 -tl 2000 -o image%04d.jpg,將會在 30 秒的時間內,每兩秒拍攝一次,並且將檔案命名為:image1.jpg、image0002.jpg…image0015.jpg。注意 %04d 表示在檔名中數字部分加入前導零,使其成為 4 位數。例如,%08d 將生成 8 位數字。如果間隔時間設定為 0,程式將不間斷(取決於系統負擔及儲存速度)進行拍攝。不過需要注意,每次捕捉前還是會有 30ms 的最小暫停時間,用於曝光計算操作。
–thumb, -th 設定縮圖引數(x:y:quality),允許指定插入到 JPEG 檔案中縮圖資訊。如果不指定,將為預設的 64×48 質量為 35 的縮圖。如果設定為 –thumb none,那麼將不會向檔案中插入縮圖資訊。檔案的尺寸也會稍微變小。
–demo, -d 執行演示模式,該引數將迴圈使用所有攝像頭引數,並且不會捕捉。而且無論是否完成所有的迴圈,在超時週期到達時都會停止演示操作。迴圈之前的時間需要設定毫秒值。
–encoding, -e 指定輸出檔案的編碼,可用的引數為 jpg、bmp、gif、png。注意,未被硬體加速支援的影象格式(gif、png、bmp)在儲存的時候要比 jpg 格式耗時更長。還需要注意,副檔名在編碼時將被完全忽略。
–exif, -x 在捕捉的內容中加入 EXIF 標籤(格式為 ‘key=value’),允許在 JPEG 影象中插入特定的 EXIF 標籤。您可以插入 32 條記錄。這是非常實用的功能,比如插入 GPS 後設資料。例如設定經度。
–exif GPS.GPSLongitude=5/1,10/1,15/100,該命令將會設定經度為 5 度 10 分 15 秒。檢視 EXIF 文件獲得所有可用標籤的詳細資訊。支援的標籤如下:
IFD0. 或 IFD1.

$raspivid -o test.h264 -t 25000 -timed 2500,5000

將進行 25 秒的錄製操作。錄製操作包括若干個 2500 毫秒(2.5 秒)錄製和 5000 毫秒(5秒)暫停的操作,並且重複時長超過 20 秒。所以該錄製過程中實際只錄制了 10 秒的內容。包括 4 段 2.5 秒的視訊片斷 = 被若干個 5 秒鐘暫停操作分隔開的 10 秒鐘視訊。
–keypress, -k 使用回車鍵在錄製和暫停兩種狀態間進行切換,每次點選回車鍵將會暫停或重新開始錄製程序。點選 X 鍵後點選回車鍵將停止錄製並關閉程式。注意,超時設定值將影響錄製結束時間,但僅在每次回車鍵點選後進行檢查,所以如果系統正在等待按鍵操作,儘管超時設定已過期,錄製程序退出前也會等待按鍵操作。
–signal, -s 使用 SIGUSR1 訊號在錄製和暫停兩種狀態間進行切換,向 Raspivid 程序傳送 USR1 訊號來切換錄製和暫停。該操作可以通過使用 kill 命令來實現。您可以使用“pgrep raspivid” 命令找到 raspivid 的程序 ID。
kill -USR1
【注意】超時設定值將影響錄製結束時間,但僅在每次傳送 SIGUSR1 訊號後進行檢查,所以如果系統正在等待訊號,儘管超時設定已過期,錄製程序退出前也會等待訊號的傳送操作。
–initial, -i 定義啟動時的初始狀態。定義攝像頭初始狀態為暫停或立即開始錄影。選項可以為“record”(錄影)或“pause”(暫停)。注意,如果您設定的超時時長很短,而且初始狀態設定為“暫停”,那麼將不會錄製任何輸出的內容。
–segment, -sg 將視訊流分段儲存到多個檔案,與儲存在單個檔案中不同,該引數將視訊分段儲存在以毫秒為單位所指定長度的數個檔案中。為了將生成的檔案命名為不同的名稱,您需要在檔名中合適的位置新增 %04d 或類似的引數來讓檔名中顯示計數值。例如:
–segment 3000 -o video%04d.h264,將分割成每段長度 3000 毫秒(3 秒)並且命名為 video0001.h264,video0002.h264 等。每個段落都是可無縫連線的(段落之間不會丟幀),但每個片段的長度將取決於幀內週期值,原因是每個分割的段落都需要起始於 I-frame 處。因此,每個段落都會等於或大於指定的時間長度。
–wrap, -wr 設定最大分段數,當輸出分段視訊時,該引數設定了最大分段數,並且達到最大值時,將返回到初始的第一個段落。該引數賦予了錄製分段視訊的功能,但是將覆蓋之前生成的檔案。所以,如果設定為 4,那麼上面的例子中所生成的檔名為 video0001.h264,video0002.h264,video0003.h264,video0004.h264。而且,一旦 video0004.h264 檔案錄製完畢後,計數將回到 1,並且 video0001.h264 將被覆蓋。
–start, -sn 設定初始段落數,當輸出分段視訊時,該引數為初始的段落數,它允許從指定的段落恢復之前的錄製操作。預設值為 1。

6.1.5應用示例

 影象捕捉
預設情況下,感測器將以其支援的最高解析度進行捕捉。可以在命令列中通過使用 -w 和 -h 引數進行更改。
# 兩秒鐘(時間單位為毫秒)延遲後拍攝一張照片,並儲存為 image.jpg
raspistill -t 2000 -o image.jpg
# 拍攝一張自定義大小的照片。
raspistill -t 2000 -o image.jpg -w 640 -h 480
# 降低影象質量,減小檔案尺寸
raspistill -t 2000 -o image.jpg -q 5
# 強制使預覽視窗出現在座標為 100,100 的位置,並且尺寸為寬 300 和高 200 畫素。
raspistill -t 2000 -o image.jpg -p 100,100,300,200
# 禁用預覽視窗
raspistill -t 2000 -o image.jpg -n
# 將影象儲存為 PNG 檔案(無失真壓縮格式,但是要比 JPEG 速度慢)。注意,當選擇影象編碼時,副檔名將被忽略。
raspistill -t 2000 -o image.png –e png
# 向 JPEG 檔案中新增一些 EXIF 資訊。該命令將會把作者名稱標籤設定為 Dreamcolor,GPS 海拔高度為 123.5米。
raspistill -t 2000 -o image.jpg -x IFD0.Artist=Dreamcolor -x GPS.GPSAltitude=1235/10
# 設定浮雕風格影象特效
raspistill -t 2000 -o image.jpg -ifx emboss
# 設定 YUV 影象的 U 和 V 通道為指定的值(128:128 為黑白影象)
raspistill -t 2000 -o image.jpg -cfx 128:128
# 僅顯示兩秒鐘預覽影象,而不對影象進行儲存。
raspistill -t 2000
# 間隔獲取圖片,在 10 分鐘(10 分鐘 = 600000 毫秒)的時間裡,每 10 秒獲取一張,並且命名為 image_number_001_today.jpg,image_number_002_today.jpg… 的形式,並且最後一張照片將命名為 latest.jpg。
raspistill -t 600000 -tl 10000 -o image_num_%03d_today.jpg -l latest.jpg
# 獲取一張照片併傳送至標準輸出裝置
raspistill -t 2000 -o –
# 獲取一張照片並儲存為一個檔案
raspistill -t 2000 -o – > my_file.jpg
#攝像頭一直工作,當按下回車鍵時獲取一張照片。
raspistill -t 0 -k -o my_pics%02d.jpg
 視訊捕捉
影象尺寸和預覽設定與影象捕捉相同。錄製的視訊預設尺寸為 1080p(1920×1080)
# 使用預設設定錄製一段 5 秒鐘的視訊片段(1080p30)
raspivid -t 5000 -o video.h264
# 使用指定位元速率(3.5Mbits/s)錄製一段 5 秒鐘的視訊片段
raspivid -t 5000 -o video.h264 -b 3500000
# 使用指定幀率(5fps)錄製一段 5 秒鐘的視訊片段
raspivid -t 5000 -o video.h264 -f 5
# 傳送到標準輸出裝置一段 5 秒鐘經過編碼的攝像頭流影象
raspivid -t 5000 -o –
# 儲存到檔案一段 5 秒鐘經過編碼的攝像頭流影象
raspivid -t 5000 -o – > my_file.h264

6.1.6檢視圖片

 方式一
安裝可以通過終端開啟截圖的shotwell。

$sudo apt-get install shotwell

檢視圖片命令。

$ sudo shotwell image.jpg

 方式二
安裝可以通過終端開啟截圖的gpicview。

$sudo apt-get install gpicview 

檢視圖片命令。

$sudo gpicview image.jpg

6.1.7截圖

想在樹莓派上面截圖或截圖用截圖工具scrot 通過命令列就能做到。
1.安裝
在Raspbian上安裝scrot:
命令: sudo apt-get install scrot
2.截圖
擷取整個螢幕:scrot (擷取圖片的預設名稱通常會有日期時間和解析度,比如:“2016-10-10-062821_1024x768_scrot.png”)
指定擷取圖片的名字:scrot example.png (那麼檔名就會叫“example” ,副檔名不要丟,另外改變副檔名也不能改變檔案格式)
指定檔案位置:scrot /home/pi/Desktop/example.png(截圖檔案“example.png”就會被儲存在 “/home/pi/Desktop/” ,注意,只有路徑沒有檔名是不行的)
擷取部分圖片:scrot -s 然後拖動要截圖的區域(scrot -s /home/pi/Desktop/example.png 命名和指定路徑)
 其他命令引數:
-h 顯示更多幫助
-v 獲取當前版本
-d x 新增X秒的延遲拍攝
-c 新增一個倒計時延遲拍攝
-s 允許使用者用滑鼠捕捉特定區域
-u 捕捉當前活動視窗
-q X 指定影象質量百分率X(預設75)
-t X 建立一個百分比大小為X的縮圖
-e 在截圖後指定一個命令來執行

6.1.8視屏播放

 MP4Box
raspivid 通常會將錄製的視訊儲存為 .h264 格式的檔案。而我們使用的很多播放器可能無法正常播放該格式的視訊檔案。這就需要我們將生成的 .h264 格式的檔案封裝到播放器能夠識別的視訊容器格式中(比如封裝為 mp4 格式)。有很多視訊處理軟體可以達到這個目的,您也可以直接在 Raspberry Pi 上直接進行封裝。這裡介紹的是“gpac”中的“MP4Box”。安裝和使用的方法如下:

$sudo apt-get update
$sudo apt-get install gpac
$sudo MP4Box -add filename.h264 filename.mp4

 Omxplayer
 播放

$sudo omxplayer –o hdmi 檔名

 播放控制
Key Action
  加速
  減速
j   上一條音軌
k   下一條音軌
i   上一節
o   下一節
n   上一條字幕軌
m   下一條字幕軌
s   顯示/不顯示字幕
q   退出
空格或p  暫停/繼續
–   減小音量
  增加音量
左   後退30
右   前進30
上   後退600
下   前進600

6.1.9 擴充套件閱讀

樹莓派專用CSI攝像頭插到樹莓派的CSI口上並在在raspi-config中開啟後就可以使用Raspistill命令直接使用,但如果在OpenCV中呼叫CSI攝像頭會出現無資料的現象(cv2.VideoCapture(0)這時不會報錯)。
這是因為樹莓派中的camera module是放在/boot/目錄中以韌體形式載入的,不是一個標準的V4L2的攝像頭驅動,所以載入起來之後會找不到/dev/video0的裝置節點。我們在/etc/modules裡面新增一行bcm2835-v4l2(小寫的L)就能解決問題。

$sudo vi /etc/modules

新增:bcm2835-v4l2

這裡寫圖片描述

6.2樹莓派實現動作捕捉、抓拍並儲存照片

6.2.1開通樹莓派SSH、VNC服務、開通攝像頭

將樹莓派接上鍵盤、滑鼠和顯示屏。進入Raspbian系統,開啟命令列終端,輸入:

$ sudo raspi-config

這裡寫圖片描述
圖3
當然也可直接在樹莓派上配置。
遠端登入,預設使用者名稱:pi, 預設密碼:raspberry

6.2.2 PC機遠端操作樹莓派

使用PC機遠端通過命令列或VNC操作樹莓派要比樹莓派接上鍵盤滑鼠,盯著小螢幕看方便很多。具體操作步驟如下:
1)樹莓派接入網路,在PC終端輸入:(注:Windows下要用PuTTY軟體作為命令列終端,Mac電腦可以直接輸入)

$ ssh [email protected]樹莓派的IP地址

輸入遠端連線密碼。如果跳到:
[email protected]:~ $
說明連線成功,你現在可以在pc機上用命令列操作樹莓派了。
2)在pc機上用VNC連線樹莓派。關於SVN的使用請讀者看前面的章節。

6.2.3安裝動作捕捉指令碼

將附件的指令碼拷貝到樹莓派的 /home/pi 目錄下建立一個新目錄用來儲存抓拍的照片:

$ sudo mkdir picam  

然後就可以執行指令碼了:

$ sudo python picam.py  

這時,如果有任何物體在移動,樹莓派的攝像頭就會抓拍,並儲存到/home/pi/picam資料夾,在pc機上,就可以遠端用VNC檢視這些照片。
【附件】picam.py的程式碼

#!/usr/bin/python
# original script by brainflakes, improved by pageauc, peewee2 and Kesthal
# www.raspberrypi.org/phpBB3/viewtopic.php?f=43&t=45235
# You need to install PIL to run this script
# type "sudo apt-get install python-imaging-tk" in an terminal window to do this
import StringIO
import subprocess
import os
import time
from datetime import datetime
from PIL import Image
# Motion detection settings:
# Threshold          - how much a pixel has to change by to be marked as "changed"
# Sensitivity        - how many changed pixels before capturing an image, needs to be higher if noisy view
# ForceCapture       - whether to force an image to be captured every forceCaptureTime seconds, values True or False
# filepath           - location of folder to save photos
# filenamePrefix     - string that prefixes the file name for easier identification of files.
# diskSpaceToReserve - Delete oldest images to avoid filling disk. How much byte to keep free on disk.
# cameraSettings     - "" = no extra settings; "-hf" = Set horizontal flip of image; "-vf" = Set vertical flip; "-hf -vf" = both horizontal and vertical flip
threshold = 10
sensitivity = 20
forceCapture = True
forceCaptureTime = 60 * 60 # Once an hour
filepath = "/home/pi/picam"
filenamePrefix = "capture"
diskSpaceToReserve = 40 * 1024 * 1024 # Keep 40 mb free on disk
cameraSettings = ""
# settings of the photos to save
saveWidth   = 1296
saveHeight  = 972
saveQuality = 15 # Set jpeg quality (0 to 100)
# Test-Image settings
testWidth = 100
testHeight = 75
# this is the default setting, if the whole image should be scanned for changed pixel
testAreaCount = 1
testBorders = [ [[1,testWidth],[1,testHeight]] ]  # [ [[start pixel on left side,end pixel on right side],[start pixel on top side,stop pixel on bottom side]] ]
# testBorders are NOT zero-based, the first pixel is 1 and the last pixel is testWith or testHeight
# with "testBorders", you can define areas, where the script should scan for changed pixel
# for example, if your picture looks like this:
#
#     ....XXXX
#     ........
#     ........
#
# "." is a street or a house, "X" are trees which move arround like crazy when the wind is blowing
# because of the wind in the trees, there will be taken photos all the time. to prevent this, your setting might look like this:
# testAreaCount = 2
# testBorders = [ [[1,50],[1,75]], [[51,100],[26,75]] ] # area y=1 to 25 not scanned in x=51 to 100
# even more complex example
# testAreaCount = 4
# testBorders = [ [[1,39],[1,75]], [[40,67],[43,75]], [[68,85],[48,75]], [[86,100],[41,75]] ]
# in debug mode, a file debug.bmp is written to disk with marked changed pixel an with marked border of scan-area
# debug mode should only be turned on while testing the parameters above
debugMode = False # False or True
# Capture a small test image (for motion detection)
def captureTestImage(settings, width, height):
command = "raspistill %s -w %s -h %s -t 200 -e bmp -n -o -" % (settings, width, height)
imageData = StringIO.StringIO()
imageData.write(subprocess.check_output(command, shell=True))
imageData.seek(0)
im = Image.open(imageData)
buffer = im.load()
imageData.close()
return im, buffer
# Save a full size image to disk
def saveImage(settings, width, height, quality, diskSpaceToReserve):
keepDiskSpaceFree(diskSpaceToReserve)
time = datetime.now()
filename = filepath   "/"   filenamePrefix   "-%04d%02d%02d-%02d%02d%02d.jpg" % (time.year, time.month, time.day, time.hour, time.minute, time.second)
subprocess.call("raspistill %s -w %s -h %s -t 200 -e jpg -q %s -n -o %s" % (settings, width, height, quality, filename), shell=True)
print "Captured %s" % filename
# Keep free space above given level
def keepDiskSpaceFree(bytesToReserve):
if (getFreeSpace() < bytesToReserve):
for filename in sorted(os.listdir(filepath   "/")):
if filename.startswith(filenamePrefix) and filename.endswith(".jpg"):
os.remove(filepath   "/"   filename)
print "Deleted %s/%s to avoid filling disk" % (filepath,filename)
if (getFreeSpace() > bytesToReserve):
return
# Get available disk space
def getFreeSpace():
st = os.statvfs(filepath   "/")
du = st.f_bavail * st.f_frsize
return du
# Get first image
image1, buffer1 = captureTestImage(cameraSettings, testWidth, testHeight)
# Reset last capture time
lastCapture = time.time()
while (True):
# Get comparison image
image2, buffer2 = captureTestImage(cameraSettings, testWidth, testHeight)
# Count changed pixels
changedPixels = 0
takePicture = False
if (debugMode): # in debug mode, save a bitmap-file with marked changed pixels and with visible testarea-borders
debugimage = Image.new("RGB",(testWidth, testHeight))
debugim = debugimage.load()
for z in xrange(0, testAreaCount): # = xrange(0,1) with default-values = z will only have the value of 0 = only one scan-area = whole picture
for x in xrange(testBorders[z][0][0]-1, testBorders[z][0][1]): # = xrange(0,100) with default-values
for y in xrange(testBorders[z][1][0]-1, testBorders[z][1][1]):   # = xrange(0,75) with default-values; testBorders are NOT zero-based, buffer1[x,y] are zero-based (0,0 is top left of image, testWidth-1,testHeight-1 is botton right)
if (debugMode):
debugim[x,y] = buffer2[x,y]
if ((x == testBorders[z][0][0]-1) or (x == testBorders[z][0][1]-1) or (y == testBorders[z][1][0]-1) or (y == testBorders[z][1][1]-1)):
# print "Border %s %s" % (x,y)
debugim[x,y] = (0, 0, 255) # in debug mode, mark all border pixel to blue
# Just check green channel as it's the highest quality channel
pixdiff = abs(buffer1[x,y][1] - buffer2[x,y][1])
if pixdiff > threshold:
changedPixels  = 1
if (debugMode):
debugim[x,y] = (0, 255, 0) # in debug mode, mark all changed pixel to green
# Save an image if pixels changed
if (changedPixels > sensitivity):
takePicture = True # will shoot the photo later
if ((debugMode == False) and (changedPixels > sensitivity)):
break  # break the y loop
if ((debugMode == False) and (changedPixels > sensitivity)):
break  # break the x loop
if ((debugMode == False) and (changedPixels > sensitivity)):
break  # break the z loop
if (debugMode):
debugimage.save(filepath   "/debug.bmp") # save debug image as bmp
print "debug.bmp saved, %s changed pixel" % changedPixels
# else:
#     print "%s changed pixel" % changedPixels
# Check force capture
if forceCapture:
if time.time() - lastCapture > forceCaptureTime:
takePicture = True
if takePicture:
lastCapture = time.time()
saveImage(cameraSettings, saveWidth, saveHeight, saveQuality, diskSpaceToReserve)
# Swap comparison buffers
image1 = image2
buffer1 = buffer2

6.2.4設定指令碼開機啟動

在終端上輸入:

$ sudo vi /etc/rc.local  

就會出現一個文字編輯器,
在文字內容的exit 0 上面新增一行:

$ python /home/pi/picam.py  

然後儲存更改。
重啟樹莓派:

$ sudo reboot  

即可實現開機自動執行。之所以選擇這個指令碼是因為它簡潔,有效,而且還能自動清除過期的圖片。相比之下,motion這個軟體就顯得比較複雜。有興趣的同學還可以修改指令碼實現抓拍後自動上傳到網盤,或傳送郵件等功能。

6.3樹莓派 motion 搭建攝像頭監控系統

1. 安裝

$sudo apt install motion

2. 配置motion選項
備份配置檔案

$sudo cp /etc/motion/motion.conf /etc/motion/motion.conf.bak

開啟配置文件

$sudo vim /etc/motion/motion.conf

更改文件中以下內容

daemon on                        #開啟守護程序(選配)
target_dir /home/pi/motion-images    #圖片儲存的路徑
#videodevice /dev/video0            #攝像頭裝置(預設)可修改            
stream_localhost off                 #允許通過網頁檢視攝像頭
stream_auth_method 2               #開啟密碼認證
stream_authentication 使用者名稱:密碼    #網頁檢視攝像頭的使用者名稱和密碼

建立一個目錄來儲存Motion拍下的照片

$mkdir ~/motion-images

官方詳細配置說明:http://lavrsen.dk/foswiki/bin/view/Motion/ConfigFileOptions
3.開啟motion

$ sudo service motion start
$sudo motion

用瀏覽器登陸樹莓派的網址 192.168.3.233:8081 ,會彈出使用者名稱和密碼的對話方塊,輸入使用者名稱和密碼後看到影象就成功了。需要登入兩次。

這裡寫圖片描述
圖4
4. 設定為開機執行(選配)

$sudo vim /etc/rc.local

在exit 0前新增 motion , 儲存,就會開機自動執行了。
5. 部分詳細配置選項的翻譯

表1

ffmpeg_duplicate_frames 除錯模式,只看到變化的影象

選項Range/Values Default 說明
auto_brightness Values: on,off
Default: off
讓motion自動調節視訊的的亮度,只適用於不帶有自動亮度調節的攝像機
brightnessValues: 0-255
Default: 0 (disabled)
調整攝像機的亮度
saturation Values: 0 – 255
Default: 0 (disabled)
調整攝像機的顏色飽和度
hueValues: 0 – 255
Default: 0 (disabled)
調整攝像機的色調
contrast Values: 0-255
Default: 0 (disabled)
調整攝像機的對比度
daemon Values: on,off
Default: off
以守護程序在後臺執行。這個選項只能放在motion.conf,不能放在 thread config file
emulate_motionValues: on, off
Default: off
即使沒有運動物體也要儲存影象
ffmpeg_output_moviesValues: on, off
Default: off
是否儲存視訊
ffmpeg_bps Values: 0 – 9999999
Default: 400000
視訊位元率
ffmpeg_variable_bitrate Values: 0, 2 -31
Default: 0 (disabled)
動態位元率,如果開啟這個功能ffmpeg_bps將被忽略,0為關閉,2為最好質量,31為最差質量
Values: on, off
Default: on
為了達到每秒的幀數要求,會複製一下幀填充空白時間,關掉這個功能後每個幀都緊接下一個幀,看起來像快進
ffmpeg_output_debug_moviesValues: on, off
Default: off
ffmpeg_video_codecValues:mpeg4, msmpeg4, swf, flv, ffv1, mov, ogg, mp4, mkv, hevc
Default: mpeg4
視訊格式
framerate Values: 2 – 100
Default: 100 (no limit)
幀速率,每秒多少幀
frequency Values: 0 – 999999
Default: 0 (Not set)
頻率協調 Hz
lightswitchValues: 0 – 100
Default: 0 (disabled)
忽略光照強度改變引起的變化
locate_motion_modeValues: on, off, preview
Default: off
給運動物體用方框標出
locate_motion_style Values: box, redbox, cross, redcross
Default: box
標記風格
max_movie_timeValues: 0 (infinite) – 2147483647
Default: 3600
最大視訊時間
minimum_frame_timeValues: 0 – 2147483647
Default: 0
最小幀間隔,設定為0表示採用攝像頭的幀率
minimum_motion_framesValues: 1 – 1000s
Default: 1
捕捉持續至少指定時間的運動幀
movie_filenameValues: Max 4095 characters
Default: %v-%Y%m%d%H%M%S
視訊的檔名
ffmpeg_timelapseValues: 0-2147483647
Default: 0 (disabled)
間隔時間,拍攝延時視訊
ffmpeg_timelapse_mode Values: hourly, daily, weekly-sunday, weekly-monday, monthly, manual
Default: daily
延時拍攝模式
timelapse_filenameValues: Max 4095 characters
Default: %v-%Y%m%d-timelapse
延時拍攝的檔名
output_pictures Values: on,off,first,best,center
Default: on
是否儲存圖片和模式設定
output_debug_picturesValues: on,off
Default: off
圖片除錯模式,只輸出運動物體
picture_filename Values: Max 4095 characters
Default: %v-%Y%m%d%H%M%S-%q
圖片檔名
picture_type Values: jpeg,ppm
Default: jpeg
圖片型別
post_capture Values: 0 – 2147483647
Default: 0 (disabled)
運動在持續多少幀之後才被捕捉
pre_capture Values: 0 – 100s
Default: 0 (disabled)
輸出影象包括捕捉到運動的前幾秒
quality Values: 1 – 100
Default: 75
jpg影象的質量
quiet Values: on, off
Default: off
安靜模式,檢測到運動不輸出嗶
rotate Values: 0, 90, 180, 270
Default: 0 (not rotated)
旋轉影象角度
stream_auth_method Values: 0,1,2
Default: 0
網頁監控身份認證方法:0-無,1-基本,2-MD5
stream_authentication Values: username:password
Default: Not defined
網頁監控使用者名稱和密碼
stream_limit Values: 0 – 2147483647
Default: 0 (unlimited)
限制幀的數量
stream_localhost Values: on, off
Default: on
是否只能本地訪問網路攝像頭
stream_maxrate Values: 1 – 100
Default: 1
限制網路攝像頭幀速率
stream_port Values: 0 – 65535
Default: 0 (disabled)
網路攝像頭埠
stream_quality Values: 1 – 100
Default: 50
網路攝像頭傳輸質量
switchfilter Values: on, off
Default: off
過濾器開關,過濾器用來區分真正的運動和噪聲
target_dir Values: Max 4095 characters
Default: Not defined = current working directory
視訊和圖片的儲存路徑
videodevice Values: Max 4095 characters
Default: /dev/video0
攝像頭裝置名
height Values: Device Dependent
Default: 288
影象高度,範圍跟攝像機相關
width Values: Device Dependent
Default: 352
影象寬度,範圍跟攝像機相關
process_id_file Values: Max 4095 characters
Default: Not defined
儲存PID的檔案,推薦/var/run/motion.pid
database_busy_timeout Values: 0 .. positive integer
Default: 0
資料庫等待超時時間,毫秒