程序代码篇---esp32视频流处理
文章目录
- 前言
- 一、ESP32摄像头设置
- 1.HTTP视频流(最常见)
- 2.RTSP视频流
- 3.MJPEG流
- 二、使用OpenCV读取视频流
- 1. 读取HTTP视频流
- 2. 读取RTSP视频流
- 三、使用requests库读取MJPEG流
- 四、处理常见问题
- 1. 连接不稳定或断流
- 2. 提高视频流性能
- 2.1降低分辨率
- 2.2跳过部分帧
- 五、使用FFmpeg作为后端
- 六、使用PyAV库(高级选项)
- 七、实际应用示例 - 视频流处理
- 八、注意事项
- 1.网络延迟
- 2.带宽限制
- 3.认证
- 4.编码格式
- 5.稳定性
前言
ESP32摄像头模块可以通过Wi-Fi提供视频流,通常使用RTSP或HTTP协议。下面将简单介绍如何使用Python读取和处理ESP32摄像头的视频流。
一、ESP32摄像头设置
在开始之前,确保你的ESP32摄像头已经正确配置并可以输出视频流。常见的ESP32摄像头流媒体方式有:
1.HTTP视频流(最常见)
通常地址为 http://[ESP32_IP]/video
或 http://[ESP32_IP]/stream
2.RTSP视频流
通常地址为 rtsp://[ESP32_IP]:554/mjpeg/1
3.MJPEG流
通常地址为 http://[ESP32_IP]/mjpeg/1
二、使用OpenCV读取视频流
1. 读取HTTP视频流
import cv2# ESP32摄像头的IP地址
esp32_ip = "192.168.1.100" # 替换为你的ESP32 IP
stream_url = f"http://{esp32_ip}/video"# 创建视频捕获对象
cap = cv2.VideoCapture(stream_url)# 设置缓冲区大小为1以减少延迟
cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)while True:ret, frame = cap.read()if not ret:print("无法获取视频流,尝试重新连接...")cap.release()cap = cv2.VideoCapture(stream_url)continue# 显示视频cv2.imshow('ESP32 Camera Stream', frame)# 按'q'退出if cv2.waitKey(1) & 0xFF == ord('q'):break# 释放资源
cap.release()
cv2.destroyAllWindows()
2. 读取RTSP视频流
import cv2esp32_ip = "192.168.1.100" # 替换为你的ESP32 IP
rtsp_url = f"rtsp://{esp32_ip}:554/mjpeg/1"cap = cv2.VideoCapture(rtsp_url)# 对于RTSP流,可能需要添加这些参数
cap.set(cv2.CAP_PROP_FPS, 30)
cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc(*'MJPG'))while True:ret, frame = cap.read()if not ret:print("RTSP流中断,尝试重新连接...")cap.release()cap = cv2.VideoCapture(rtsp_url)continuecv2.imshow('ESP32 RTSP Stream', frame)if cv2.waitKey(1) & 0xFF == ord('q'):breakcap.release()
cv2.destroyAllWindows()
三、使用requests库读取MJPEG流
对于MJPEG格式的视频流,可以使用requests库:
import cv2
import numpy as np
import requests
from io import BytesIOesp32_ip = "192.168.1.100" # 替换为你的ESP32 IP
stream_url = f"http://{esp32_ip}/mjpeg/1"# 创建请求会话
session = requests.Session()
stream = session.get(stream_url, stream=True)bytes_data = bytes()
for chunk in stream.iter_content(chunk_size=1024):bytes_data += chunka = bytes_data.find(b'\xff\xd8') # JPEG开始标记b = bytes_data.find(b'\xff\xd9') # JPEG结束标记if a != -1 and b != -1:jpg = bytes_data[a:b+2]bytes_data = bytes_data[b+2:]# 转换为numpy数组img = cv2.imdecode(np.frombuffer(jpg, dtype=np.uint8), cv2.IMREAD_COLOR)if img is not None:cv2.imshow('ESP32 MJPEG Stream', img)if cv2.waitKey(1) & 0xFF == ord('q'):breakcv2.destroyAllWindows()
session.close()
四、处理常见问题
1. 连接不稳定或断流
python
import time
def connect_to_stream(url, max_retries=5, retry_delay=1):
for i in range(max_retries):
cap = cv2.VideoCapture(url)
if cap.isOpened():
return cap
print(f"连接失败,尝试 {i+1}/{max_retries}…")
time.sleep(retry_delay)
return None
esp32_ip = “192.168.1.100”
stream_url = f"http://{esp32_ip}/video"
cap = connect_to_stream(stream_url)
if cap is None:
print(“无法连接到摄像头”)
exit()
while True:
ret, frame = cap.read()
if not ret:
print(“视频流中断,尝试重新连接…”)
cap.release()
cap = connect_to_stream(stream_url)
if cap is None:
break
continue
cv2.imshow('Stream', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):break
cap.release()
cv2.destroyAllWindows()
2. 提高视频流性能
2.1降低分辨率
def resize_frame(frame, scale_percent=50):width = int(frame.shape[1] * scale_percent / 100)height = int(frame.shape[0] * scale_percent / 100)return cv2.resize(frame, (width, height))
2.2跳过部分帧
frame_counter = 0
frame_skip = 2 # 每3帧处理1帧while True:ret, frame = cap.read()if not ret:# 处理断流...continueframe_counter += 1if frame_counter % (frame_skip + 1) != 0:continue# 处理帧frame = resize_frame(frame, 50)cv2.imshow('Optimized Stream', frame)if cv2.waitKey(1) & 0xFF == ord('q'):break
五、使用FFmpeg作为后端
对于某些ESP32摄像头流,使用FFmpeg作为后端可能更稳定:import cv2
import subprocessesp32_ip = "192.168.1.100"
stream_url = f"http://{esp32_ip}/video"# 使用FFmpeg作为视频捕获后端
command = ['ffmpeg','-i', stream_url,'-f', 'image2pipe','-pix_fmt', 'bgr24','-vcodec', 'rawvideo', '-'
]pipe = subprocess.Popen(command, stdout=subprocess.PIPE, bufsize=10**8)while True:# 读取原始视频数据raw_image = pipe.stdout.read(640*480*3)# 转换为numpy数组image = np.frombuffer(raw_image, dtype='uint8')if image.size == 0:breakimage = image.reshape((480, 640, 3))cv2.imshow('FFmpeg Stream', image)if cv2.waitKey(1) & 0xFF == ord('q'):breakpipe.terminate()
cv2.destroyAllWindows()
六、使用PyAV库(高级选项)
import av
import cv2
import numpy as npesp32_ip = "192.168.1.100"
stream_url = f"http://{esp32_ip}/video"container = av.open(stream_url)for frame in container.decode(video=0):img = frame.to_ndarray(format='bgr24')cv2.imshow('PyAV Stream', img)if cv2.waitKey(1) & 0xFF == ord('q'):breakcontainer.close()
cv2.destroyAllWindows()
七、实际应用示例 - 视频流处理
import cv2
import numpy as npdef process_frame(frame):"""帧处理函数示例"""# 转换为灰度图gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)# 边缘检测edges = cv2.Canny(gray, 100, 200)# 转换为3通道以便与原图拼接edges = cv2.cvtColor(edges, cv2.COLOR_GRAY2BGR)# 水平拼接原图和边缘图processed = cv2.hconcat([frame, edges])return processedesp32_ip = "192.168.1.100"
stream_url = f"http://{esp32_ip}/video"cap = cv2.VideoCapture(stream_url)while True:ret, frame = cap.read()if not ret:print("视频流中断")break# 处理帧result = process_frame(frame)# 显示FPSfps = cap.get(cv2.CAP_PROP_FPS)cv2.putText(result, f"FPS: {fps:.1f}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)cv2.imshow('Processed ESP32 Stream', result)if cv2.waitKey(1) & 0xFF == ord('q'):breakcap.release()
cv2.destroyAllWindows()
八、注意事项
1.网络延迟
网络延迟:Wi-Fi视频流通常有100-500ms的延迟
2.带宽限制
带宽限制:高清视频流可能需要较大的带宽
3.认证
认证:如果ESP32摄像头需要认证,URL格式为 http://username:password@ip/video
4.编码格式
编码格式:确认ESP32摄像头的视频编码格式**(通常是MJPEG)**
5.稳定性
稳定性:无线连接可能不稳定,需要添加重连逻辑
通过以上方法,你可以灵活地使用Python读取和处理ESP32摄像头的视频流,并根据需要进行各种图像处理和分析。