很早一段时间之前入手了一个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()

之后运行以下我们的代码,可以看到虽然运行起来还不是很流畅,但是也可以勉强接受,相比官方的几秒一帧已经有很大的改善了。



嘉立创PCB
全部评论 默认 最新
已折叠部分评论 展开
没有更多啦~