三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

服务机器人访客视觉感知与人体特征分析系统开发

服务机器人访客视觉感知与人体特征分析系统开发

服务机器人访客视觉感知与人体特征分析系统开发
人体、人脸视觉感知是接待导购、陪护服务机器人的核心业务能力,属于服务机器人应用技术员核心考核技能;岗位工作包含机器人视觉相机标定部署人体/人脸目标检测、访客距离测算、访客身份特征识别、访客图像信息归档等开发调试内容,支撑机器人主动迎宾、分人群差异化服务、访客到访记录留存等商用服务场景。本任务依托服务机器人云台视觉相机,开发访客人体感知与性别识别分析程序,完成商用机器人视觉交互全流程功能开发。
任务三:机器人访客AI视觉感知处理系统开发
创建名为03.py的文件,编写程序实现“AI视觉性别识别与人体分析系统”功能,并将文件存储至任务一第1条构建的文件夹中,具体功能要求如
1.调用人工智能试验箱外接摄像头,在窗口内显示实时画面。
2.同时识别人脸和人体轮廓:人脸用黄色(BGR值:0,255,255)矩形框标记,人体轮廓用蓝色(BGR值:255,0,0)多边形(基于轮廓点连接)标记。
3.实时计算人脸与摄像头的距离:基于人脸像素宽度估算,假设人脸实际宽度为15cm,当人脸在图像中占据100像素时,距离为100cm,每增加10像素距离减少10cm(公式:距离=(100*15)/人脸像素宽度),在窗口左上角显示“Face Distance:XXcm”(XX为计算出的距离值,保留1位小数)。
4.性别识别:基于预训练Caffe模型识别人脸性别(Male/Female),在人脸矩形框下方显示性别结果(字体大小20,颜色绿色(BGR:0,255,0))。
5.数据留存:按下“q”键退出程序时,自动保存检测到的所有人脸截图(截图仅包含人脸区域,命名格式:face_时间.jpg,如face_20250520143000.jpg)到face_captures 子文件夹(需自动创建,与03.py同目录)。
程序如下:

导入必要的库

from exboard import RGB # 试验箱RGB灯环控制库
import cv2 # OpenCV计算机视觉库
import numpy as np # 数值计算库
import os # 文件系统操作
import time # 时间处理
from datetime import datetime # 日期时间处理

====================== 1. 初始化配置 ======================

摄像头设备ID(根据实际连接情况调整)

CAMERA_ID = 2

人脸实际宽度(cm)

KNOWN_FACE_WIDTH = 15.0

参考距离100cm时的人脸像素宽度

REFERENCE_PIXEL_WIDTH = 100

计算参考焦距(基于用户提供的公式推导)

FOCAL_LENGTH = (REFERENCE_PIXEL_WIDTH * 100) / KNOWN_FACE_WIDTH

颜色定义(BGR格式,OpenCV默认使用BGR)

YELLOW = (0, 255, 255) # 人脸框颜色
BLUE = (255, 0, 0) # 人体轮廓颜色
GREEN = (0, 255, 0) # 性别文字颜色

性别识别模型配置(Caffe预训练模型)

GENDER_MODEL = “gender_net.caffemodel”
GENDER_PROTO = “gender_deploy.prototxt”
GENDER_LABELS = [‘Male’, ‘Female’]

模型输入参数

MODEL_MEAN_VALUES = (78.4263377603, 87.7689143744, 114.895847746)
INPUT_SIZE = (227, 227)

初始化RGB灯环(试验箱硬件)

rgb = RGB()

初始关闭所有灯珠

rgb.set([(0, 0, 0)] * 24)

====================== 2. 加载模型与初始化 ======================

def init_system():
“”“系统初始化:加载模型、创建文件夹、初始化摄像头”“”
# 1. 自动创建人脸截图保存目录
if not os.path.exists(“face_captures”):
os.makedirs(“face_captures”)
print(“创建人脸截图目录: face_captures”)

# 2. 加载人脸检测器(Haar级联分类器) face_cascade = cv2.CascadeClassifier("haarcascade_frontalface_default.xml") if face_cascade.empty(): raise Exception("无法加载人脸检测器,请确保haarcascade_frontalface_default.xml文件存在") # 3. 加载性别识别Caffe模型 gender_net = cv2.dnn.readNetFromCaffe(GENDER_PROTO, GENDER_MODEL) if gender_net.empty(): raise Exception("无法加载性别识别模型,请确保gender_net.caffemodel和gender_deploy.prototxt文件存在") # 4. 初始化摄像头 cap = cv2.VideoCapture(CAMERA_ID) if not cap.isOpened(): raise Exception(f"无法打开摄像头(ID: {CAMERA_ID}),请检查设备连接") # 设置摄像头分辨率(可选,根据实际情况调整) cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480) return face_cascade, gender_net, cap

====================== 3. 核心功能函数 ======================

