树莓派3B人脸识别实践:Python与C联合开发详解

基于树莓派3B+的人脸识别实践:Python与C联合开发

引言

树莓派因其小巧的体积和丰富的扩展性,成为嵌入式开发的理想平台。本文将分享如何通过Python与C语言联合开发,在树莓派3B+上实现从硬件控制、摄像头拍照到百度API人脸比对的完整流程。项目代码已开源,欢迎参考与改进。


一、硬件与环境准备

所需硬件

  • 树莓派3B+
  • Raspberry Pi Camera Module(或USB摄像头)
  • 可选:LED指示灯、杜邦线(用于GPIO交互)
  • 环境配置

    1. 系统安装:建议使用Raspberry Pi OS (Legacy)或支持libcamera的版本。
    2. 安装依赖库
      sudo apt-get install wiringpi libcamera-dev python3-opencv
      pip3 install baidu-aip  # 百度AI SDK
      

    二、C语言控制摄像头拍照

    1. 使用wiringPi初始化GPIO

    通过C程序控制GPIO引脚(例如触发拍照信号后点亮LED):

    #include <wiringPi.h>
    
    void setup_gpio() {
        wiringPiSetup();
        pinMode(17, OUTPUT);  // 使用GPIO17控制LED
    }
    

    2. 调用libcamera拍照

    通过system()函数调用命令行工具libcamera-jpeg实现拍照:

    #include <stdio.h>
    #include <stdlib.h>
    #include <Python.h>
    #include <unistd.h>
    #include <string.h>
    
    #define WEGET_CMD "libcamera-jpeg -o /tmp/SearchFace.jpg"
    #define SEARCHFACE_FILE  "/tmp/SearchFace.jpg"
    
    
    void face_initialize(void)
     {
        Py_Initialize();
        // 将当前路径添加到sys.path中
        PyObject *sys = PyImport_ImportModule("sys");
        if(sys == NULL)
        {
            Py_DECREF(sys);
        }
        PyObject *path = PyObject_GetAttrString(sys, "path");
        if(path == NULL)
        {
            Py_DECREF(path);
        }
        PyList_Append(path, PyUnicode_FromString("."));
     }
    
    void get_result() {
        digitalWrite(17, HIGH);  // 拍照时点亮LED
        system(WEGET_CMD);
        if(access(SEARCHFACE_FILE,F_OK) != 0)
        {
            return result;
        }
        digitalWrite(17, LOW);
        printf("拍照成功\n");
        PyObject *pModule = PyImport_ImportModule("face_search");//导入face_search.py模块
        if (!pModule)
        {
            PyErr_Print();
            printf("Error: failed to load face.py\n");
            goto FAILED_MODULE;
        }
        printf("1\n");
        PyObject *pFunc = PyObject_GetAttrString(pModule, "search_Face");//获取search_Face函数对象
        if (!pFunc)
        {
            PyErr_Print();
            printf("Error: failed to load search_Face\n");
            goto FAILED_FUNC;
        }
        printf("2\n");
        PyObject *pValue = PyObject_CallObject(pFunc, NULL);//调用alibabacloud_face函数并获取返回值
        if (!pValue)
        {
            PyErr_Print();
            printf("Error: function call failed\n");
            goto FAILED_VALUE;
        }
        printf("3\n");
        char *temp = NULL;
        if  (!PyArg_Parse(pValue, "s", &temp))//解析获取alibabacloud_face函数的返回值,转行为C语言格式
        {
            PyErr_Print();
            printf("Error: parse failed");
            goto FAILED_RESULT;
        }
        printf("4\n");
        printf("%s|temp = %s\n",__func__,temp);
        strcpy(result,temp);
    FAILED_RESULT:
        Py_DECREF(pValue);
    FAILED_VALUE:
        Py_DECREF(pFunc);
    FAILED_FUNC:
        Py_DECREF(pModule);
    FAILED_MODULE:
        return result;
    }
    

    三、Python调用百度人脸比对API

    1. 百度AI平台配置

  • 注册百度AI开放平台,创建人脸识别应用,获取API KeySecret Key
  • 2. Python代码实现

    import base64
    import urllib
    import requests
    import json
    
    API_KEY = "xxx"
    SECRET_KEY = "xxx"
    
    def search_Face():
            
        url = "https://aip.baidubce.com/rest/2.0/face/v3/search?access_token=" + get_access_token()
        
        # image 可以通过 get_file_content_as_base64("C:\fakepath\微信图片_20250321164625.jpg",False) 方法获取
        payload = json.dumps({
            "group_id_list": "test1",
            "image": get_file_content_as_base64("/tmp/SearchFace.jpg"),
            "image_type": "BASE64"
        }, ensure_ascii=False)
        headers = {
            'Content-Type': 'application/json'
        }
        
        response = requests.request("POST", url, headers=headers, data=payload.encode("utf-8")).json()
        result = response.get("result").get("user_list")[0]
        # {'group_id': 'test1', 'user_id': 'hyx', 'user_info': '', 'score': 96.68011474609375}
        str_result = f'{result.get("user_id")},{result.get("score")}'
        print(str_result)
        return str_result
        
    
    def get_file_content_as_base64(path, urlencoded=False):
        """
        获取文件base64编码
        :param path: 文件路径
        :param urlencoded: 是否对结果进行urlencoded 
        :return: base64编码信息
        """
        with open(path, "rb") as f:
            content = base64.b64encode(f.read()).decode("utf8")
            if urlencoded:
                content = urllib.parse.quote_plus(content)
        return content
    
    def get_access_token():
        """
        使用 AK,SK 生成鉴权签名(Access Token)
        :return: access_token,或是None(如果错误)
        """
        url = "https://aip.baidubce.com/oauth/2.0/token"
        params = {"grant_type": "client_credentials", "client_id": API_KEY, "client_secret": SECRET_KEY}
        return str(requests.post(url, params=params).json().get("access_token"))
    
    if __name__ == '__main__':
        search_Face()
    
    

    四、联合开发流程整合

    1. 整体逻辑

    1. C程序控制摄像头拍照并保存图像。
    2. Python脚本读取图像,调用API进行人脸比对。
    3. 根据结果触发GPIO动作(如开门信号)。

    2. 封装Shell脚本调用

    在C程序中调用Python脚本:
    使用Python.h中的函数,实现在c中调用python中的函数并传回数据。

    3. 完整代码结构

    // main.c
     int main()
    {
         face_initialize();
         char result[128] = {0};
         get_result(result);
         printf("main.c:%s\n",result);
         return 0;
       }
    

    五、优化与注意事项

    1. 性能提升:通过共享内存减少I/O延迟。
    2. 错误处理:增加拍照失败重试、网络请求超时机制。
    3. 安全建议:加密存储百度API密钥,使用HTTPS传输数据。
    4. 实时性优化:使用OpenCV边缘计算减少云API依赖。

    六、效果演示

    【后期补】

    结语

    通过本文,您已经实现了树莓派上软硬件协同的人脸识别系统。未来可结合MQTT实现物联网控制,或移植到更复杂的边缘计算场景中。完整代码已托管至[GitHub仓库链接],欢迎Star与Fork!


    附录

  • 百度AI人脸识别文档
  • libcamera官方指南
  • wiringPi GPIO参考

  • 问题反馈:欢迎在评论区留言交流,或通过GitHub提交Issue。

    作者:坏柠

    物联沃分享整理
    物联沃-IOTWORD物联网 » 树莓派3B人脸识别实践:Python与C联合开发详解

    发表回复