当前位置: 首页 > news >正文

【工业树莓派CM0 Dev Board】AI视觉应用部署方案:人脸检测

【工业树莓派CM0 Dev Board】AI视觉应用部署方案:人脸检测

本文介绍了树莓派 CM0 Dev Board 的实现 AI 视觉应用方案:人脸检测的项目设计,包括准备工作、Harr 级联识别、ONNX 模型识别、流程图、关键代码以及效果演示等。

项目介绍

  • 准备工作:包括所需 Python 环境以及软件包的安装部署等;
  • Haar 级联:使用 OpenCV 自带的数据库实现 Haar 级联检测人脸;
  • ONNX 模型:使用 RetinaFace 、YuNet 等轻量化 ONNX模型实现人脸检测的板端推理。

准备工作

系统安装及环境搭建详见:【工业树莓派CM0 Dev Board】介绍、镜像烧录、系统测试 .

硬件连接

在这里插入图片描述

库安装

执行指令 sudo apt install python3-opencv 安装 OpenCV

在这里插入图片描述

执行指令 sudo apt install opencv-data 补全 OpenCV 库

在这里插入图片描述

或 下载 模型文件至本地 ./model 文件;

mkdir model
cd model
wget https://github.com/opencv/opencv/blob/4.x/data/haarcascades/haarcascade_frontalface_default.xml

流程图

开始
读取图片
等比缩放
转灰度
Haar级联检测
是否有人脸?
回显原图
映射原图坐标
绘制边框
弹窗显示
结束

代码

执行 touch fd_xml.py 指令新建文件,并使用 nano 文本编辑器添加如下代码

import cv2
from pathlib import Pathdef detect_faces(image_path: str,max_side: int = 1280,padding: float = 0.05) -> None:"""零切割人脸检测:param image_path:  原图路径:param max_side:    检测前最长边上限(越大越慢,越小越可能漏):param padding:     矩形向外扩的边距比例(0.05 = 5 %)"""# 1. 读图img = cv2.imread(image_path)if img is None:raise FileNotFoundError(image_path)h0, w0 = img.shape[:2]# 2. 等比例缩放scale = min(1.0, max_side / max(h0, w0))if scale < 1.0:img_small = cv2.resize(img, (int(w0 * scale), int(h0 * scale)),interpolation=cv2.INTER_LINEAR)else:img_small = imgh1, w1 = img_small.shape[:2]# 3. 灰度 + 检测gray = cv2.cvtColor(img_small, cv2.COLOR_BGR2GRAY)cascade_path = "/usr/share/opencv4/haarcascades/haarcascade_frontalface_default.xml"#cascade_path = Path(cv2.__file__).parent / "data" / "haarcascade_frontalface_default.xml"face_cascade = cv2.CascadeClassifier(cascade_path)#face_cascade = cv2.CascadeClassifier(str(cascade_path))faces = face_cascade.detectMultiScale(gray,scaleFactor=1.1,minNeighbors=7,minSize=(60, 60))# 4. 映射回原图 + 边缘修正for (x, y, w, h) in faces:# 映射回原图坐标x = int(x / scale)y = int(y / scale)w = int(w / scale)h = int(h / scale)# 外扩边距dw = int(w * padding)dh = int(h * padding)x = max(0, x - dw)y = max(0, y - dh)x2 = min(w0, x + w + 2 * dw)y2 = min(h0, y + h + 2 * dh)cv2.rectangle(img, (x, y), (x2, y2), (0, 255, 0), 2)# 5. 显示max_h = 500                        # 高度不超过 500 pxif h0 > max_h:scale_show = max_h / h0new_w = int(w0 * scale_show)show_img = cv2.resize(img, (new_w, max_h))else:show_img = imgcv2.namedWindow("Face Detection", cv2.WINDOW_AUTOSIZE)cv2.imshow("Face Detection", show_img)cv2.waitKey(0)cv2.destroyAllWindows()if __name__ == "__main__":detect_faces(r"./img/friends.jpg")

保存代码;

效果

终端执行 python fd_xml.py 弹窗显示人脸检测结果;

在这里插入图片描述

ONNX 模型

Open Neural Network Exchange (ONNX) 是一个开放的生态系统,为 AI 开发人员提供支持 随着项目的发展选择正确的工具。

