樹莓派上安裝的系統是不帶圖形界面的,不能直接查看拍攝的圖形和視頻,考慮通過網絡將樹莓派攝像頭拍攝的圖片和視頻發送給其他電腦進行查看。
其中控制攝像頭使用的是picamera庫,該庫是使用python控制樹莓派攝像頭的。
一、安裝picamera庫
1、在python3中安裝picamera庫
sudo apt-get install python3-camera
2、檢查picamera庫安裝是否成功
python3 import picamera
二、使用樹莓派將拍攝的圖片發送給上位機,一共需要兩個python文件,一個運行在樹莓派上作為客戶端,負責采集圖像數據,一個運行在window上作為服務端,接受樹莓派發送的數據並保存到本地目錄下。
每次發送數據時,先發送圖片信息的長度,然后發送圖像的數據信息,每一幅圖片都按照這個規定發送。
1、樹莓派端的代碼如下:
#!/usr/bin/python3 # -*- coding:utf-8 -*- #通過網絡發送圖片給上位機,發送的格式為,先發送圖片長度信息,然后再發送圖像數據 import os import picamera import struct import socket import time #創建一個socket連接,地址為服務器端的地址 client_socket = socket.socket() client_socket .connect(('192.168.6.37',8000)) #創建一個類似文件對象輸出 connection = client_socket.makefile('wb') try: camera = picamera.PiCamera() #初始化攝像頭 camera.resolution = (640,480) #設置分辨率 #攝像頭預熱 camera.start_preview() time.sleep(2) #獲取當前時間 start = time.time() #創建一個字節流 stream = io.BytesIO() for foo in camera.capture_continuous(stream,'jpeg') #連續捕獲圖像 #寫圖像長度信息到文件流,按照32bit無符號整數 connection.write(struct.pack('<L',stream.tell())) connection.flush() #清空緩沖區 #重定位指針位置 stream.seek(0) connection.write(stream.read()) #寫入圖像數據 if time.time() - start > 30: #捕獲30s的圖像 break #開始捕獲下一幅圖像 stream.seek(0) stream.truncate() connection.write(struct.pack('<L',0)) #寫長度為0表示結束發送標志 finally: connection.close() client_socket.close()
2、服務器端代碼:
#-*- coding:utf-8 -*- #接受樹莓派發送來的圖片,保存到本地目錄 import os import socket import struct from PIL import Image #創建一個socket連接 server_socket = socket.socket() server_socket.bind(('0.0.0.0',8000)) #綁定所有的接口 server_socket.listen(0) #監聽 #將接受的數據轉換為類似文件的對象輸出 connection = server_socket.accept()[0].makefile('rb') index =0 try: while True: #按照32bit無符號小端對齊方式讀取圖片的長度 image_len = struct.unpack('<L',connection.read(struct.calcsize('<L')))[0] if not image_len: #長度為0表示發送結束 break #創建一個字節流 image_stream = io.BytesIO() image_stream.write(connection.read(image_len)) #重定位流的坐標位置 image_stream.seek(0) #打開圖片 image = Image.open(image_stream) index +=1 # 保存圖片到本地 image.save('pic'+str(index)+'.jpg') print('Image is %dx%d' %image.size) #打印圖像尺寸信息 #檢查圖片是否損壞 image.verfity() print('Image is verified') finally: connection.close() server_socket.close()
先運行服務器端的程序,然后運行客戶端的程序。
三、樹莓派將攝像頭拍攝的視頻通過網絡發送給上位機,上位機通過vlc播放器播放實時視頻。
1、樹莓派采集視頻,通過網絡發送,代碼如下:
#!/usr/bin/python3 # -*- coding:utf-8 -*- #樹莓派將拍攝的視頻通過網絡發送給上位機進行實時播放 import socket import time import picamera #創建一個socket連接 client_socket = socket.socket() client_socket.connect(('192.168.6.37',8000)) #創建一個類似文件對象輸出 connection = client_socket.makefile('rb') try: camera = picamera.PiCamera() camera.resolution= (320,240) #設置分辨率 camera.framerate = 20 #設置幀頻 #預熱攝像頭 camera.start_preview() time.sleep(2) #開始捕獲一段60s的視頻到文件流 camera.start_recording(connection,format = 'h264') camera.wait_recording(60) camera.stop_recording() finally: connection.close() client_socket.close()
2、服務端負責接收視頻數據並實時顯示,代碼如下:
#-*- coding:utf-8 -*- #接收樹莓派發送的視頻數據,並通過vlc播放器播放 import socket import subprocess #創建一個socket連接 server_socket = socket.socket() #綁定所有端口 server_socket.bind(('0.0.0.0',8000)) server_socket.listen(0) #接收單個連接,創建類似文件對象輸出 connection = server_socket.accept()[0].makefile('rb') try: #在命令行調用vlc播放器 cmdline = ['vlc','--demux','h264','-'] #創建一個進程 player = subprocess.Popen(cmdline,stdin=subprocess.PIPE) while True: #重復讀1024個字節數據,寫入媒體播放器 data = connection.read(1024) if not data: break player.stdin.write(data) finally: connection.close() server_socket.close() player.terminate()
在vlc上播放實時視頻時,有2秒左右的延時,而且畫面有馬賽克的情況,效果比較差。