局域网下实现高清低延时图传(一)

乘着空闲时间想做一个基于树莓派的监控,所以第一步就需要实现树莓派的摄像功能。
我这里用到的是树莓派盗版的摄像头(CSI接口摄像头),在淘宝上购买的价格也就在30RMB左右,很便宜。
个人博客:https://www.xiaokai1999.cn/

一、树莓派的摄像头操作

1.查看是否加载到了对应的video device设备:
ls /dev/


可以看到在里面没有看到vedio device,如果有的话会有vedioX(X={0,1,2,3…})

2.使能树莓派摄像头
sudo raspi-config

选择Interfacing Option,选中Select然后Enter进入;

接下来机会问你是否同意使能Pi camera,选择是然后会让你重启,选择 “是”

3、重启完之后,看看/dev下面是否存在摄像头设备:
ls -al /dev/ | grep video

如果有vedio device 就可以确定没有问题了。

4.拍摄照片
raspistill -o new.jpg
5.查看照片
xdg-open new.jpg

二、远程流视频传输1(python实现)

主机.py

import cv2
import socket
import numpy as np
cap = cv2.VideoCapture(0)

s = socket.socket()
img_param = [int(cv2.IMWRITE_JPEG_QUALITY), 95]#opencv 图像清晰度,帧数
port = 12345

s.bind(("192.168.229.129",port)) #绑定ip地址和端口
s.listen(5)						#等待客户机连接
c,addr = s.accept()				#接受客户机连接
while True:
    ret,frame = cap.read()
    frame = cv2.resize(frame, (320,230))
    print("连接地址:"+addr[0])
    _, img_encode = cv2.imencode('.jpg', frame, img_param)#opencv图像编码
    img_code = np.array(img_encode)
    img_data = img_code.tostring()#将数组格式转为字符串格式
    print(img_data)
    c.send(bytes(str(len(img_data)).ljust(16),encoding="utf8"))# 先发送数据的长度
    c.send(img_data)#再发送数据内容
    cv2.imshow("主机",frame)
    if cv2.waitKey(1)==27:
        c.close()
        break

客户机.py

import socket
import cv2
import numpy as np
import gzip

def recv_all(s,count):
    buf=bytes()
    while count:
        newbuf = s.recv(count)
        if not newbuf:return None
        buf+=newbuf
        count-=len(newbuf)
    return buf

s = socket.socket()
host = socket.gethostname()
port = 12345

while True:
    try:
        s.connect(("192.168.229.129",port))
    except:
        print("有错误")
    else:
        break
while True:
    data_len = recv_all(s,16)
    if len(data_len) == 16:
        stringData = recv_all(s, int(data_len))
        
        data = np.fromstring(stringData, dtype='uint8')
        
        tmp = cv2.imdecode(data, 1)  # 解码处理,返回mat图片
        
        img = cv2.resize(tmp, (320, 230))
        print(img)
        cv2.imshow('客户机', img)
    if cv2.waitKey(1) == 27:
        break
s.close()

效果

缺点

我程序不够完善,只实现了一发一接,能实现一发多接就完美了。但是这种方法会比较麻烦。