在这里插入图片描述

ONNX 为 AI 模型(包括深度学习和传统 ML)提供开源格式。它定义了一个可扩展的计算图模型,以及内置运算符和标准的定义 数据类型。

详见:onnx/onnx: Open standard for machine learning interoperability .

这里使用 ONNX 模型实现人脸检测。

准备工作

库安装

安装解析 ONNX 模型所需的 onnxruntime 库,终端执行

sudo apt install python3-pip
sudo pip3 install onnxruntime --break-system-packages

安装完成

在这里插入图片描述

模型下载

可实现人脸检测的模型有许多,这里选择轻量化的 RetinaFace 模型。

新建 model 文件夹,并拉取训练好的 ONNX 模型,终端执行代码

mkdir model
cd model
wget https://github.com/Linzaer/Ultra-Light-Fast-Generic-Face-Detector-1MB/blob/master/models/onnx/version-RFB-320.onnx

也可获取更多模型

在这里插入图片描述

详见:Linzaer/Ultra-Light-Fast-Generic-Face-Detector-1MB .

流程图

开始
读取图片
调整尺寸
归一化
ONNX 推理
输出检测结果
置信度 > 0.7 ?
丢弃
选框坐标
NMS
选框自适应
画框+置信度
弹窗显示
结束

代码

执行 touch fd_onnx.py 指令新建文件,并使用 nano 文本编辑器添加如下代码

