树莓派通过网络将拍摄的图片和视频发送给上位机
树莓派上安装的系统是不带图形界面的,不能直接查看拍摄的图形和视频,考虑通过网络将树莓派摄像头拍摄的图片和视频发送给其他电脑进行查看。
其中控制摄像头使用的是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秒左右的延时,而且画面有马赛克的情况,效果比较差。