之前的学习中,曾经在香橙派上使用阿里云平台的服务实现过类型识别:
现在,尝试在树莓派上通过阿里云平台的服务实现人脸识别!
通过VScode远程连接树莓派
当然,使用SourceInsight来编写代码也可以,全看个人喜好。
我的个人理解是:
- VScode 更适合远程编写和调试
- SourceInsight 更适合本地编写多文件的项目
对于本节想要实现的人脸识别,并不特别需要很多文件,且经常需要调试,如果使用SourceInsight就要经常涉及将文件传给树莓派这个操作,较为繁琐。
关于如何连接,可以参考之前连接香橙派的博文,步骤几乎一模一样,唯一需要注意的是在.config文件中,树莓派的用户名是“pi”而不是“rasberrypi”:
小插曲 -- 使用Visual Studio Code远程连接香橙派_visual code 连接 inspect-CSDN博客
VSCODE小操作回顾&补充
- “ALT + SHIFT":多行缩进
- “CTRL + S”:保存
- “CTRL + F”:变量名查找 / 替换
连接成功后的样子:
树莓派Python版本检查
python版本不够的升级方法:
在之前就提到过,想要使用阿里云的人工智能模型,python版本最好是3开头的,所以在树莓派中同样运行以下指令检查python版本:
python --version
可见python版本已经是3.11了,那就不需要改动了!
并且由于这是自带的python,所以其库就在“/usr/bin” 下:
ls /usr/bin
配置环境变量
在后面的代码中,涉及到C语言调用python,所以需要调用<Python.h>,因此需要配置环境变量,否则这个库找不到:
vi ~/.bashrc
#将以下内容加到最后,保存退出
export C_INCLUDE_PATH=/usr/include/python3.11
注意,配置后,要重启树莓派后才能生效 !!
阿里云的人脸识别方案
-
阿里云官网:阿里云|达摩院视觉智能开放平台
-
如果之前没有进行过注册,则需要通过支付宝注册,并获取AccessKey ID和Secret
我之前就创建过账号,现在再获取一组 ID & Secret (如果之前有用之前的应该也可以):阿里云登录 - 欢迎登录阿里云,安全稳定的云计算服务平台
AccessKey ID 和 密码 一定要自己保存好!!
-
在树莓派上下载相应的SDK:
关于人脸人体的SDK的查找:
pip install alibabacloud_facebody20191230
此处发生了报错:
解决办法:
sudo mv /usr/lib/python3.11/EXTERNALLY-MANAGED /usr/lib/python3.11/EXTERNALLY-MANAGED.bak
-
安装完成后,根据自己实际的ACCESS_KEY_ID 和 ACCESS_KEY_SECRET,将以下内容写入到家目录下的.bashrc中:
vi ~/.bashrc
#然后在末尾输入以下内容:
export ALIBABA_CLOUD_ACCESS_KEY_ID="XXX" #根据自己实际的ID填写
export ALIBABA_CLOUD_ACCESS_KEY_SECRET="XXXX" #根据自己实际的SECRET填写
保存退出后,重启树莓派,再输入“export”验证:
可见,ACCESSKEY已经成功被配置成为环境变量!
-
在官网的人脸识别中找到一个感兴趣的模型,我此处找了“人脸比对1:1 ”:能力展示-阿里云视觉智能开放平台
- 点击“立即开通”开通服务
- 点击“立刻购买”购买服务(此处似乎有优惠,免费使用1年)
此时,就可以使用这个模型了!
-
下载示例代码进行测试
不能直接在人脸比对1:1下使用那个python代码例程,而是要在以下链接中找到“文件在本地或文件不在同一地域OSS”的例程:
在树莓派”mjm_code“下创建一个“face_detect_test”文件夹,将示例代码拷贝进来并稍作修改:
test.py:
# -*- coding: utf-8 -*-
# 引入依赖包
# 最低SDK版本要求:facebody20191230的SDK版本需大于等于4.0.8
# 可以在此仓库地址中引用最新版本SDK:https://pypi.org/project/alibabacloud-facebody20191230/
# pip install alibabacloud_facebody20191230
import os
import io
from urllib.request import urlopen
from alibabacloud_facebody20191230.client import Client
from alibabacloud_facebody20191230.models import CompareFaceAdvanceRequest
from alibabacloud_tea_openapi.models import Config
from alibabacloud_tea_util.models import RuntimeOptions
def face_detect(): #定义成一个函数,方便调用!
config = Config(
# 创建AccessKey ID和AccessKey Secret,请参考https://help.aliyun.com/document_detail/175144.html。
# 如果您用的是RAM用户的AccessKey,还需要为RAM用户授予权限AliyunVIAPIFullAccess,请参考https://help.aliyun.com/document_detail/145025.html。
# 从环境变量读取配置的AccessKey ID和AccessKey Secret。运行代码示例前必须先配置环境变量。
access_key_id=os.environ.get('ALIBABA_CLOUD_ACCESS_KEY_ID'),
access_key_secret=os.environ.get('ALIBABA_CLOUD_ACCESS_KEY_SECRET'),
# 访问的域名
endpoint='facebody.cn-shanghai.aliyuncs.com',
# 访问的域名对应的region
region_id='cn-shanghai'
)
runtime_option = RuntimeOptions()
compare_face_request = CompareFaceAdvanceRequest()
#场景一:文件在本地
streamA = open(r'/home/pi/mjm_code/face_detect_test/mjm.png', 'rb') #预存的照片
compare_face_request.image_urlaobject = streamA
streamB = open(r'/home/pi/mjm_code/face_detect_test/face.png', 'rb') #待测试的照片
compare_face_request.image_urlbobject = streamB
try:
# 初始化Client
client = Client(config)
response = client.compare_face_advance(compare_face_request, runtime_option)
# 获取整体结果
print(response.body)
except Exception as error:
# 获取整体报错信息
print(error)
# 获取单个字段
print(error.code)
# tips: 可通过error.__dict__查看属性名称
# 关闭流
streamA.close()
streamB.close()
if __name__ == '__main__': #写一个main调用face_detect函数来测试
face_detect()
我使用了我自己的照片作为标准,并使用了两张照片进行测试,第一张是我本人的另一张照片;第二张是我同学的照片:
分别存在树莓派本地:
-
/home/pi/mjm_code/face_detect_test/mjm.png //预存的照片
-
/home/pi/mjm_code/face_detect_test/face.png //待测试的照片
可见,当我使用本人照片时,置信度约为77%,而当我使用同学照片时,置信度直接变为0%(我同学和我长的也太不一样了哈哈哈),所以综合来说测试成功!
-
置信度的提取和转化
但是返回的结果是一个结构非常的数据体,所以尝试将置信度单独返回,并只保留整数部分
提取的代码如下:
# 单独提取置信度
confidence = response.body.to_map()['Data']['Confidence'] #to_map()函数很重要,不要忘记
score = int(confidence)
print(score)
return score
现在,就可以返回置信度的整数部分了! 而之后就可以根据这个整数score来进行判断了!
编写C语言调用python的人脸识别
在刚刚的测试中,写出了调用阿里云人脸识别服务的pyhton程序,那么现在,尝试写C语言程序来调用python程序从而实现人脸识别!
-
①将刚刚的test.py中的main函数部分删除并重命名为face.py
刚刚加入main函数是为了直接调用封装好的face_detect函数,而现在要使用C语言来调用它,自然就不需要main函数了!
-
②编写调用face_detect函数的C函数
回顾“C语言调用Python的步骤”:
详见之前的博文:
face_cmp.c:
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <Python.h>
#include "face_cmp.h"
void face_init(void)
{
Py_Initialize();
PyObject *sys = PyImport_ImportModule("sys");
PyObject *path = PyObject_GetAttrString(sys, "path");
PyList_Append(path, PyUnicode_FromString("."));
}
void face_final(void)
{
Py_Finalize();
}
int face_score(void) //python下face_detect函数返回的是已经经过提取和取证过的置信度score,是个int型
{
PyObject *pModule = PyImport_ImportModule("face"); //加载python文件
if (!pModule)
{
PyErr_Print();
printf("Error: failed to load module\n");
goto FAILED_MODULE; //goto的意思就是如果运行到这里就直接跳转到FAILED_MODULE
}
PyObject *pFunc = PyObject_GetAttrString(pModule, "face_detect"); //加载python文件中的对应函数
if (!pFunc)
{
PyErr_Print();
printf("Error: failed to load function\n");
goto FAILED_FUNC;
}
PyObject *pValue = PyObject_CallObject(pFunc, NULL);
if (!pValue)
{
PyErr_Print();
printf("Error: function call failed\n");
goto FAILED_VALUE;
}
int result = 0;
if (!PyArg_Parse(pValue, "i", &result)) //ace_detect函数返回的是已经经过提取和取证过的置信度score,是个int型,用‘i’表示
{
PyErr_Print();
printf("Error: parse failed");
goto FAILED_RESULT;
}
/* 如果函数返回的是字符串,上面的PyArg_Parse则需要用‘s’来表示,且下面注释的代码非常重要,因为字符串名代表了其首地址,所以不能直接复制而是需要使用strncpy函数!!!
category = (char *)malloc(sizeof(char) * (strlen(result) + 1) ); //开辟一个新的字符串常量。+1是为了留出空间给\0
memset(category, 0, (strlen(result) + 1)); //初始化字符串
strncpy(category, result, (strlen(result) + 1)); //将result的结果复制给新的字符串
*/
FAILED_RESULT:
Py_DECREF(pValue);
FAILED_VALUE:
Py_DECREF(pFunc);
FAILED_FUNC:
Py_DECREF(pModule);
FAILED_MODULE:
return result;
}
face_cmp.h:
#ifndef __face__H
#define __face__H
void face_init(void);
void face_final(void);
int face_score(void);
#endif
- face_cmp的作用就是封装C语言下的人脸识别函数
- C语言下的人脸识别函数的实现通过调用python代码下的face_detect函数
-
③编写C程序调用刚刚的C函数实现人脸识别
face_test.c:
#include <stdio.h>
#include <stdlib.h>
#include "face_cmp.h"
int main()
{
int score = 0;
face_init();
score = face_score();
printf("score=%d\n", score);
face_final();
return 0;
}
-
④编译并试运行
运行以下代码编译:
gcc face_test.c face_cmp.c -I /usr/include/python3.11/ -l python3.11
可见,调用成功!