树莓派无线WiFi采集摄像头数据的三种方法
本帖最后由 不脱发的程序猿 于 2023-12-22 09:15 编辑1、方法一:Python OpenCV
使用Python和OpenCV实现树莓派/PC实时摄像头数据共享,主要分为服务器和客户端两部分。服务器Demo如下:<font color="#000000">#服务器端
import socket
import threading
import struct
import time
import cv2
import numpy
class Carame_Accept_Object:
def __init__(self,S_addr_port=("",8880)):
self.resolution=(640,480) #分辨率
self.img_fps=15 #每秒传输多少帧数
self.addr_port=S_addr_port
self.Set_Socket(self.addr_port)
#设置套接字
def Set_Socket(self,S_addr_port):
self.server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
self.server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) #端口可复用
self.server.bind(S_addr_port)
self.server.listen(5)
#print("the process work in the port:%d" % S_addr_port)
def check_option(object,client):
#按格式解码,确定帧数和分辨率
info=struct.unpack('lhh',client.recv(8))
if info>888:
object.img_fps=int(info)-888 #获取帧数
object.resolution=list(object.resolution)
# 获取分辨率
object.resolution=info
object.resolution=info
object.resolution = tuple(object.resolution)
return 1
else:
return 0
def RT_Image(object,client,D_addr):
if(check_option(object,client)==0):
return
camera=cv2.VideoCapture(0) #从摄像头中获取视频
img_param=#设置传送图像格式、帧数
while(1):
time.sleep(0.1) #推迟线程运行0.1s
_,object.img=camera.read()#读取视频每一帧
object.img=cv2.resize(object.img,object.resolution) #按要求调整图像大小(resolution必须为元组)
_,img_encode=cv2.imencode('.jpg',object.img,img_param)#按格式生成图片
img_code=numpy.array(img_encode) #转换成矩阵
object.img_data=img_code.tostring() #生成相应的字符串
try:
#按照相应的格式进行打包发送图片
client.send(struct.pack("lhh",len(object.img_data),object.resolution,object.resolution)+object.img_data)
except:
camera.release() #释放资源
return
if __name__ == '__main__':
camera=Carame_Accept_Object()
while(1):
client,D_addr=camera.server.accept()
clientThread=threading.Thread(None,target=RT_Image,args=(camera,client,D_addr,))
clientThread.start()</font>客户端Demo如下:<font color="#000000">#客户端
import socket
import cv2
import threading
import struct
import numpy
class Camera_Connect_Object:
def __init__(self,D_addr_port=["",8880]):
self.resolution=
self.addr_port=D_addr_port
self.src=888+15 #双方确定传输帧数,(888)为校验值
self.interval=0 #图片播放时间间隔
self.img_fps=100 #每秒传输多少帧数
def Set_socket(self):
self.client=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
self.client.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
def Socket_Connect(self):
self.Set_socket()
self.client.connect(self.addr_port)
print("IP is %s:%d" % (self.addr_port,self.addr_port))
def RT_Image(self):
#按照格式打包发送帧数和分辨率
self.name=self.addr_port+" Camera"
self.client.send(struct.pack("lhh", self.src, self.resolution, self.resolution))
while(1):
info=struct.unpack("lhh",self.client.recv(8))
buf_size=info #获取读的图片总长度
if buf_size:
try:
self.buf=b"" #代表bytes类型
temp_buf=self.buf
while(buf_size): #读取每一张图片的长度
temp_buf=self.client.recv(buf_size)
buf_size-=len(temp_buf)
self.buf+=temp_buf #获取图片
data = numpy.fromstring(self.buf, dtype='uint8') #按uint8转换为图像矩阵
self.image = cv2.imdecode(data, 1) #图像解码
gray = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY)
cv2.imshow(self.name, self.image) #展示图片
except:
pass;
finally:
if(cv2.waitKey(10)==27): #每10ms刷新一次图片,按‘ESC’(27)退出
self.client.close()
cv2.destroyAllWindows()
break
def Get_Data(self,interval):
showThread=threading.Thread(target=self.RT_Image)
showThread.start()
if __name__ == '__main__':
camera=Camera_Connect_Object()
camera.addr_port=input("Please input IP:")
camera.addr_port=tuple(camera.addr_port)
camera.Socket_Connect()
camera.Get_Data(camera.interval)</font>运行效果还是比较流畅的,因为传输网络视频流,所以画质欠佳。https://img-blog.csdn.net/20180824154956643?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzM4MTA2OTIz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/702、方法二:Python picamera接下来使用Python和picamera实现树莓派/PC实时摄像头数据共享,主要也可分为服务器和客户端两部分。服务器(PC/树莓派)Demo如下:<font color="#000000">import numpy as np
import cv2
import socket
class VideoStreamingTest(object):
def __init__(self, host, port):
self.server_socket = socket.socket()
self.server_socket.bind((host, port))
self.server_socket.listen(0)
self.connection, self.client_address = self.server_socket.accept()
self.connection = self.connection.makefile('rb')
self.host_name = socket.gethostname()
self.host_ip = socket.gethostbyname(self.host_name)
self.streaming()
def streaming(self):
try:
print("Host: ", self.host_name + ' ' + self.host_ip)
print("Connection from: ", self.client_address)
print("Streaming...")
print("Press 'q' to exit")
# need bytes here
stream_bytes = b' '
while True:
stream_bytes += self.connection.read(1024)
first = stream_bytes.find(b'\xff\xd8')
last = stream_bytes.find(b'\xff\xd9')
if first != -1 and last != -1:
jpg = stream_bytes
stream_bytes = stream_bytes
image = cv2.imdecode(np.frombuffer(jpg, dtype=np.uint8), cv2.IMREAD_COLOR)
cv2.imshow('image', image)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
finally:
self.connection.close()
self.server_socket.close()
if __name__ == '__main__':
# host, port
h, p = "192.168.0.4", 8000
VideoStreamingTest(h, p)</font>客户端(树莓派)Demo如下:<font color="#000000">import io
import socket
import struct
import time
import picamera
# create socket and bind host
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(('192.168.2.104', 8000))
connection = client_socket.makefile('wb')
try:
with picamera.PiCamera() as camera:
camera.resolution = (320, 240) # pi camera resolution
camera.framerate = 15 # 15 frames/sec
time.sleep(2) # give 2 secs for camera to initilize
start = time.time()
stream = io.BytesIO()
# send jpeg format video stream
for foo in camera.capture_continuous(stream, 'jpeg', use_video_port = True):
connection.write(struct.pack('<L', stream.tell()))
connection.flush()
stream.seek(0)
connection.write(stream.read())
if time.time() - start > 600:
break
stream.seek(0)
stream.truncate()
connection.write(struct.pack('<L', 0))
finally:
connection.close()
client_socket.close()</font>无论是运行速度还是画质都是比较理想的。3、方法三:搭建网络摄像头搭建网络摄像头有两种方法。3.1、motion方式第一步:安装motion包 <font color="#000000">sudo apt-get install motion
</font>第二步:打开 motion daemon 守护进程,让它可以一直在后台运行<font color="#000000">sudo nano /etc/default/motion
#no修改成yes:
start_motion_daemon=yes</font>第三步:修改motion的配置文件<font color="#000000">sudo vim /etc/motion/motion.conf
#deamon off 改成 on
deamon on
#设置分辨率
width 800
height 600
#关闭 localhost 的限制
webcam_localhost off</font>第四步:运行 motion<font color="#000000">sudo motion</font>安装好USB摄像头,运行后重启树莓派,现在我们的摄像头已经变成了一台网络摄像头,在chrome浏览器下访问 http://:8081 即可看到摄像头当前拍摄的画面,需要注意有时候重启树莓派后网络摄像头可能未启动,所以需要重新运行motion。需要注意,第一种网络摄像头搭建方式不便于Android手机端的访问,所以这里我并未使用,这里仅做拓展讲解。PC端使用Python访问非常简单,直接使用OpenCv模块的VideoCapture()方法,输入网络摄像头URL即可。使用伪代码如下:<font color="#000000">'''
VideoCapture()中参数是0,表示打开电脑内置摄像头,
参数是1或2打开外部摄像头
参数是视频文件路径则打开视频文件
参数是URL打开网络摄像头
'''
cap = cv2.VideoCapture(URL)</font>3.2、MJPG-streamer方式
第一步:安装所需模块
<font color="#000000">sudo apt-get updatesudo
sudo apt-get install subversionsudo
sudo apt-get install libjpeg8-devsudo
sudo apt-get install imagemagicksudo
sudo apt-get install libv4l-devsudo
sudo apt-get install cmakesudo
sudo apt-get install git</font>第二步:git一个开源的project:MJPG-streamer
<font color="#000000">sudo git clone github.com/jacksonliam/mjpg-streamer.git
cd mjpg-streamer/mjpg-streamer-experimentalsudo
make all
sudo make install</font>git过程比较缓慢,大家可以耐心等待一段时间,等待100%后确认完成后再执行下一条命令,启动USB摄像头,指令如下:
<font color="#000000">./mjpg_streamer -i "./input_uvc.so" -o "./output_http.so -w ./www"</font>
这里有一点需要注意,配置USB摄像头和树莓派专用摄像头指令不一样,这里我配置的是USB摄像头,具体指令分别如下:
<font color="#000000">指令启动普通USB摄像头指令:
./mjpg_streamer -i "./input_uvc.so" -o "./output_http.so -w ./www"
启动树莓派专用摄像头RaspiCamera的指令:
./mjpg_streamer -i "./input_raspicam.so" -o "./output_http.so -w ./www"</font>并且使用树莓派专用摄像头需要开启专用摄像头配置的,输入指令如下:
<font color="#000000">sudo raspi-config</font>
点击摄像头使能开启即可。
以上就实现了全部的网络摄像头搭建。不过每次我们启动树莓派的时候还是需要手动去执行对应的命令,比较麻烦。那么接下来我们把当前项设置为一个系统自启动项。
第三步:设置自启动
cd到系统home目录下,新建一个sh可执行文件,输入如下命令即可:
<font color="#000000">sudo nano videoStart.sh</font>videoStart.sh文件中输入内容如下:
<font color="#000000">cd /home/pi/mjpg-streamer/mjpg-streamer-experimental/
./mjpg_streamer -i "./input_uvc.so" -d /dev/video0 -f 30 -r 1280x720 " -o
"./output_http.so -p 8080 -w ./www"</font>然后退出保存,最后记得再给个可执行权限,输入命令:
<font color="#000000">sudo chmod +x /home/pi/videoStart.sh</font>接着再创建一个目录,输入命令如下:
<font color="#000000">sudo mkdir .config/autostart</font>继续新建一个文件,输入对应命令如下:
<font color="#000000">sudo nano .config/autostart/my.desktop</font>文件内容如下:
<font color="#000000">
Type=shell
Exec=/home/pi/videoStart.sh</font>最后保存退出,这样每次开机就自动执行对应文件命令,省去了每次手动执行的麻烦。
第四步:测试
查看图像,在PC端打开浏览器,输入下面网址可以看到静态截图:
http://<树莓派IP>:8080/?action=snapshot
动态图像的这个地址在有的浏览器不太好使,可以使用下面这个网址:
http://<树莓派IP>:8080/javascript_simple.html
经过不断探索树莓派和PC视频数据通信“三部曲”到此结束,希望对小伙伴们有帮助~
很好的教程 赞 {:6_209:}
页:
[1]