Python實現樹莓派攝像頭持續錄像並傳送到主機

關於樹莓派,想必從事嵌入式開發的開發者都有聽過,樹莓派原名爲Raspberry Pi,也就是它的英文讀法,樹莓派誕生於英國,由「Raspberry Pi 基金會」這個慈善組織註冊開發。埃•厄普頓就是該項目的頭目。在2012年的3月,英國劍橋大學埃本•阿普頓(Eben Epton)正式發售世界上最小的臺式機,又稱卡片式電腦,外形只有信用卡大小,卻具備電腦的全部基本功能,這就是Raspberry Pi電腦板,中文譯名」樹莓派」!python

樹莓派做爲一個輕便迷你的小終端很受大衆的喜好!!!shell

樹莓派的特色

與常見的51單片機和STM32等這類的嵌入式微控制器相比,不只能夠完成相同的IO引腳控制以外,還能運行有相應的操做系統,能夠完成更復雜的任務管理與調度,可以支持更上層應用的開發,爲了開發者提供了更廣闊的應用空間。好比開發語言的選擇不只僅只限於C語言,鏈接底層硬件與上層應用,能夠實現物聯網的雲控制和雲管理,也能夠忽略樹莓派的IO控制,使用樹莓派搭建小型的網絡服務器,作一些小型的測試開發和服務。緩存

與通常的PC計算機平臺相比,樹莓派能夠提供的IO引腳,可以直接控制其餘底層硬件的功能,這是通常PC計算機作不到的,固然,樹莓派體積小,成本低,照常能夠完成一些PC任務與應用。服務器

樹莓派自帶的攝像頭拍攝夜空是有先例的,起碼能夠作到延時攝影。對於實時拍攝沒有研究,可是仍然有必要測試。
樹莓派自帶的攝像頭是500萬像素,價格在26-29歐元(人民幣200+左右)網絡

實時仍是過後採集記錄結果?

樹莓派上的攝像機,是使用一個 raspivid 命令操做的。 拋開這個命令的其餘參數,其輸出數據有2種方式:併發

  • 將數據保存成文件,儲存在SD卡上,以便過後讀取;
  • 將數據按照字節流的形式,直接輸出到STDOUT標準輸出中,能夠實時獲取。

選擇哪一種方式,首先要考慮咱們可否具備足夠的採集數據的能力。測試

raspivid 命令能夠調節相機模塊的輸出比特率。輸出是以 H264 編碼輸出的,比特率通常默認是17Mbps,可是這個數字能夠調小。 若是按照17Mbps算,就是一秒鐘2.12兆字節。 咱們記錄數據或者獲取數據的速度不能低於這個值,不然長時間錄像可能形成樹莓派的緩存充滿,致使樹莓派崩潰。ui

樹莓派的網卡是使用了其USB總線,傳送速度是100Mb/s或者12.5MB/s。 實際上後文的實驗代表,目前能達到的傳送速度只有 3MB/s(TCP) 或者 6MB/s(UDP)this

若是使用SD卡存儲,這個記錄速度也是能夠達到的,可是,SD卡有寫入壽命,這是要考慮的。 例如,對於32GB的卡,即便咱們能利用所有存儲空間,以2MB/s的速度錄像,也只能記錄4.55小時。編碼

如何經過網絡實時傳送數據?

raspivid 命令的 -o 選項,就是用來指定輸出文件的。 在Linux系統中,輸出到文件並不等於寫入到磁盤(這裏是SD卡)。 咱們仍然可能使用 RAMDisk 這種技術,讓輸出只是暫時存儲在內存中,並稍後讀取,而後刪除之。 可是,樹莓派的可用內存可能只有 280MB ,這最多隻能記錄差很少2分鐘的視頻。

若是咱們有文件形式的攝像記錄,那麼就彷佛可使用文件傳輸的協議,例如 sftp, scp 等等登陸到樹莓派下載文件了。 然而這是不對的。這些協議在傳輸中使用了加密。

樹莓派在向咱們的電腦進行數據傳送的時候,若是用這些協議,就必須先對發送的數據進行加密。 在互聯網上,加密是很好的設計。可是在樹莓派和電腦之間只用一根網線鏈接的時候,就不是了。 樹莓派的運算能力是頗有限的,使用加密只會讓傳送速度變慢,因此,不要使用加密!

咱們使用最原始而簡單的方法:使用 netcat命令 ,在筆記本電腦這一端監聽數據輸入。 在樹莓派這一端,咱們讓 raspivid 獲取必定週期(好比10分鐘,也許能夠更長)的錄像, 將結果設定爲直接輸出,而後利用Linux的管道機制,直接送進 netcat 發送。

