1. 項(xiàng)目介紹
近幾年,生物特征識(shí)別技術(shù)獲得快速發(fā)展。人臉作為一種生物特征,具有很強(qiáng)的自身穩(wěn)定性和個(gè)體差異性,是進(jìn)行身份驗(yàn)證的最理想依據(jù),主要方法包括步態(tài)識(shí)別、虹膜識(shí)別、皮膚芯片、臉像識(shí)別、多模態(tài)(即多生物特征融合)技術(shù)等。其中,人臉識(shí)別技術(shù)因?yàn)榫哂蟹奖?、直觀、易于普及等優(yōu)點(diǎn)尤為受到關(guān)注與研究。
文章針對(duì)當(dāng)前常用考勤方式中普遍存在的代簽到、考勤數(shù)據(jù)整合較慢等問題,利用華為云的人臉識(shí)別技術(shù)實(shí)現(xiàn)了一種基于QT框架設(shè)計(jì)的在線考勤系統(tǒng)。該系統(tǒng)可大大提高考勤效率,滿足各類場(chǎng)環(huán)境景下的考勤需求,具有識(shí)別度高、檢測(cè)速度快、操作簡(jiǎn)單的特點(diǎn),能夠?yàn)橛脩籼峁└啾憷麕椭?/p>
實(shí)現(xiàn)大致流程:
- 注冊(cè)華為云賬號(hào)
- 開通華為云的人臉識(shí)別服務(wù)
- 通過API創(chuàng)建人臉庫(kù)
- 將需要考勤識(shí)別的人臉,添加到人臉庫(kù)
- 考勤時(shí),調(diào)用本地?cái)z像頭獲取人臉圖像,與人臉庫(kù)里注冊(cè)的人臉進(jìn)行對(duì)比,找到考勤人,完成考勤。
核心思路總結(jié):
華為云人臉識(shí)別服務(wù)支持,人臉庫(kù)創(chuàng)建,向人臉庫(kù)添加人臉,在人臉庫(kù)里搜索匹配的人臉,.......很多功能。當(dāng)前
考勤系統(tǒng)主要用到這3個(gè)功能。
創(chuàng)建人臉庫(kù): 在創(chuàng)建人臉庫(kù)的時(shí)候,支持創(chuàng)建自定義字段,也就是每個(gè)人臉可以加一些自定義的屬性描述,但是不支持中文字符,如果是字符串字段,范圍是0~255長(zhǎng)度;
向人臉庫(kù)添加人臉: 如果在創(chuàng)建人臉庫(kù)的時(shí)候,注冊(cè)了自定義字段,在添加人臉的時(shí)候就可以帶上自定義字段的描述,除了添加自定義字段,也可以添加ID,這個(gè)ID關(guān)聯(lián)數(shù)據(jù)庫(kù)方便考勤的時(shí)候進(jìn)行查找對(duì)比。
在人臉庫(kù)搜索人臉: 可以取一張本地的圖片與人臉庫(kù)里存在的人臉進(jìn)行匹配,得到相識(shí)度,在搜索人臉的時(shí)候也可以設(shè)置過濾條件,常見的條件就是相識(shí)度閥值,低于設(shè)置閥值就不返回,也可以設(shè)置自定義字段返回,如果注冊(cè)人臉的時(shí)候添加了自定義屬性,在識(shí)別到人臉的時(shí)候就可以通過返回的自定義屬性判斷這個(gè)人臉是誰。
考勤實(shí)現(xiàn)核心思路:
向人臉庫(kù)添加人臉的時(shí)候,可以指定external_image_id
字段,這個(gè)是代表圖片外部ID,與當(dāng)前圖像綁定,這個(gè)字段可以存放在本地的數(shù)據(jù)庫(kù)里,在考勤的時(shí)候,從當(dāng)前攝像頭取一幀圖像與華為云人臉庫(kù)里的圖像進(jìn)行對(duì)比,找到相識(shí)度最高的一張圖片,然后這張圖片的external_image_id
字段,然后與數(shù)據(jù)庫(kù)里的external_image_id
字段匹配,就找到這個(gè)人的詳細(xì)信息了(詳細(xì)信息是存放到本地?cái)?shù)據(jù)庫(kù)里的),然后就可以實(shí)現(xiàn)考勤邏輯了。
軟件最終的效果:
(1)主界面
(2)打開攝像頭
如果視頻里沒有人臉,會(huì)有錯(cuò)誤提示的。
(3)點(diǎn)擊人臉注冊(cè),添加工號(hào)自定義屬性
(4)點(diǎn)擊人臉?biāo)阉鳎核阉鞯街髸?huì)把自定義的屬性顯示出來--工號(hào)
其他功能都不在演示了,詳細(xì)實(shí)現(xiàn)看下面章節(jié)的代碼流程。
項(xiàng)目源碼下載地址: https://download.csdn.net/download/xiaolong1126626497/71245801
2. 創(chuàng)建人臉庫(kù)
2.1 開通人臉識(shí)別服務(wù)
官網(wǎng)地址: https://console.huaweicloud.com/frs/?region=cn-north-4&locale=zh-cn#/frs/manage/index
如果沒有華為云賬號(hào),打開上面地址時(shí),需要先注冊(cè),如果有賬號(hào)登錄之后就可以看到下面的頁(yè)面,鼠標(biāo)移到最右邊,開通對(duì)應(yīng)的服務(wù)。
2.2 創(chuàng)建人臉庫(kù)
官方幫助文檔地址: https://support.huaweicloud.com/api-face/face_02_0088.html
2.3 AK/SK、ID、域名參數(shù)獲取
在使用API訪問接口時(shí),需要填充很多的參數(shù),endpoint
,project_id
等等。
關(guān)于這些API需要使用的簽名參數(shù)介紹在這個(gè)頁(yè)面里:https://support.huaweicloud.com/devg-apisign/api-sign-provide-start.html
Endpoint 是代表地區(qū)與終端節(jié)點(diǎn),即云服務(wù)在不同Region有不同的訪問域名。
查看地址: https://developer.huaweicloud.com/endpoint
打開鏈接之后,選擇自己的服務(wù),然后往下翻就可以看到對(duì)應(yīng)服務(wù)的地址。
華北-北京四 cn-north-4 face.cn-north-4.myhuaweicloud.com HTTPS
獲取AK/SK
- 打開控制臺(tái)頁(yè)面
- 將鼠標(biāo)移至用戶名,在下拉列表中單擊“我的憑證”。
- 單擊“訪問密鑰”。
- 單擊“新增訪問密鑰”,進(jìn)入“新增訪問密鑰”頁(yè)面。
- 輸入描述信息,單擊“確定”,下載密鑰,請(qǐng)妥善保管。
在API憑證頁(yè)面可以看到項(xiàng)目ID:
2.4 在線調(diào)試接口
華為云提供了在調(diào)試API接口,非常方便,可以提前驗(yàn)證功能是否正常。
地址: https://apiexplorer.developer.huaweicloud.com/apiexplorer/debug?product=FRS&api=CreateFaceSet
選擇自己要調(diào)試的API,然后填充對(duì)應(yīng)的參考,進(jìn)行調(diào)試即可。
下面的例子是創(chuàng)建人臉庫(kù)。
如果同一個(gè)人臉庫(kù)創(chuàng)建兩次,就會(huì)報(bào)錯(cuò),可以在調(diào)試頁(yè)面看到錯(cuò)誤的提示,方便自己寫代碼時(shí)進(jìn)行判斷,處理。
如果不清楚訪問的域名地址是多少,在調(diào)試接口頁(yè)面是可以直接獲取查看的。
創(chuàng)建人臉庫(kù)的時(shí)候,還可以指定自定義字段,方便對(duì)這張人臉進(jìn)行打個(gè)性化標(biāo)簽屬性,方便知道這張臉是誰的。
請(qǐng)求頭:
{
"User-Agent": "API Explorer",
"X-Auth-Token": "******",
"Content-Type": "application/json"
}
請(qǐng)求體:
{
"external_fields": {
"face_name": {
"type": "string"
},
"face_phone": {
"type": "string"
},
"face_class": {
"type": "string"
}
},
"face_set_name": "face3"
}
2.5 代碼實(shí)現(xiàn)
/*
功能: 創(chuàng)建人臉庫(kù)
*/
void Widget::HuaweiCreatesFaceDatabase(QString face_lib_name)
{
//表示創(chuàng)建人臉庫(kù)
function_select=2;
?
QString requestUrl;
QNetworkRequest request;
?
//設(shè)置請(qǐng)求地址
QUrl url;
?
//人臉注冊(cè)的請(qǐng)求地址
requestUrl = QString("https://face.%1.myhuaweicloud.com/v2/%2/face-sets")
.arg(SERVER_ID)
.arg(PROJECT_ID);
?
//自己創(chuàng)建的TCP服務(wù)器,測(cè)試用
//requestUrl="http://10.0.0.6:8080";
?
//設(shè)置數(shù)據(jù)提交格式
request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/json"));
?
//設(shè)置token
request.setRawHeader("X-Auth-Token",Token);
//構(gòu)造請(qǐng)求
url.setUrl(requestUrl);
?
request.setUrl(url);
?
//添加自定義字段 external_fields這個(gè)對(duì)象就是自定義字段
//我這里只是定義了3個(gè)字段,可以自己增加
//添加人臉的時(shí)候也需要添加這里設(shè)置的自定義字段
QString post_param=QString("{"
""external_fields": {"
""face_name": {"
""type": "string""
"},"
""face_phone": {"
""type": "string""
"},"
""face_class": {"
""type": "string""
"}"
"},"
""face_set_name": "%1""
"}").arg(face_lib_name);
?
//發(fā)送請(qǐng)求
manager- >post(request, post_param.toUtf8());
}
3. 如何獲取X-Subject-Token
使用API訪問華為云的所有服務(wù)接口,都需要填X-Subject-Token參數(shù),下面介紹步驟:
3.1 創(chuàng)建一個(gè)新的IAM帳戶
鼠標(biāo)懸停在右上角的用戶名稱上,彈出下拉框,選擇統(tǒng)一身份認(rèn)證。
3.2 選擇創(chuàng)建用戶
3.3 使用調(diào)試接口測(cè)試獲取oken
調(diào)試接口地址: https://apiexplorer.developer.huaweicloud.com/apiexplorer/debug?product=IAM&api=KeystoneCreateUserTokenByPassword
右邊響應(yīng)頭里的X-Subject-Token
就是獲取的token。
3.4 上面的這些賬戶名稱從哪里獲???
3.5 請(qǐng)求地址和數(shù)據(jù)格式
獲取X-Subject-Token請(qǐng)求的地址: https://iam.cn-north-4.myhuaweicloud.com/v3/auth/tokens
請(qǐng)求頭數(shù)據(jù):
{
"User-Agent": "API Explorer",
"X-Auth-Token": "******",
"Content-Type": "application/json;charset=UTF-8"
}
請(qǐng)求體數(shù)據(jù):
{
"auth": {
"identity": {
"methods": [
"password"
],
"password": {
"user": {
"domain": {
"name": "xxxxx" //這里填當(dāng)前主賬戶名稱
},
"name": "xxxx", //這個(gè)新建的子賬戶名稱
"password": "xxxxx" //這個(gè)是新建的子賬戶密碼
}
}
},
"scope": {
"project": {
"name": "cn-north-4"
}
}
}
}
3.5 代碼實(shí)現(xiàn)
/*
功能: 獲取token
*/
void Widget::GetToken()
{
//表示獲取token
function_select=3;
?
QString requestUrl;
QNetworkRequest request;
?
//設(shè)置請(qǐng)求地址
QUrl url;
?
//獲取token請(qǐng)求地址
requestUrl = QString("https://iam.%1.myhuaweicloud.com/v3/auth/tokens")
.arg(SERVER_ID);
?
//自己創(chuàng)建的TCP服務(wù)器,測(cè)試用
//requestUrl="http://10.0.0.6:8080";
?
//設(shè)置數(shù)據(jù)提交格式
request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/json;charset=UTF-8"));
?
//構(gòu)造請(qǐng)求
url.setUrl(requestUrl);
?
request.setUrl(url);
?
QString text =QString("{"auth":{"identity":{"methods":["password"],"password":"
"{"user":{"domain": {"
""name":"%1"},"name": "%2","password": "%3"}}},"
""scope":{"project":{"name":"%4"}}}}")
.arg(MAIN_USER)
.arg(IAM_USER)
.arg(IAM_PASSWORD)
.arg(SERVER_ID);
?
//發(fā)送請(qǐng)求
manager- >post(request, text.toUtf8());
}
4. 向人臉庫(kù)添加人臉
4.1 調(diào)試接口
官方地址: https://support.huaweicloud.com/api-face/face_02_0093.html
添加人臉調(diào)試接口地址: https://apiexplorer.developer.huaweicloud.com/apiexplorer/debug?product=FRS&api=AddFacesByFile
4.2 請(qǐng)求接口與地址總結(jié)
請(qǐng)求地址: https://face.cn-north-4.myhuaweicloud.com/v2/項(xiàng)目ID/face-sets/人臉庫(kù)名稱/faces
請(qǐng)求方式: post
請(qǐng)求頭:
{
"User-Agent": "API Explorer",
"X-Auth-Token": "******", //替換成自己的token
"Content-Type": "application/json"
}
請(qǐng)求體:
{
"image_base64": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAk..........."
}
4.3 查詢?nèi)四?/h3>
文檔地址: https://support.huaweicloud.com/api-face/face_02_0094.html
調(diào)試地址: https://apiexplorer.developer.huaweicloud.com/apiexplorer/debug?product=FRS&api=ShowFaceSet
4.4 代碼實(shí)現(xiàn): 添加人臉時(shí)增加自定義字段
//注冊(cè)人臉,添加人臉,添加自定義數(shù)據(jù)
//QString name 這個(gè)是自定義字段,0~255 字節(jié),只能英文字母和數(shù)字
void Widget::RegFace2(const QImage image,QString face_lib,QString name)
{
function_select=0;
?
QString requestUrl;
QNetworkRequest request;
?
//存放圖片BASE64編碼
QString imgData;
?
//設(shè)置請(qǐng)求地址
QUrl url;
?
//人臉注冊(cè)的請(qǐng)求地址
requestUrl = QString("https://face.%1.myhuaweicloud.com/v2/%2/face-sets/%3/faces")
.arg(SERVER_ID)
.arg(PROJECT_ID)
.arg(face_lib);
qDebug()< < "requestUrl:"<
5. 從人臉庫(kù)搜索匹配的人臉
5.1 參數(shù)介紹
官方文檔地址: https://support.huaweicloud.com/api-face/face_02_0086.html
5.2 調(diào)試接口
接口地址: https://apiexplorer.developer.huaweicloud.com/apiexplorer/doc?product=FRS&api=SearchFaceByFile
我這里調(diào)試接口里選擇本地指定文件與人臉庫(kù)的人臉進(jìn)行匹配,返回相識(shí)度。
返回的結(jié)果:
{
"faces": [
{
"face_id": "6ED4NSsS",
"external_image_id": "FPhviHgr",
"bounding_box": {
"width": 197,
"top_left_x": 201,
"top_left_y": 80,
"height": 241
},
"similarity": 1
},
{
"face_id": "EpBvdmp5",
"external_image_id": "ubxcVUpN",
"bounding_box": {
"width": 104,
"top_left_x": 111,
"top_left_y": 100,
"height": 123
},
"similarity": 0.9802261
},
{
"face_id": "cSKntQmF",
"external_image_id": "nBoRpVab",
"bounding_box": {
"width": 113,
"top_left_x": 65,
"top_left_y": 106,
"height": 127
},
"similarity": 0.97810614
},
{
"face_id": "TZGv2cKI",
"external_image_id": "49y0pLG9",
"bounding_box": {
"width": 104,
"top_left_x": 90,
"top_left_y": 97,
"height": 125
},
"similarity": 0.9768342
},
{
"face_id": "3p1Ho8Vw",
"external_image_id": "vpuYDUvU",
"bounding_box": {
"width": 108,
"top_left_x": 100,
"top_left_y": 108,
"height": 122
},
"similarity": 0.9619592
},
{
"face_id": "nIuMJ1fA",
"external_image_id": "v8mNyJSY",
"bounding_box": {
"width": 102,
"top_left_x": 58,
"top_left_y": 141,
"height": 98
},
"similarity": 0.95380914
},
{
"face_id": "IamCTWR9",
"external_image_id": "KzUyJDxU",
"bounding_box": {
"width": 108,
"top_left_x": 32,
"top_left_y": 142,
"height": 97
},
"similarity": 0.5663861
}
]
}