基于树莓派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 

void setup_gpio() {
    wiringPiSetup();
    pinMode(17, OUTPUT);  // 使用GPIO17控制LED
}

2. 调用libcamera拍照

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

#include 
#include 
#include 
#include 
#include 

#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。

你可能感兴趣的:(ARM-Linux开发,python,c语言,树莓派)