import cv2
import numpy as np
import onnxruntime as ort
import osdef correct_face_detection(model_path, image_path):"""正确的UltraFace检测实现"""# 加载模型session = ort.InferenceSession(model_path, providers=['CPUExecutionProvider'])input_name = session.get_inputs()[0].name# 读取图片image = cv2.imread(image_path)if image is None:print(f"无法读取图片: {image_path}")return []orig_h, orig_w = image.shape[:2]print(f"原始图片尺寸: {orig_w}x{orig_h}")# 预处理resized = cv2.resize(image, (320, 240))input_tensor = resized.astype(np.float32) / 255.0input_tensor = input_tensor.transpose(2, 0, 1)input_tensor = np.expand_dims(input_tensor, axis=0)# 推理outputs = session.run(None, {input_name: input_tensor})scores, boxes = outputsprint(f"输出形状 - scores: {scores.shape}, boxes: {boxes.shape}")# 处理检测结果 - 使用更严格的过滤all_faces = []for i in range(scores.shape[1]):face_score = scores[0, i, 1]  # 人脸置信度# 提高置信度阈值,减少误检if face_score > 0.9:  # 从0.7提高到0.9box = boxes[0, i]# UltraFace输出是相对坐标 [0,1] 范围x1 = int(box[0] * orig_w)y1 = int(box[1] * orig_h)x2 = int(box[2] * orig_w)y2 = int(box[3] * orig_h)width = x2 - x1height = y2 - y1# 更严格的尺寸过滤if width > 40 and height > 40 and width < 300 and height < 300:all_faces.append([x1, y1, x2, y2, face_score])print(f"高质量候选框: {len(all_faces)} 个")# 改进的NMS去重def nms(boxes, scores, iou_threshold=0.4):"""非极大值抑制"""if len(boxes) == 0:return []# 按分数排序order = np.argsort(scores)[::-1]keep = []while order.size > 0:i = order[0]keep.append(i)if order.size == 1:break# 计算IoUxx1 = np.maximum(boxes[i, 0], boxes[order[1:], 0])yy1 = np.maximum(boxes[i, 1], boxes[order[1:], 1])xx2 = np.minimum(boxes[i, 2], boxes[order[1:], 2])yy2 = np.minimum(boxes[i, 3], boxes[order[1:], 3])w = np.maximum(0.0, xx2 - xx1)h = np.maximum(0.0, yy2 - yy1)inter = w * harea_i = (boxes[i, 2] - boxes[i, 0]) * (boxes[i, 3] - boxes[i, 1])area_other = (boxes[order[1:], 2] - boxes[order[1:], 0]) * (boxes[order[1:], 3] - boxes[order[1:], 1])iou = inter / (area_i + area_other - inter)# 保留IoU小于阈值的框inds = np.where(iou <= iou_threshold)[0]order = order[inds + 1]return keepif all_faces:# 转换为numpy数组以便NMS计算boxes_array = np.array([[x1, y1, x2, y2] for x1, y1, x2, y2, score in all_faces])scores_array = np.array([score for x1, y1, x2, y2, score in all_faces])# 应用NMSkeep_indices = nms(boxes_array, scores_array, 0.4)final_faces = []for idx in keep_indices:x1, y1, x2, y2, score = all_faces[idx]final_faces.append([x1, y1, x2, y2, score])print(f"去重后剩余 {len(final_faces)} 张人脸")# 显示结果 - 简化显示逻辑result_image = image.copy()# 检查图片数据print(f"结果图片信息: shape={result_image.shape}, dtype={result_image.dtype}")print(f"像素值范围: {result_image.min()} - {result_image.max()}")# 如果图片是全黑的,重新创建if result_image.max() == 0:print("检测到黑色图片,重新创建...")result_image = image.copy()# 绘制人脸框和置信度for i, (x1, y1, x2, y2, score) in enumerate(final_faces):color = (0, 255, 0)  # 绿色thickness = 2# 绘制矩形框cv2.rectangle(result_image, (x1, y1), (x2, y2), color, thickness)# 简化标签显示label = f"{score:.3f}"cv2.putText(result_image, label, (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 1)print(f"人脸 {i+1}: 位置({x1}, {y1}, {x2-x1}, {y2-y1}), 置信度: {score:.3f}")# 显示图片 - 修复显示问题try:# 检查图片是否有效if result_image is not None and result_image.size > 0 and result_image.max() > 0:# 创建窗口并显示window_name = f"人脸检测结果 - {len(final_faces)} faces"cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)cv2.imshow(window_name, result_image)print("显示检测结果中... 按任意键关闭窗口")cv2.waitKey(0)cv2.destroyAllWindows()else:print("错误: 结果图片数据无效或全黑")# 显示原图作为备用cv2.imshow("原始图片", image)cv2.waitKey(0)cv2.destroyAllWindows()except Exception as e:print(f"显示图片时出错: {e}")# 保存图片到文件作为备用output_path = "debug_result.jpg"cv2.imwrite(output_path, result_image)print(f"结果已保存到: {output_path}")return final_faceselse:print("未检测到人脸")# 显示原图cv2.imshow("原始图片", image)cv2.waitKey(0)cv2.destroyAllWindows()return []def main():model_path = "./model/version-slim-320.onnx"image_path = "./img/friends.jpg"if not os.path.exists(model_path):print(f"模型文件不存在: {model_path}")returnif not os.path.exists(image_path):print(f"图片文件不存在: {image_path}")returnprint("开始人脸检测...")faces = correct_face_detection(model_path, image_path)if faces:print(f"\n 最终检测到 {len(faces)} 张人脸")else:print(f"\n 未检测到人脸")if __name__ == "__main__":main()

保存代码;

效果

终端执行 python fd_onnx.py 弹窗显示人脸检测结果;

在这里插入图片描述

同时终端输出识别信息

在这里插入图片描述

简化

为了更加轻量化,简化上述 ONNX 模型处理代码,如下

