基于Python进行人脸识别控制小灯闪烁(识别到指定人脸)

这里我没有给 ESP8266 刷入 MicroPython 固件,而是用的Python和Mixly(在Mixly上写的代码,这个是一个可以图形化的软件,也可以进行部分代码编写,当然复杂程序还是用Arduino IDE,这边两者都可实现,以下仅展示用Mixly2.0进行的操作),且是HTTP服务器版本,非MQTT版本。

此篇是在该篇基础上进行了优化可点此处直接跳转,引入了人脸识别(即校验到指定人脸才亮灯)

用了face_recognition人脸识别库,需要先进行安装:

bash 复制代码
pip install face_recognition

注意如果安装过程中如果有报错类似:

bash 复制代码
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
     
        You must use Visual Studio to build a python extension on windows.  If you
        are getting this error it means you have not installed Visual C++.  Note
        that there are many flavors of Visual Studio, like Visual Studio for C#
        development.  You need to install Visual Studio for C++.
     
     
        !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

可以先安装Visual Studio的C++构建工具

或者直接下载dlib库,然后再pip install face_recognition。

dlib包链接:dlib包链接

以下是代码:

python 复制代码
import requests
import cv2
import face_recognition
import os
import time
import threading

# ESP8266的IP地址
ESP8266_IP = "192.168.1.12"
BASE_URL = f"http://{ESP8266_IP}"
TEST_URL = f"{BASE_URL}/text/plain"
LED_ON_URL = f"{BASE_URL}/led/on"
LED_OFF_URL = f"{BASE_URL}/led/off"

class FaceRecognitionSystem:
    def __init__(self):
        """初始化人脸识别系统"""
        self.known_faces_dir = r"D:\PythonProject\known_faces" # 图片存放地址
        self.known_face_encodings = []
        self.known_face_names = []
        self.last_trigger_time = 0
        self.led_cooldown = 3  # LED冷却时间(秒)
        self.led_is_on = False
        
        # 加载已知人脸
        self.load_known_faces()
        
    def load_known_faces(self):
        """加载已知人脸图片"""

        if not os.path.exists(self.known_faces_dir):
            print(f"已知人脸目录不存在: {self.known_faces_dir}")
            return
        
        all_files = os.listdir(self.known_faces_dir)
        
        for filename in all_files:
            # 检查文件后缀(兼容大小写)
            if filename.lower().endswith(('.jpg', '.jpeg', '.png')):
                image_path = os.path.join(self.known_faces_dir, filename)
                print(f"图片路径: {image_path}")
                
                # 检查文件是否为有效图片
                try:
                    image = face_recognition.load_image_file(image_path)
                except Exception as e:
                    print(f"图片加载失败: {e}")
                    continue
                
                # 获取人脸编码
                face_encodings = face_recognition.face_encodings(image)
                
                if len(face_encodings) > 0:
                    self.known_face_encodings.append(face_encodings[0])
                    self.known_face_names.append(os.path.splitext(filename)[0])
                    print(f"已加载人脸: {filename}")
                else:
                    print(f"未在图片中检测到人脸: {filename}")
            else:
                print(f"非支持的图片格式: {filename}")
                
        print(f"最终加载人脸数量: {len(self.known_face_encodings)}")
    
    def recognize_faces(self, frame):
        """识别人脸并返回是否匹配已知人脸"""
        if not self.known_face_encodings:
            return False
            
        # 调整图像大小以加快处理速度
        small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25)
        
        # 转换颜色空间 BGR->RGB
        rgb_small_frame = cv2.cvtColor(small_frame, cv2.COLOR_BGR2RGB)
        
        # 检测所有人脸位置
        face_locations = face_recognition.face_locations(rgb_small_frame)
        
        if not face_locations:
            return False
            
        # 获取所有人脸编码
        face_encodings = face_recognition.face_encodings(
            rgb_small_frame, 
            face_locations
        )
        
        # 与已知人脸比较
        for face_encoding in face_encodings:
            matches = face_recognition.compare_faces(
                self.known_face_encodings, 
                face_encoding,
                tolerance=0.4
            )
            
            # 如果匹配到任意已知人脸
            if True in matches:
                print("匹配到已知人脸")
                return True
            else:
                print("未匹配到已知人脸")
                
        return False
    
    def control_led(self, should_turn_on):
        """控制LED开关"""
        current_time = time.time()
        
        if should_turn_on and not self.led_is_on:
            # 检查冷却时间
            if current_time - self.last_trigger_time >= self.led_cooldown:
                print("检测到已知人脸,正在打开LED...")
                response = requests.get(LED_ON_URL, timeout=3)
                if response.status_code == 200:
                    print("LED已打开")
                    self.led_is_on = True
                    self.last_trigger_time = current_time
                    
                    # 设置3秒后关闭的计时器
                    def turn_off_led():
                        time.sleep(3)
                        response = requests.get(LED_OFF_URL, timeout=3)
                        if response.status_code == 200:
                            print("✓ LED已关闭")
                            self.led_is_on = False
                    
                    timer = threading.Thread(target=turn_off_led)
                    timer.daemon = True
                    timer.start()
                    
                else:
                    print(f"无法打开LED: {response.status_code}")

