回到首页 返回首页
回到顶部 回到顶部
返回上一页 返回上一页

【FireBeetle 2 ESP32-C5】API 连接与本地图像识别 简单

头像 无垠的广袤 2025.10.03 45 1

【FireBeetle 2 ESP32-C5】API 连接与本地图像识别

本文介绍了 FireBeetle 2 ESP32-C5 开发套件基于网络 HTTP 协议 API 实现本地图像识别的项目设计。

项目介绍

准备工作:包括开发板固件烧录、模型下载、Python 库部署等;

流程图:包括开发板代码和网页服务器代码对应的流程图;

工程代码:包括开发板板端执行代码、网页服务器端代码等;

工程测试:包括程序运行、图片上传、识别结果查看等;

准备工作

下载 YOLOv8n.pt 模型,或程序自动从 GitHub 网站下载;

开发板烧录 MicroPython 固件;

电脑安装 Thonny IDE 软件,用来调试板端程序;

电脑安装 Python 软件,并部署所需库函数,如 opencv-python 等,便于模型识别与调用。

详见:【LattePanda Mu 开发套件】AI 视觉应用开发——物体识别- Makelog(造物记) .

流程图

 

网页服务器代码流程图

flowchart_http_api_server.jpeg

 

ESP32-C5 代码流程图

 

flowchart_http_server_api_or_esp32_mpy.jpeg

 

工程代码

包括 ESP32-C5 代码、网页服务器执行代码两部分。

ESP32-C5 代码

打开 Thonny IDE 软件,新建 api_object_recognition.py 工程文件,并添加如下代码

 

# ------ ESP32-C5  one-shot send local JPG to YOLO server ----------
import network
import urequests
import sys

# ---------- Wi-Fi ----------
SSID = "xxx"
PWD  = "xxx"
SERVER = "http://192.168.31.101:5000/detect"

sta = network.WLAN(network.STA_IF)
sta.active(True)
sta.connect(SSID, PWD)
while not sta.isconnected():
    pass
print("Wi-Fi ok:", sta.ifconfig()[0])

# ---------- send target picture ----------
LOCAL_JPG = "desktop.jpg"

with open(LOCAL_JPG, "rb") as f:
    jpg = f.read()

boundary = "123456"
hdr  = f"--{boundary}\r\n"
hdr += f'Content-Disposition: form-data; name="image"; filename="{LOCAL_JPG}"\r\n'
hdr += "Content-Type: image/jpeg\r\n\r\n"
end  = f"\r\n--{boundary}--\r\n"
body = hdr.encode() + jpg + end.encode()

try:
    rsp = urequests.post(SERVER,
                         data=body,
                         headers={"Content-Type": f"multipart/form-data; boundary={boundary}"})
    data = rsp.json()
    print("objects:", data["objects"])
    print("result file:", data["result_file"])
except Exception as e:
    print("err:", e)

# ---------- finish ----------
print("done – program ends")
sys.exit()

 

保存代码;

 

网页服务器代码

在模型文件上级目录创建 yolo_http_server.py 文件,添加如下代码

 

"""
YOLOv8 HTTP inference server
POST /detect  →  multipart JPEG upload
GET  /last    →  shows last annotated image in browser
"""
import os
import uuid
import time
from pathlib import Path
from flask import Flask, request, jsonify, send_file
import cv2
from ultralytics import YOLO

app = Flask(__name__)

# ---------- config -------------------------------------------------
MODEL_PATH   = "models/yolov8n.pt"   # will auto-download first run
STORAGE_DIR  = Path("img")        # same folder you used before
STORAGE_DIR.mkdir(exist_ok=True)
ALLOWED_EXT  = {".jpg", ".jpeg", ".png"}

# ---------- warm-up model once -------------------------------------
print("Loading YOLOv8 model …")
model = YOLO(MODEL_PATH)
print("Model ready.")

# ---------- helpers ------------------------------------------------
def save_upload(multipart_file):
    """store original file and return Path object"""
    ext = Path(multipart_file.filename).suffix.lower()
    if ext not in ALLOWED_EXT:
        raise ValueError("Only .jpg .jpeg .png allowed")
    name = f"{int(time.time()*1000)}_{uuid.uuid4().hex[:8]}{ext}"
    path = STORAGE_DIR / name
    multipart_file.save(path)
    return path

def infer_and_annotate(image_path: Path):
    """run YOLOv8 + plot; return (results_list, annotated_cv2_image)"""
    img_bgr = cv2.imread(str(image_path))
    if img_bgr is None:
        raise RuntimeError("Cannot decode image")

    results = model(img_bgr)          # ultralytics engine
    annotated_bgr = results[0].plot()  # boxes + labels drawn

    # build serialisable list
    objects = []
    for box in results[0].boxes:
        cls   = int(box.cls)
        conf  = float(box.conf)
        xyxy  = box.xyxy[0].tolist()  # [x1,y1,x2,y2]
        objects.append({
            "label": model.names[cls],
            "conf":  round(conf, 3),
            "box":   [int(x) for x in xyxy]
        })
    return objects, annotated_bgr

# ---------- routes -------------------------------------------------
@app.route("/detect", methods=["POST"])
def detect():
    if "image" not in request.files:
        return jsonify(error="missing 'image' multipart field"), 400

    try:
        original_path = save_upload(request.files["image"])
        objects, annotated = infer_and_annotate(original_path)

        # save annotated image side-by-side
        annotated_name = original_path.stem + "_yolo.jpg"
        annotated_path = STORAGE_DIR / annotated_name
        cv2.imwrite(str(annotated_path), annotated)

        return jsonify(
            objects=objects,
            result_file=annotated_name,
            original_file=original_path.name
        )
    except Exception as e:
        return jsonify(error=str(e)), 500

@app.route("/last")
def last_image():
    """convenience: show most recent _yolo.jpg in browser"""
    files = sorted(STORAGE_DIR.glob("*_yolo.jpg"), key=os.path.getmtime, reverse=True)
    if not files:
        return "No annotated image yet", 404
    return send_file(files[0], mimetype="image/jpeg")

@app.route("/")
def root():
    return ("YOLOv8 inference server is running.
"
            "POST to /detect   (multipart JPEG)
"
            "GET  /last        (newest annotated image)")
# ---------- entry --------------------------------------------------
if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000, threaded=True)

 

保存代码;

 

工程测试

命令行终端进入网页服务器代码所在文件夹;

终端执行 python yolo_http_server.py 指令;

or_http_server.JPG

打开终端提示的网址 http://192.168.31.109:5000/ 显示界面如下

http_or_server_face.JPG

表明模型加载成功且正在运行;

运行 Thonny IDE 并连接开发板,将目标图片 desktop.jpg 传输至板端根目录;

img_board_file.JPG

运行 api_object_recognition.py 程序,终端输出 WiFi 连接和物体识别结果;

or_print_web_api.JPG

打开网页 http://192.168.31.109:5000/last 查看图片识别结果;

http_api_or_img.JPG

总结

本文介绍了 FireBeetle 2 ESP32-C5 开发 HTTP 协议 API 实现本地图像识别的项目设计,包括网页服务器工程代码、板端执行代码、工程测试流程、识别结果查看等,为相关产品的开发设计和快速应用提供了参考。

 


 

评论

user-avatar
  • 舞动的枫叶

    舞动的枫叶2025.10.03

    很棒的作品!ESP32-C5支持蓝牙和WiFi6无线通信,可以蓝牙连接手机,手机发送图片,由ESP32-C5作为转发器,通过WiFi上传图片到网页服务器完成识别~

    0