def calculate_face_distance(face_width):
“”"
计算人脸与摄像头的距离
公式:距离 = (实际宽度 × 参考焦距) / 人脸像素宽度
“”"
if face_width <= 0:
return 0.0
distance = (KNOWN_FACE_WIDTH * FOCAL_LENGTH) / face_width
return round(distance, 1) # 保留1位小数

def detect_human_contour(frame):
“”“检测人体轮廓:基于背景减除和轮廓分析”“”
# 转换为灰度图
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 高斯模糊降噪
blur = cv2.GaussianBlur(gray, (5, 5), 0)
# 二值化(自适应阈值)
_, thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
# 形态学操作:去除噪点
kernel = np.ones((3, 3), np.uint8)
morph = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel, iterations=2)

# 查找轮廓 contours, _ = cv2.findContours(morph, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 筛选人体轮廓(基于面积大小) human_contours = [] for cnt in contours: area = cv2.contourArea(cnt) if area > 2000: # 过滤小轮廓(可根据实际情况调整) human_contours.append(cnt) return human_contours

def predict_gender(net, face_roi):
“”“基于Caffe模型预测人脸性别”“”
# 预处理:调整大小、归一化、创建blob
blob = cv2.dnn.blobFromImage(
face_roi, 1.0, INPUT_SIZE,
MODEL_MEAN_VALUES, swapRB=False
)

# 输入模型并前向传播 net.setInput(blob) predictions = net.forward() # 获取性别结果 gender_idx = np.argmax(predictions[0]) gender = GENDER_LABELS[gender_idx] confidence = predictions[0][gender_idx] return gender, confidence

def save_face_snapshot(face_roi, timestamp):
“”“保存人脸截图到face_captures文件夹”“”
# 生成文件名:face_时间戳.jpg
filename = f"face_captures/face_{timestamp}.jpg"
# 保存图像
cv2.imwrite(filename, face_roi)
print(f"保存人脸截图: {filename}")

====================== 4. 主程序 ======================

def main():
try:
# 系统初始化
face_cascade, gender_net, cap = init_system()
print(“系统初始化完成,开始运行…”)

# 存储检测到的人脸(用于退出时保存) detected_faces = [] while True: # 读取摄像头帧 ret, frame = cap.read() if not ret: print("无法读取摄像头画面,跳过帧") time.sleep(0.1) continue # 复制原始帧用于显示 display_frame = frame.copy() # ====================== 任务2:识别人脸和人体轮廓 ====================== # 1. 人脸检测 gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) faces = face_cascade.detectMultiScale( gray, scaleFactor=1.3, minNeighbors=5, minSize=(30, 30) ) # 存储当前帧检测到的人脸ROI current_faces = [] # 处理每个人脸 for (x, y, w, h) in faces: # 绘制黄色人脸矩形框 cv2.rectangle(display_frame, (x, y), (x+w, y+h), YELLOW, 2) # ====================== 任务3:计算人脸距离 ====================== face_distance = calculate_face_distance(w) # 在窗口左上角显示距离 cv2.putText( display_frame, f"Face Distance: {face_distance} cm", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, YELLOW, 2 ) # ====================== 任务4:性别识别 ====================== # 提取人脸ROI face_roi = frame[y:y+h, x:x+w] current_faces.append(face_roi) # 保存人脸ROI # 性别预测 gender, confidence = predict_gender(gender_net, face_roi) # 在人脸框下方显示性别结果 cv2.putText( display_frame, f"{gender} ({confidence:.2f})", (x, y+h+30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, GREEN, 2 ) # 2. 人体轮廓检测 human_contours = detect_human_contour(frame) # 绘制蓝色多边形轮廓 cv2.drawContours(display_frame, human_contours, -1, BLUE, 2) # 更新检测到的人脸列表(去重) detected_faces.extend(current_faces) # 显示实时画面 cv2.imshow("AI Test Box - Face & Human Detection", display_frame) # 控制灯环:检测到人脸时亮绿灯,否则熄灭 if len(faces) > 0: rgb.set([(0, 255, 0)] * 24) # 绿灯常亮 else: rgb.set([(0, 0, 0)] * 24) # 关闭灯环 # 按键处理 key = cv2.waitKey(1) & 0xFF if key == ord('q'): # ====================== 任务5:数据留存 ====================== print("接收到退出指令,保存人脸截图...") timestamp = datetime.now().strftime("%Y%m%d%H%M%S") # 保存所有检测到的人脸 for i, face in enumerate(detected_faces): if face.size > 0: # 确保人脸有效 save_face_snapshot(face, f"{timestamp}_{i}") print("退出程序,感谢使用!") break except Exception as e: print(f"程序运行出错: {str(e)}") finally: # 资源释放 if 'cap' in locals() and cap.isOpened(): cap.release() cv2.destroyAllWindows() rgb.set([(0, 0, 0)] * 24) # 关闭灯环

程序入口

ifname== “main”:
main()

← 返回列表