def test_esp8266_connection():
    """测试ESP8266连接"""
    print("测试ESP8266连接...")
    try:
        response = requests.get(f"{BASE_URL}/", timeout=3)
        if response.status_code == 200:
            print(f"ESP8266连接成功 (IP: {ESP8266_IP})")
            return True
    except:
        print(f"无法连接到ESP8266 (IP: {ESP8266_IP})")
        return False

def main():
    """主函数"""
    
    # 测试ESP8266连接
    if not test_esp8266_connection():
        print("连接测试失败,请检查配置")
        return
        
    # 初始化人脸识别系统
    face_system = FaceRecognitionSystem()
    
    if not face_system.known_face_encodings:
        print("未找到已知人脸,请将人脸图片放入 'known_faces' 文件夹")
        return
        
    # 打开摄像头
    print("正在打开摄像头...")
    cap = cv2.VideoCapture(0)
    
    if not cap.isOpened():
        print("无法打开摄像头")
        return
        
    print("摄像头已打开,退出请按 'q' 键退出程序")
    
    try:
        while True:
            # 读取摄像头画面
            ret, frame = cap.read()
            if not ret:
                print("无法读取摄像头画面")
                break
                
            # 识别人脸
            face_detected = face_system.recognize_faces(frame)
            
            # 控制LED
            face_system.control_led(face_detected)
            
            # 在画面上显示状态
            status_text = "已知人脸" if face_detected else "未知人脸"
            color = (0, 255, 0) if face_detected else (0, 0, 255)
            
            cv2.putText(frame, f"status: {status_text}", (10, 30),
                       cv2.FONT_HERSHEY_SIMPLEX, 1, color, 2)
            cv2.putText(frame, "LED: ON" if face_system.led_is_on else "LED: OFF", 
                       (10, 70), cv2.FONT_HERSHEY_SIMPLEX, 1, 
                       (0, 255, 255) if face_system.led_is_on else (128, 128, 128), 2)
            cv2.putText(frame, "Press 'q' to quit", (10, frame.shape[0] - 10),
                       cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 255, 255), 2)
            
            # 显示画面
            cv2.imshow('FaceRecognition', frame)
            
            # 按'q'退出
            if cv2.waitKey(1) & 0xFF == ord('q'):
                break
                
            # 控制处理频率,避免过于频繁
            time.sleep(0.1)
            
    except Exception as e:
        print(f"\n程序出错: {e}")
    finally:
        # 释放资源
        cap.release()
        cv2.destroyAllWindows()
        
        # 确保LED关闭
        try:
            if face_system.led_is_on:
                requests.get(LED_OFF_URL, timeout=2)
                print("程序退出,LED已关闭")
        except:
            pass
            
        print("程序已结束")

if __name__ == "__main__":
    main()

仍有可优化地方:比如将图片上传到云,从云获取,然后上传时候就进行图片人脸编码,摄像头识别到时可以直接获取。

以上是所有内容,感谢观看。

相关推荐
Aevget4 小时前
MFC扩展库BCGControlBar Pro v37.2新版亮点:控件功能进一步升级
c++·mfc·界面控件
Tansmjs4 小时前
C++与GPU计算(CUDA)
开发语言·c++·算法
喵手4 小时前
Python爬虫零基础入门【第九章:实战项目教学·第15节】搜索页采集:关键词队列 + 结果去重 + 反爬友好策略!
爬虫·python·爬虫实战·python爬虫工程化实战·零基础python爬虫教学·搜索页采集·关键词队列
Suchadar5 小时前
if判断语句——Python
开发语言·python
ʚB҉L҉A҉C҉K҉.҉基҉德҉^҉大5 小时前
自动化机器学习(AutoML)库TPOT使用指南
jvm·数据库·python
喵手5 小时前
Python爬虫零基础入门【第九章:实战项目教学·第14节】表格型页面采集:多列、多行、跨页(通用表格解析)!
爬虫·python·python爬虫实战·python爬虫工程化实战·python爬虫零基础入门·表格型页面采集·通用表格解析
逄逄不是胖胖5 小时前
《动手学深度学习》-54循环神经网络RNN
人工智能·深度学习
0思必得05 小时前
[Web自动化] 爬虫之API请求
前端·爬虫·python·selenium·自动化
莫问前路漫漫6 小时前
WinMerge v2.16.41 中文绿色版深度解析:文件对比与合并的全能工具
java·开发语言·python·jdk·ai编程
木头左6 小时前
Backtrader框架下的指数期权备兑策略资金管理实现与风险控制
python