1. 程式人生 > >5、樹莓派連線官方CSI攝像頭的使用

5、樹莓派連線官方CSI攝像頭的使用

本篇博文大部分轉https://blog.csdn.net/u013162035/article/details/78580486

其中有部分細節根據自己的實際操作進行了修改

5.1樹莓派基本操作

      目前提供了三個應用程式,分別為:raspistill、raspivid、raspistillyuv。其中 raspistill 和 raspistillyuv 非常相似,並且都是用於捕捉影象,而 raspivid 用於捕捉視訊。 在樹莓派3B+的樹莓派的 raspberry 2018.04.18 stretch版本的系統中已經自帶raspistill,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 元件將會對預覽幀進行“吸收”。這是由於儘管不需要攝像頭生成供顯示所用的的預覽幀,但是仍需要使用它們進行曝光計算和白平衡設定的緣故。
   此外,還可以省略檔名引數,這樣既可以直接預覽顯示而不寫入檔案,或者直接輸出到標準輸出裝置上。命令列幫助可以通過直接輸入應用程式名稱獲得。

5.1.1安裝攝像頭硬體

警告:攝像頭對靜電非常敏感。如果您在安裝攝像頭電路板時沒有防靜電手環,可以嘗試觸控一下水龍頭、金屬水槽或其它類似的東西即可。
     攝像頭電路板與 Raspberry Pi 通過一條 15 芯的排線進行連線。僅有兩個連線座需要連線,排線需要安裝到攝像頭電路板和 Raspberry Pi 上。您需要正確安裝,否則攝像頭無法工作。對於攝像頭電路板,排線末端的藍色標記應該背對著電路板。而 Raspberry Pi 部分,藍色標記應該正對著網路介面方向。 


     儘管兩部分連線座不盡相同,但它們的工作方式很相似。對於 Raspberry Pi,拉起連線座兩端的卡扣。它應該很容易拉起,並能夠輕微活動。把排線完全插入到連線座中,並保證豎直,然後輕輕按下兩端的卡扣。攝像頭電路板方面,也需要您將卡扣向電路板相反方向拉開,然後輕輕插入排線,最後將卡扣推回。攝像頭電路板的連線座與 Pi 上的區別就在這裡。

5.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,儲存在/home/pi的目錄下面,同時顯示出需要相關資訊。

5.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)。

5.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。

5.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
  • 1

檢視圖片命令。

$ sudo shotwell image.jpg
  • 1

 方式二
安裝可以通過終端開啟截圖的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

5.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
  • 1

這裡寫圖片描述

圖3

當然也可直接在樹莓派上配置。
遠端登入,預設使用者名稱:pi, 預設密碼:raspberry

6.2.2 PC機遠端操作樹莓派

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

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

輸入遠端連線密碼。如果跳到:
[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這個軟體就顯得比較複雜。有興趣的同學還可以修改指令碼實現抓拍後自動上傳到網盤,或傳送郵件等功能。

5.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.8.105: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自動調節視訊的的亮度,只適用於不帶有自動亮度調節的攝像機
brightness Values: 0-255 Default: 0 (disabled) 調整攝像機的亮度
saturation Values: 0 - 255 Default: 0 (disabled) 調整攝像機的顏色飽和度
hue Values: 0 - 255 Default: 0 (disabled) 調整攝像機的色調
contrast Values: 0-255 Default: 0 (disabled) 調整攝像機的對比度
daemon Values: on,off Default: off 以守護程序在後臺執行。這個選項只能放在motion.conf,不能放在 thread config file
emulate_motion Values: on, off Default: off 即使沒有運動物體也要儲存影象
ffmpeg_output_movies Values: 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_movies Values: on, off Default: off
ffmpeg_video_codec Values: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
lightswitch Values: 0 - 100 Default: 0 (disabled) 忽略光照強度改變引起的變化
locate_motion_mode Values: on, off, preview Default: off 給運動物體用方框標出
locate_motion_style Values: box, redbox, cross, redcross Default: box 標記風格
max_movie_time Values: 0 (infinite) - 2147483647 Default: 3600 最大視訊時間
minimum_frame_time Values: 0 - 2147483647 Default: 0 最小幀間隔,設定為0表示採用攝像頭的幀率
minimum_motion_frames Values: 1 - 1000s Default: 1 捕捉持續至少指定時間的運動幀
movie_filename Values: Max 4095 characters Default: %v-%Y%m%d%H%M%S 視訊的檔名
ffmpeg_timelapse Values: 0-2147483647 Default: 0 (disabled) 間隔時間,拍攝延時視訊
ffmpeg_timelapse_mode Values: hourly, daily, weekly-sunday, weekly-monday, monthly, manual Default: daily 延時拍攝模式
timelapse_filename Values: Max 4095 characters Default: %v-%Y%m%d-timelapse 延時拍攝的檔名
output_pictures Values: on,off,first,best,center Default: on 是否儲存圖片和模式設定
output_debug_pictures Values: 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 資料庫等待超時時間,毫秒