我司最近要做和人臉識別相關的產品,原來使用的是其他的在線平台,識別率和識別速度很滿意,但是隨着量起來的話,成本也是越來越不能接受(目前該功能我們是免費給用戶使用的),而且一旦我們的設備掉線了就無法使用人臉識別功能。基於這些考慮,我司需要尋找其他的方案。
通過搜索,目前發現,開源或免費支持離線的方案也有不少。目前初步考慮虹軟 ArcFace 戳這里查看詳情和Dlib。通過官方的demo 和 網上的資料,寫了個工程,也可以在這里看。
這里說一下要注意的
- 攝像頭是使用了 OpenCV 來處理的,這里可能會涉及到預覽圖和屏幕方向不一致的情況,我主要是通過一下代碼處理
// 轉換圖片矩陣 這個也是主要使用 <span style="background-color: rgb(255, 255, 255);">OpenCV 來處理的</span>
private Mat rotateMat(Mat srcMat){
int _cameraDisplayRotation = cameraDisplayRotation;
if(mCameraIndex == CAMERA_ID_BACK){ // 后置攝像頭
_cameraDisplayRotation = 180 + _cameraDisplayRotation;
}
Point center = new Point(srcMat.cols()/2,srcMat.rows()/2);
Mat dstMat = srcMat;
Mat rotImage = Imgproc.getRotationMatrix2D(center, _cameraDisplayRotation, 1); // 獲取旋轉矩陣 逆時針旋轉。參數說明 center:表示旋轉的中心點;angle:表示旋轉的角度 ;scale:圖像縮放因子
Imgproc.warpAffine(srcMat, dstMat, rotImage, dstMat.size()); // 實現坐標系仿射變換。參數說明 src: 輸入源圖像;dst: 輸出圖像;M: 仿射變換矩陣;dsize: 輸出圖像的尺寸
if(mCameraIndex == CAMERA_ID_FRONT){
Core.flip(dstMat,dstMat,1);//整理表示水平翻轉,0表示垂直翻轉,負數表示既有水平也有垂直翻轉
}
if(rotImage!=null)rotImage.release();
return dstMat;
}
- Dlib 和虹軟 ArcFace要做人臉識別前都需要先檢測人臉,要不然后續提取不到人臉特征
- 人臉特征比對時,建議將需要識別的人臉特征庫預先加載到內存,這樣可以加快速度(當然也占用比較大的內存)
- 在使用 Dlib 做人臉檢測時要注意,人臉方向和屏幕方向不一致時檢測不到人臉(虹軟 ArcFace 不存在這個問題),如果不一致,需要將圖片的人臉方向轉為和屏幕方向一致時再來做人臉檢測
- 虹軟 ArcFace 做人臉識別時,要注意你下載的憑條 SDK 與 APP_Id、SDK_key 要一致(這個是沒懂要搞這么多驗證數據)。庫的引用直接安裝文檔操作即可。
- 虹軟 ArcFace 做人臉識別時,要使用人臉檢測時的人臉角度,要不然提取不到人臉特征,可以參考一下代碼說明
// data 圖片數據 注意數據格式是NV21的,目前虹軟只支持這種格式,可以通過攝像頭參數設置,也可以通過相關工具轉換得到
// width 圖片寬
// height 圖片高
// AFD_FSDKEngine.CP_PAF_NV21 圖片數據格式 目前虹軟只支持這種格式
// faceDB 我的人臉特征庫
List<AFD_FSDKFace> result_FD = new ArrayList<>(); // 用來存放檢測到的人臉信息列表
AFD_FSDKError error_FD = engine_detection.AFD_FSDK_StillImageFaceDetection(data, width, height, AFD_FSDKEngine.CP_PAF_NV21, result_FD); // 檢測人臉
AFR_FSDKFace face = new AFR_FSDKFace(); // 用來存放提取到的人臉信息
AFR_FSDKMatching score = new AFR_FSDKMatching(); //score用於存放人臉對比的相似度值
for(int i=0; i < result_FD.size(); i++){
AFD_FSDKFace item = result_FD.get(i);
Rect itemRect = item.getRect(); // 人臉位置
int degree = item.getDegree(); // 人臉方向 這個比 Dlib 好的地方
AFR_FSDKError error_FR = engine_recognition.AFR_FSDK_ExtractFRFeature(data, width, height, AFR_FSDKEngine.CP_PAF_NV21, itemRect, degree, face); // 提取人臉信息
error_FR = engine_recognition.AFR_FSDK_FacePairMatching(face, item, score);
for(int j=0; j<faceDB.getFaceList().size(); j++ ){
AFR_FSDKFace itemFace = faceDB.getFaceList().get(j);
error_FR = engine_recognition.AFR_FSDK_FacePairMatching(face, itemFace, score); // 人臉對比
if(score.getScore() > myThreshold){ // 找到相似的人臉
。。。
}
}
}
測試結果:
- 原圖是1280x960,經壓縮處理是320x240,經測試發現虹軟的壓縮和不壓縮圖片,效果是差不多的
Dlib測試結果
| 機型 | 一次人臉檢測耗時 | 一次一個人臉特征提取耗時 | 一次人臉特征比對耗時 |
| 堅果 U1 | 280毫秒左右 | 6800毫秒左右 | 0.03毫秒左右 |
| 堅果 pro2 | 93毫秒左右 | 1060毫秒左右 | 0.002毫秒左右 |
虹軟測試結果
| 機型 | 一次人臉檢測耗時 | 一次一個人臉特征提取耗時 | 一次人臉特征比對耗時 |
| 堅果 U1 | 43毫秒左右 | 943毫秒左右 | 0.883毫秒左右 |
| 堅果 pro2 | 20毫秒左右 | 314毫秒左右 | 0.308毫秒左右 |
