人脸识别Arduino-Python串口联动LED功能异常求助
人脸检测门禁灯控功能修复
问题描述
需要实现:检测到已注册人脸时点亮绿灯(允许通行);检测到未注册人脸时点亮红灯。当前Python与Arduino代码无法正常实现该功能,以下是问题排查与修正方案。
原代码问题分析
Python代码问题
- 缺少依赖导入:代码中使用
cv2库但未导入,直接运行会报错 - 逻辑顺序错误:检测到人脸后先发送绿灯指令(
b'o'),还没完成人脸匹配就触发绿灯,不符合需求 - 未处理未注册人脸场景:仅处理了“检测到人脸”和“匹配到注册人脸”的情况,未匹配时无对应指令触发红灯
- 串口无初始化校验:未确认串口是否成功打开,可能导致通信失败
Arduino代码问题
- 未读取串口数据:
while(Serial.available())循环内未将串口数据读取到var变量,导致指令判断永远基于初始值,无法响应Python发送的指令 - 指令与灯控逻辑反向:原代码中
'o'对应绿灯、'f'对应红灯,与需求中“匹配到人脸亮绿灯”的逻辑完全相反 - 无默认状态维护:未处理无串口指令时的灯状态,可能出现灯态混乱
修正后的代码
Python代码
import face_recognition as fr import os import serial import cv2 # 补充缺失的OpenCV库导入 # 初始化串口,添加缓存清空与超时设置确保连接稳定 porta_serial = serial.Serial('COM3', 9600, timeout=1) porta_serial.flush() encoders = [] nomes = [] def criarEncoders(): lista = os.listdir('Pessoas') for arquivo in lista: imAtual = fr.load_image_file(f'Pessoas/{arquivo}') imAtual = cv2.cvtColor(imAtual, cv2.COLOR_BGR2RGB) # 增加异常处理,避免单张图片无人脸导致程序崩溃 try: encoders.append(fr.face_encodings(imAtual)[0]) nomes.append(os.path.splitext(arquivo)[0]) except IndexError: print(f"警告:{arquivo}中未检测到人脸,已跳过") def compararWebcam(): video = cv2.VideoCapture(0) face_matched = False while True: check, img = video.read() if not check: print("无法读取摄像头画面") break imgP = cv2.resize(img, (0, 0), None, 0.25, 0.25) imgP = cv2.cvtColor(imgP, cv2.COLOR_BGR2RGB) faceLoc = fr.face_locations(imgP) face_matched = False matched_name = "" if faceLoc: # 绘制人脸框 y1, x2, y2, x1 = faceLoc[0] y1, x2, y2, x1 = y1*4, x2*4, y2*4, x1*4 cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) encodeImg = fr.face_encodings(imgP)[0] # 遍历比对注册人脸库 for id, enc in enumerate(encoders): comp = fr.compare_faces([encodeImg], enc) if comp[0]: face_matched = True matched_name = nomes[id] cv2.rectangle(img, (x1, y2-35), (x2, y2), (0, 255, 0), -1) cv2.putText(img, matched_name, (x1+6, y2-6), cv2.FONT_HERSHEY_COMPLEX, 1, (255, 255, 255), 2) print(matched_name) break # 根据匹配结果发送对应指令 if face_matched: porta_serial.write(b'f') # 匹配成功,发送绿灯指令 else: porta_serial.write(b'o') # 未匹配,发送红灯指令 else: # 未检测到人脸,发送默认红灯指令 porta_serial.write(b'q') cv2.imshow('Webcam', img) # 按下q键退出程序 if cv2.waitKey(1) & 0xFF == ord('q'): break video.release() cv2.destroyAllWindows() porta_serial.close() # 退出时关闭串口 criarEncoders() compararWebcam()
Arduino代码
int led_liberado = 8; // 绿灯:对应已注册人脸 int led_nao_liberado = 7; // 红灯:对应未注册/无人脸 char var; void setup() { Serial.begin(9600); pinMode(led_liberado, OUTPUT); pinMode(led_nao_liberado, OUTPUT); // 初始状态:红灯亮,绿灯灭 digitalWrite(led_nao_liberado, HIGH); digitalWrite(led_liberado, LOW); } void loop() { if (Serial.available() > 0) { var = Serial.read(); // 读取串口数据到变量 if (var == 'f') { // 匹配到注册人脸:绿灯亮,红灯灭 digitalWrite(led_liberado, HIGH); digitalWrite(led_nao_liberado, LOW); } else if (var == 'o') { // 检测到未注册人脸:红灯亮,绿灯灭 digitalWrite(led_nao_liberado, HIGH); digitalWrite(led_liberado, LOW); } else if (var == 'q') { // 未检测到人脸:回到初始红灯状态 digitalWrite(led_nao_liberado, HIGH); digitalWrite(led_liberado, LOW); } } }
额外注意事项
- 确保
Pessoas文件夹下的图片均为单人脸清晰照片,避免人脸编码失败 - 确认Arduino的COM口与Python代码中的
COM3一致(可在Arduino IDE的工具菜单查看) - 运行Python代码前,先上传Arduino代码并关闭串口监视器,避免端口占用冲突
内容的提问来源于stack exchange,提问作者Iago Molina Camargo
相关产品推荐
相关产品推荐

