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