基于ESP32_Cam和Python的实时图像显示
很早一段时间之前入手了一个ESP32_Cam即Camera摄像头。但是一直没有时间去研究这个模块,难得最近空下来了所以本期决定使用ESP32_Cam去实现一个实时视频传输的效果。

ESP32_Cam如上图所示,淘宝上加上烧录器(一个串口转CH340)总计30+,使用的是经典的OV2640摄像头。
官方Demo使用

组装好之后,我们打开Arduino IDE,烧入ESP32的摄像头例程。并且修改相应的设置。


使用该实例的代码,需要注意的是,我们需要注释掉第17行,解开第24行的注释,之后烧入我们的代码。


修改WIFI连接的账号还有密码,之后开启电脑热点(或者自己家的WIFI)保证处于同一个局域网中。

我们打开Start Stream来开启我们的流式传输,效果如下打开串口,输入这个浏览器地址就可以使用ESP32的官方Demo啦。

代码优化
为了更好的帧率以及拓展,我们决定使用Python来实现数据的接收以及显示。
首先我们需要修改我们的代码。

将官方例程中的这两个函数注释掉,我们在Loop循环中添加我们的逻辑。
void loop() {
camera_fb_t *fb = esp_camera_fb_get();//获取图像
if (fb == nullptr) {
Serial.println("Camera capture failed");
}
else
{
Serial.println("Camera capture OK");
//使用TCP协议上传
WiFiClient client;
client.connect("192.168.137.1", 8081);//上传地址的端口号
client.write(fb->buf, fb->len);//上传字节数组和长度
}
esp_camera_fb_return(fb);//返回帧
}
为此ESP32的代码编写完成。
之后我们需要编辑Python部分的代码,关于Python的环境安装可以看往期的公众号。

需要导入Opencv库来显示我们的图像。
#该线程用于图像显示
def display_image():
global shared_image
while True:
if shared_image is not None:
for (x, y, w, h) in faces:
cv2.rectangle(shared_image, (x, y), (x + w, y + h), (0, 255, 0), 2)
cv2.imshow('Received Image with Face Detection', shared_image)
cv2.waitKey(1)
# 服务器地址和端口
host = '0.0.0.0' #0.0.0.0则是设置监听所有可用地址
port = 8081
# 创建一个TCP套接字
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 将套接字绑定到指定地址和端口
server_socket.bind((host, port))
# 开始监听连接,允许最大连接数为1
server_socket.listen(1)
print(f"Listening on {host}:{port}...")
# 创建一个线程用于图像显示
display_thread = threading.Thread(target=display_image)
display_thread.daemon = True # 设置为守护线程,主程序退出时线程也会退出
display_thread.start()
while True:
# 接受客户端连接
client_socket, client_address = server_socket.accept()
print(f"Accepted connection from {client_address}")
# 接收数据并保存到内存中
data = b""
while True:
packet = client_socket.recv(4096)
if not packet:
break
data += packet
# 将接收到的二进制数据转换为NumPy数组
image_array = np.frombuffer(data, dtype=np.uint8)
# 解码图像
with image_lock:
shared_image = cv2.imdecode(image_array, cv2.IMREAD_COLOR)
print("Image received and sent to display.")
# 关闭连接
client_socket.close()
之后运行以下我们的代码,可以看到虽然运行起来还不是很流畅,但是也可以勉强接受,相比官方的几秒一帧已经有很大的改善了。


登录 或 注册 后才可以进行评论哦!