#!/usr/bin/env python3
import cv2
import numpy as np
import onnxruntime as ort
from pathlib import PathMODEL_PATH = "model/version-slim-320.onnx"   # 240×320 模型
IMG_PATH   = "img/friends.jpg"# ---------- 1. 加载模型 ----------
sess = ort.InferenceSession(MODEL_PATH, providers=['CPUExecutionProvider'])
in_name = sess.get_inputs()[0].name   # [1,3,240,320]
out_score = sess.get_outputs()[0].name  # [1,N,2]
out_box   = sess.get_outputs()[1].name  # [1,N,4]  x1,y1,x2,y2 归一化# ---------- 2. 读图 ----------
img0 = cv2.imread(IMG_PATH)
if img0 is None: raise FileNotFoundError(IMG_PATH)
h0, w0 = img0.shape[:2]# ---------- 3. 预处理(exact 240×320 + FP32) ----------
blob = cv2.resize(img0, (320, 240))          # 宽 320,高 240
blob = blob.astype(np.float32) / 255.0
blob = blob.transpose(2, 0, 1)[None]         # NCHW# ---------- 4. 推理 ----------
scores, boxes = sess.run([out_score, out_box], {in_name: blob})
scores = np.squeeze(scores)[:, 1]            # 人脸置信度 [N]
boxes  = np.squeeze(boxes)                   # 归一化框 [N,4]# ---------- 5. NMS 去重 + 自适应框 ----------
conf_thres = 0.7
nms_iou    = 0.3
rel_size   = 0.12                            # 框边长 = 0.12×图像宽# 先过滤低置信
keep = scores > conf_thres
boxes, scores = boxes[keep], scores[keep]# OpenCV NMSBoxes 需要 [x,y,w,h] + 分数
nms_boxes = []
for b in boxes:x1, y1, x2, y2 = bw_box = int((x2 - x1) * w0)              # 真实像素宽h_box = int((y2 - y1) * h0)              # 真实像素高nms_boxes.append([int(x1 * w0), int(y1 * h0), w_box, h_box])if nms_boxes:indices = cv2.dnn.NMSBoxes(nms_boxes, scores.tolist(), score_threshold=conf_thres, nms_threshold=nms_iou)for idx in indices.flatten():x, y, w, h = nms_boxes[idx]# 自适应框:以检测框为中心,用相对尺寸画框cx = x + w // 2cy = y + h // 2side = int(rel_size * w0)              # 统一边长x1 = max(0, cx - side // 2)y1 = max(0, cy - side // 2)x2 = min(w0, cx + side // 2)y2 = min(h0, cy + side // 2)cv2.rectangle(img0, (x1, y1), (x2, y2), (0, 255, 0), 2)cv2.putText(img0, f"{scores[idx]:.2f}", (x1, max(5, y1 - 5)),cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)# ---------- 6. 弹窗 ----------
cv2.imshow("Face-Detection-ONNX", img0)
cv2.waitKey(0)
cv2.destroyAllWindows()

保存代码;

效果
  • 运行代码,可更快速地获得人脸检测效果

在这里插入图片描述

  • 更多效果

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

相关模型详见:GitHub - xuguowong/rknn_model_zoo-RKNN .

总结

本文介绍了树莓派 CM0 Dev Board 的实现 AI 视觉应用方案:人脸检测的项目设计,包括准备工作、Harr 级联识别、ONNX 模型识别、流程图、关键代码以及效果演示等,为相关产品的开发设计和快速应用提供了参考。

http://www.dtcms.com/a/533698.html

相关文章:

  • 网站建设报价单表格网站文章更新时间
  • 摄影网站源代码wordpress底部怎么改
  • 深圳设计功能网站免费搭建wordpress
  • 海南网站制作精准数据营销方案
  • 网站技术建设维护技术论文如何推广网店
  • ros2 launch 常用python模块详细使用范例
  • Spring AOP XML配置实战:传统方式的进阶应用与对比分析(含核心关键词)
  • 映像星球官网网页版入口 - 最新影视资源高清在线观看平台
  • 如何评判一个网站建设的怎么样怎么用html做移动网站吗
  • 苏州网站建设网站开发庐江网站建设
  • 1.6 大数据方法论与实践指南-数据治理工具
  • 基于python大数据的台风灾害分析及预测系统
  • 城乡住房建设网站手机网站最小宽度
  • 华为OD算法开发指导-比赛的冠亚季军
  • 算法:矩形面积II
  • app怎么查网站备案计算机网站php设计代做
  • 晋中公司做网站装修效果图软件app哪个好
  • yum安装配置
  • 网站标题算关键词优化吗吴忠北京网站建设
  • 做ps网页设计的网站有哪些wordpress配置文件路径
  • 笔试强训(九)
  • 线程池ThreadPoolExecutor
  • 合同的系统培训约定
  • cf租号网站怎么做的河南建设安全协会网站
  • 建设的网站别人登录密码公司企业邮箱号
  • 电商网站怎样做天津网站建设哪个好
  • 长沙网站建设接单wordpress站点名没有更改
  • 手机wap网站建设一套完整的app 开发流程
  • 在线制作wap网站中牟建设工程信息网站
  • K8S--标签(labels)和选择器(selectors)的作用