目前基于像处理使用市场上监控摄像头二次开发的案例很多,包括海康威视萤石开源摄像头;还有使用自带FIFO的OV7725或者OV7670摄像头模块结合stm32进行;还有OPENMV+OV7725的像处理方案;还有种使用MIPS架构的路由器芯片例如RT5350加免驱MPJG摄像头方案。每种方案价格都要达到50块以上,因为除了购买摄像头之外还有购买单片机,成本降不下来。 好消息的是,乐鑫科技推出的ESP32芯片能满足的需求,某宝基于该芯片出售的ESP32-cam摄像头模块能满足的需求,最低价格26块能买到手,性价比相当高,ESP32的运行速度和wifi速度都比ESP8266高。26块集成了ESP32最小系统板和OV2640摄像头和板载蓝牙wifi天线,买了也不亏,个好点的USB摄像头都不只这个价格了!为啥很少人使用呢?原因是入门比较麻烦。要是使用乐鑫idf去搭建开发,很麻烦,很难成功。 国内某个测评网有详细简介:https://post.smzdm.com/p/amm03d0d/ 模块的原理如下: 模块的全家福如下: 该模块在某宝很多家店铺有售,至于代工厂估计有很多家,但是根据原理就那么多IO口,资料都是通用的。 经过我自己个人努力,半年时间内掌握了ESP32技术,采用的是Arduino开发环境开发,很多情况下使用库函数来快速实现的功能。搭建开发环境也花了不少时间,后面根据个教程搭建成功了。 搭建视频链接:https://pan.baidu.com/s/1_xYw-Mg3LPb5vqMuVgiD2A 提取码:qdl2 搭建软件及素材:链接:https://pan.baidu.com/s/1eIES_hDWNgr5lZD4akP9Jw 提取码:zrwu 最后是我根据搭建环境自带的源码修改裁剪后的源码(在最后免费下载),该源码是我将三四个源码文件裁剪修改合成个源码文件,实现功能,代码精简利于阅读和学习,先进行配置和运行的说明: (1)整个工程就是个9kb的源码,名字叫websocket.ino文件,然后修改热点的名称和密码: (2)个CH340的USB转TTL电平的模块,某宝几块钱有卖的,按照下接上模块: 右边的模块就是USB转TTL模块,主要是用来下载程序和串口调试,左边接ESP32模块,右边接电脑。 个人建议给cam模块供电压5V在第张原理左下角的端口供电,免得电源不足,不要接错了! UoR就是RX端 UOT是TX端 这两个端跟CH340的RX、TX交叉连接,如示 将IO0端口与GND连接上之后就可以马上下载程序了: (3)用Arduino下载程序:(如果下载过程中出现失败,可以尝试按下模块的RST按键) (4)创建个热点,名称和密码都与(1)的步骤相同,让ESP32的wifi能连上,我就用笔记本电脑创建了个热点,然后打开串口Arduino监视器或者打开个串口调试助手,打开电脑与CH340链接的串口,拔掉cam模块中IO0与GND链接的线(第三张灰色的线,不断开就不能启动程序只能不断下载),再按下次cam模块的RST按钮松开,如下: 从上看出,RST按下时,第次程序运行不对,第二次运行正确了,打印出IP地址。右下角显示有设备连上热点。多试试几次就能成功的! (5)打开谷歌浏览器,输入网址串口打印的网址:172.25.139.2(个人具体IP看打印为准)就可以看到摄像头采集的视频流,相当流畅,如下所示:(其他浏览器可能失败) 由于摄像前面的保护膜没有撕掉,所以有点模糊,视频还是很流畅的。 总结:该项目演示了用ESP32作为个STA模式连上路由器或者笔记本热点,在同局域网环境下用浏览器登录ESP32的IP地址就可以收看ESP32摄像头采集下来的像信息。后期会陆续发布根据此源码升级成视频监控小车、视频监控智能控制摄像头、视频监控系统和手机客户端、stm单片机接收、机器人视觉人脸签到系统、远程MQTT手机app接收、局域网javaweb显示、等等项目,敬请期待。
### 使用Python实现WiFi输上位机 #### 、构建服务器端(树莓派) 基于提供的参考资料,可以使用`Picamera2`库配合HTTP协议搭建个简单的Web服务用于局域网内的视频流输。具体来说,GitHub上的[mjpeg_server.py](https://github.com/raspberrypi/picamera2/blob/main/tests/mjpeg_server.py)[^1]提供了个很好的起点。 此脚本创建了个多部分JPEG (M-JPEG) 流媒体服务器,允许客户端通过浏览器或其他支持该格式的应用程序访问来自Raspberry Pi Camera Module V2的实时视频馈送。对于希望调整性能参数的情况,比如改变帧率,可以在源代码中的指定位置进行修改[^2]。 ```python from picamera2 import Picamera2 import io import socketserver from threading import Condition from http import server class StreamingHandler(server.BaseHTTPRequestHandler): def do_GET(self): if self.path == '/': self.send_response(301) self.send_header('Location', '/index.html') self.end_headers() elif self.path == '/index.html': content = PAGE.encode('utf-8') self.send_response(200) self.send_header('Content-Type', 'text/html') self.send_header('Content-Length', len(content)) self.end_headers() self.wfile.write(content) elif self.path == '/stream.mjpg': self.send_response(200) self.send_header('Age', 0) self.send_header('Cache-Control', 'no-cache, private') self.send_header('Pragma', 'no-cache') self.send_header( 'Content-Type', 'multipart/x-mixed-replace; boundary=FRAME') self.end_headers() try: while True: with output.condition: output.condition.wait() frame = output.frame self.wfile.write(b'--FRAME\r\n') self.send_header('Content-Type', 'image/jpeg') self.send_header('Content-Length', len(frame)) self.end_headers() self.wfile.write(frame) self.wfile.write(b'\r\n') except Exception as e: logging.warning( 'Removed streaming client %s: %s', self.client_address, str(e)) else: self.send_error(404) self.end_headers() # ...省略其他初始化设置... ``` #### 二、开发客户端应用(Windows/Linux/MacOS) 针对不同操作系统平台下的PC作为接收端时,可以通过编写GUI应用程序来展示接收到的画面。这里以PyQt为例说明如何解析并显示从网络获取到的数据包: 根据给定的内容,在实际编程过程中加入异常处理机制能够有效提高系统的健壮性和用户体验感。特别是当涉及到IP地址和端口配置错误可能导致程序崩溃的情况下,应该给予用户友好的反馈信息,并引导其正确操作[^3]。 ```python import sys import cv2 import numpy as np from PyQt5.QtWidgets import QApplication, QLabel, QMainWindow from PyQt5.QtGui import QImage, QPixmap from PyQt5.QtCore import QTimer class MainWindow(QMainWindow): def __init__(self): super().__init__() # UI setup code here... timer = QTimer(self) timer.timeout.connect(self.update_frame) timer.start(33) def update_frame(self): ret, jpeg = cap.read() # Assume `cap` is a pre-initialized VideoCapture object. if not ret: return image = cv2.imdecode(np.frombuffer(jpeg, dtype=np.uint8), flags=cv2.IMREAD_COLOR) height, width, channel = image.shape bytesPerLine = 3 * width qImg = QImage(image.data, width, height, bytesPerLine, QImage.Format_RGB888).rgbSwapped() pixmap = QPixmap(qImg) label.setPixmap(pixmap) if __name__ == '__main__': app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec_()) ``` 请注意上述例子假设已经存在个有效的OpenCV `VideoCapture` 对象 (`cap`) 来读取远程主机发送过来的JPG编码后的字节串;而在真实场景下可能还需要额外的工作去建立TCP/UDP连接以及处理数据包重组等问题。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

锡城筱凯

你的鼓励是我创造的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值