配置由樹莓派和筆記本構成的網絡

樹莓派和筆記本電腦之間的鏈接,使用普通網線便可, 由於筆記本和樹莓派上的網卡都能自動適應網線,設定正確的模式(正常來講要使用交叉網線)。

重要的一步是,筆記本電腦和樹莓派鏈接後構成的網絡中,須要手動爲兩個設備設定IP地址。 對於筆記本電腦的設定,就比較簡單了。 咱們將筆記本電腦和樹莓派相連的網卡上,將電腦的 IP地址設定爲xxx.xxx.x.xxx子網掩碼爲255.255.255.0網關不要填 ``。

配置樹莓派的方法是,先將樹莓派斷電,而後取出所用的SD卡,用讀卡器插回電腦。 在SD卡的boot分區中,有個cmdline.txt,這是樹莓派開機時所用到的一些參數。

打開這個文件,會發現裏面只有一行。這一行中用空格分開了不少設定參數。 咱們在這一行的結尾,不添加空行,直接加上空格,而後寫上: ip=xxx.xxx.x.xxx

固然若是這一行裏面已經有了ip=的參數,應該直接修改它。

這樣的結果就是,樹莓派開機以後,會本身選擇這個IP地址做爲本身的地址。

實如今筆記本上監聽輸入

netcat命令,在每收到一個文件的EOF(End Of File,代表文件已經到結尾),就會退出。 咱們爲了讓接收可以連續進行,須要用腳本連續運行這個命令。 這樣就會爲每一個新接收到的視頻,在筆記本電腦這一端創建一個文件用來存儲。

# -*- coding: utf-8 -*-

import os
import signal
import subprocess
import sys
import uuid

# 獲取程序運行的本地目錄,和用來存儲接收結果的recv文件夾目錄

BASEPATH = os.path.realpath(os.path.dirname(sys.argv[0]))
RECV = os.path.join(BASEPATH, 'recv')

# 若是接收目錄不存在,就自動新建

print " *** Received files are put into: %s" % RECV
if not os.path.isdir(RECV):
    os.system('mkdir -p %s' % RECV)

# 下面的部分用來記錄正在等待接收的文件。這個文件會以一個UUID.tmp的格式命名。
# 在接收成功後,就會被重命名爲UUID。(UUID是一個特定格式的惟一字符串,不會重複)。
# 若是在接收過程當中按下Ctrl+C,就會發送一個終止命令給程序,這樣程序會退出,
# 並刪除沒有接收完整的那個文件。

working = False
fullname = False

def sigint_handler(signum, frame):
    global fullname, working
    print "\n"
    print " *** SIGINT detected. End the program."
    if working and fullname != False:
        print " *** Unfinished recording deleted."
        os.system('rm -f %s.tmp' % fullname)
    exit()
signal.signal(signal.SIGINT, sigint_handler)

# 使用一個死循環來不斷運行netcat(nc)命令。

n = 1
while True:
    recname = str(uuid.uuid1())
    print " [%8d] Listening for file [%s]. Use Ctrl+C to stop this script." % (n, recname)
    fullname = os.path.join(RECV, recname)

    working = True # 標記接收開始
    # 使用 nc -lp 10401 命令接收數據,代表端口爲10401。
    subprocess.call('nc -lp 10401 > %s.tmp' % fullname, shell=True)
    os.system('mv %s.tmp %s' % (fullname, fullname))
    working = False # 標記接收完畢

    n += 1

上文所述的腳本,在筆記本上運行以後,就會在本地開啓10401端口,等待樹莓派上傳送的文件。 傳送的會直接寫入一個由UUID(全局惟一ID)標識的文件中,能夠供之後處理。

在樹莓派上攝像併發送攝像結果

在樹莓派上命令拍攝的方法是:

$ raspivid -o - -b 16000000 -t 100000 | nc xxx.xxx.x.xxx 10401

這條指令的意義以下:

  • -o - ,使用-o設定輸出,-表示直接輸出到標準輸出中,不寫入文件。
  • -b 16000000 ,設定輸出比特率爲16000000 bit/s。這大約是2兆字節每秒。
  • -t 100000 ,設定錄像時間爲100000毫秒,亦即100秒。
  • | nc xxx.xxx.x.xxx 10401 ,使用管道|將結果導入到nc中,nc是發送模式,目標是xxx.xxx.x.xxx計算機上的10401端口。
相關文章
相關標籤/搜索