1. 前言
在AI人工智能發展應用的過程中,人臉識別技術得到了重用。目前在人臉識別相關的技術已經深入到生活方方面面。在公共安全、智能安防、手機認證等多個領域得到應用,比如: 通過人臉識別來解鎖手機,通過人臉識別進入某些政務軟件平臺或是銀行APP, 還是各大門店,超市使用的"支付寶刷臉支付"等等,這些應用大大方便了人們生活。
目前,因為新冠疫情防控的需要,人人出門都需要戴口罩,查驗健康碼和測量體溫,在辦公大樓門口、地鐵口、小區門口、商場門口人流量都比較大,傳統的人工測量體溫方式,費時費力、效率比較低,而且人工近距離核驗溫度,易產生交叉感染風險。
當前文章就利用 華為云提供的AI人臉識別接口+紅外測溫傳感器MLX90614ESF(DCI)+瑞芯微RK3399完成AI人臉測溫一體機設計 ,方便測量來往人員的體溫,減輕防疫防控工作人員的負擔。
實現的具體功能: 當檢測到人臉時,就測量溫度,并檢測有沒有帶口罩;在顯示屏上實時顯示溫度信息,如果溫度超出設置值,會通過語音播報提示。如果人員沒有戴口罩,會語音提示帶口罩。
2. 軟硬件設計
(1)核心板采用瑞芯微RK3399,運行ubuntu18.04 64位系統,編譯器采用aarch64-linux-gcc。攝像頭采用羅技的720p攝像頭。
(2)軟件界面采用QT設計,在RK3399的ubuntu18.04系統里可以直接安裝QT開發環境完成開發,也可以在PC機上交叉編譯后將程序和相關庫拷貝過來。
(3)測溫傳感器采用MLX90614ESF(DCI),這個是紅外非接觸式測溫傳感器,測量距離可達到1米左右,這個模塊是IIC協議接口。
3. 華為云人臉識別服務
3.1 開通人臉識別服務
官網地址: https://www.huaweicloud.com/product/face.html
3.2 人臉識別接口功能
華為云提供的人臉檢測可以對輸入圖片進行人臉檢測和分析,輸出人臉在圖像中的位置、人臉關鍵點位置、人臉關鍵屬性等信息。支持識別JPG、PNG、JPEG、BMP等格式的圖片,上傳圖片時選擇將圖片轉為Base64編碼上傳。
(1)接口請求方式: POST
(2)接口請求地址
格式:
https://face.{endpoint}.myhuaweicloud.com/v2/{project_id}/face-detect
?
示例:
https://face.cn-north-4.myhuaweicloud.com/v2/0e5957be8a00f53c2fa7c0045e4d8fbf/face-detect
(3)請求頭的參數
{
"X-Auth-Token": "******"
}
X-Auth-Token字段是訪問華為云的任何API接口都需要填,獲取方法看這里: https://bbs.huaweicloud.com/blogs/317759 翻到2.3小節。
(4)請求Body參數
image_base64字段 : 存放Base64編碼后的圖片數據,大小不超過8MB,建議小于1MB。
?
attributes字段 :這個參數可以選擇不填,不填就只是返回人臉的在圖片里的尺寸位置。如果希望獲取更多的屬性列表,可以填下面之這些屬性:
2:年齡
4:裝束(帽子、眼鏡)
6:口罩
7:發型
8:胡須
11:圖片類型
12:質量
13:表情
21:人臉圖片旋轉角(順時針偏轉角度),支持0°、90°、180°和270°圖片旋轉。
?
多個屬性間使用逗號(,)隔開。
(5)響應參數
如果圖像里沒有人臉,返回的數據是這樣的:
{"faces":[]}
?
如果沒有填額外的屬性,返回的數據是這樣的:
{
"faces": [
{
"bounding_box": {
"top_left_x": 61,
"top_left_y": 54,
"width": 114,
"height": 151
}
}
]
}
?
填了額外的屬性,返回的數據是這樣的:
{
"faces": [
{
"bounding_box": {
"top_left_x": 61,
"top_left_y": 54,
"width": 114,
"height": 151
},
"attributes": {
"age": 30,
"dress": {
"glass": "none",
"hat": "none"
},
"mask": "none",
"hair": "short",
"beard": "none",
"phototype": "internet photo",
"quality": {
"total_score": 0.62109375,
"blur": 0.3359375,
"pose": 0.266357421875,
"occlusion": 0.330810546875,
"illumination": 0.378662109375
},
"expression": {
"type": "neutral",
"probability": 0.9991200566291809
}
}
}
]
}
3.3 調試接口
地址: https://apiexplorer.developer.huaweicloud.com/apiexplorer/debug?product=FRS&api=DetectFaceByFile
如果最開始想體驗一下接口,了解參數的含義,可以先使用在線調試接口測試一下效果。
現在人臉檢測的調試接口可以直接在網頁上選擇本地圖片,不用再傳bash64數據,測試更加方便。
4. 設計設備端程序
4.1 調用人臉檢測接口
//人臉檢測
void Widget::FaceCheck(QImage image)
{
QString requestUrl;
QNetworkRequest request;
?
//存放圖片BASE64編碼
QString imgData;
?
//設置請求地址
QUrl url;
?
//人臉檢測請求地址
requestUrl = QString("https://face.%1.myhuaweicloud.com/v2/%2/face-detect")
.arg(SERVER_ID)
.arg(PROJECT_ID);
?
//設置數據提交格式
request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/json"));
?
//將圖片進行Base64編碼
imgData = QString(toBase64(image)); //編碼后的圖片大小不超過2M
//設置token
request.setRawHeader("X-Auth-Token",Token);
?
//構造請求
url.setUrl(requestUrl);
request.setUrl(url);
?
QString post_param=QString
("{"
""image_base64": "%1","
""attributes":%2"
"}").arg(imgData).arg("6");
?
//發送請求
manager- >post(request, post_param.toUtf8());
}
4.2 接口數據解析
if(function_select==6)
{
//解析數據
QJsonParseError json_error;
QJsonDocument document = QJsonDocument::fromJson(replyData, &json_error);
if(json_error.error == QJsonParseError::NoError)
{
//判斷是否是對象,然后開始解析數據
if(document.isObject())
{
QJsonObject obj = document.object();
//解析錯誤代碼
if(obj.contains("faces"))
{
QJsonArray face_arr=obj.take("faces").toArray();
?
for(int i=0;i< face_arr.size();i++)
{
QJsonObject object=face_arr.at(i).toObject();
if(object.contains("bounding_box"))
{
QJsonObject obj1=object.take("bounding_box").toObject();
?
int top_left_x=0;
int top_left_y=0;
int width=0;
int height=0;
?
if(obj1.contains("top_left_x"))
{
top_left_x=obj1.take("top_left_x").toInt();
}
if(obj1.contains("top_left_y"))
{
top_left_y=obj1.take("top_left_y").toInt();
}
if(obj1.contains("width"))
{
width=obj1.take("width").toInt();
}
if(obj1.contains("height"))
{
height=obj1.take("height").toInt();
}
?
qDebug()< < "top_left_x:"<
4.3 token獲取
void Widget::GetToken()
{
//表示獲取token
function_select=3;
?
QString requestUrl;
QNetworkRequest request;
?
//設置請求地址
QUrl url;
?
//獲取token請求地址
requestUrl = QString("https://iam.%1.myhuaweicloud.com/v3/auth/tokens")
.arg(SERVER_ID);
?
//自己創建的TCP服務器,測試用
//requestUrl="http://10.0.0.6:8080";
?
//設置數據提交格式
request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/json;charset=UTF-8"));
?
//構造請求
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);
?
//發送請求
manager- >post(request, text.toUtf8());
}
4.4 攝像頭初始化
//查找系統可用攝像頭
void Widget::Find_CameraNumber()
{
//清空列表
ui- >comboBox_camera_number- >clear();
?
/*查找電腦當前可用攝像頭*/
cameras = QCameraInfo::availableCameras();
if(cameras.count())
{
for(int i=0;i< cameras.count();i++)
{
ui- >comboBox_camera_number- >addItem(tr("%1").arg(i));
}
ui- >pushButton_start_camera- >setEnabled(true);
}
else
{
QMessageBox::warning(this,tr("提示"),"本機沒有可用的攝像頭!
"
"軟件作者:DS小龍哥
"
"BUG反饋:1126626497@qq.com");
ui- >pushButton_start_camera- >setEnabled(false);
}
?
/*攝像頭沒有啟動時,按鈕不可用*/
ui- >pushButton_find- >setEnabled(false);
ui- >pushButton_delete- >setEnabled(false);
ui- >pushButton_update- >setEnabled(false);
ui- >pushButton_register- >setEnabled(false);
}
?
?
//啟動攝像頭
void Widget::on_pushButton_start_camera_clicked()
{
//攝像頭啟動標志
if(camera_flag) //如果攝像頭已經啟動一次,再次啟動需要將之前的空間釋放掉
{
camera- >stop();
delete camera;
ui- >horizontalLayout_2- >removeWidget(videoWidget);
delete videoWidget;
}
?
camera_flag=1; //標志攝像頭已經啟動一次
?
//攝像頭啟動之后,就無法在重復啟動
ui- >pushButton_start_camera- >setEnabled(false);
?
/*創建攝像頭對象,根據選擇的攝像頭打開*/
camera = new QCamera(cameras.at(ui- >comboBox_camera_number- >currentIndex()));
?
/*構造捕獲的對象*/
camera_image_capture = new QCameraImageCapture(camera);
?
/*設置捕獲的目的地*/
camera_image_capture- >setCaptureDestination(QCameraImageCapture::CaptureToFile);
?
//設置截圖輸出、緩沖區格式、分辨
camera_image_capture- >setCaptureDestination(QCameraImageCapture::CaptureToBuffer);
camera_image_capture- >setBufferFormat(QVideoFrame::PixelFormat::Format_Jpeg);
?
//設置截圖的圖片尺寸
iamge_setting.setResolution(320,240);
camera_image_capture- >setEncodingSettings(iamge_setting);
?
//關聯捕獲的信號,發出捕獲截圖信號時,發出信號
connect(camera_image_capture,&QCameraImageCapture::imageCaptured,this,&Widget::processCapturedImage);
?
/*配置攝像頭捕獲模式為幀捕獲模式*/
camera- >setCaptureMode(QCamera::CaptureViewfinder);
?
videoWidget = new QVideoWidget();
videoWidget- >setMinimumSize(320,240);
?
//將攝像頭顯示窗口加入到布局中
ui- >horizontalLayout_2- >insertWidget(0,videoWidget);
?
/*設置取景器顯示*/
camera- >setViewfinder(videoWidget);
?
/*啟動攝像頭*/
camera- >start();
?
/*攝像頭啟動時,按鈕可用*/
ui- >pushButton_find- >setEnabled(true);
ui- >pushButton_delete- >setEnabled(true);
ui- >pushButton_update- >setEnabled(true);
ui- >pushButton_register- >setEnabled(true);
}