## 教程簡介 Angular是Google推出的Web前端開發框架,從12年發佈起就受到了強烈的關註,他首次提出了雙向綁定的概念,讓人耳目一新,在2016年9月中旬,Google正式發佈了Angular的第二代開發框架Angular 2,2017年3月推出了Angular4。 [Angular 4 ...
一、前言
- 建議使用低版本 SDK : Baidu_Face_Offline_SDK_Windows_Java_6.1.3
- 目前已知8.x版本對服務端不相容,存在運行過程中,第一次調用sdk能夠正常執行,第二次時出現JVM異常。
- SDK不支持多線程,一般都用於設備端,如人臉閘機上的面板機設備。
- 自定義庫文件路徑,與項目分離。
- 整合springBoot項目,實現啟動初始化SDK,按需調用。
二、SDK 引入並配置
- 解壓程式,查看對應操作系統的文件夾,將src目錄下的文件移動到我們的項目中。請不要修改此目錄結構。
- 給Face.java類添加註解,實現條件實例化。
@Slf4j
@Component
@Conditional(FaceSdkEnableCondition.class)
public class Face {
// *******以下為人臉sdk api介面*********
- 修改Face.java類載入庫的方式,以及初始化。
- 新增 Environment 類動態獲取庫路徑。
- 更換 System.load() 載入庫文件。
- 使用
@PostConstruct
註解,當類對象被創建時,自動完成初始化工作。 - 使用
@PreDestroy
註解,當類對象被銷毀時,自動完成釋放記憶體工作。
// ********* 以下為系統載入庫文件及opencv **********
private static String libPath;
public Face(){ }
@Autowired
public Face(Environment env) {
// 初始化libPath
libPath = env.getProperty("face-sdk.libPath",String.class);
// 載入dll文件
System.load(libPath + "BaiduFaceApi.dll");
System.load(libPath + "opencv_java320.dll");
}
Face api = null;
/* sdk初始化 */
@PostConstruct
public void init() {
log.info("離線SDK開始初始化");
log.info("SDK路徑:{}",libPath);
api = new Face();
int res = api.sdkInit(libPath);
if (res != 0) {
log.info("sdk init fail and error = {}\n", res);
return;
}
log.info("離線SDK初始化完成");
}
/* sdk釋放記憶體 */
@PreDestroy
private void destroy() {
if(api != null){
api.sdkDestroy();
}
log.info("離線SDK銷毀");
}
- 配置條件啟動類相關
package cn.dyina.config;
public class FaceSdkEnableCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
Environment env = context.getEnvironment();
// 根據face-sdk.enable屬性來決定是否創建 Face bean
return "true".equals(env.getProperty("face-sdk.enable"));
}
}
-
配置路徑存放庫文件
face-sdk: enable: true # 路徑請務必使用雙斜桿 libPath: D:\\FaceLib\\ imagesPath: D:\\FaceImages\\
- 請將SDK文件的所有.dll文件拷貝到
libPath
目錄下。 - 請將SDK文件下的opencv-jar、models、license文件夾拷貝到
libPath
目錄下。 - 請登錄 百度智能雲 控制中心,註冊並獲取離線識別SDK序列號,替換license\license.key內的序列號。
- 請將SDK文件的所有.dll文件拷貝到
-
安裝maven依賴,以解決打包異常
- 請修改併在項目終端執行以下的命令,將opencv-jar下的opencv-320.jar依賴安裝到maven倉庫。
mvn install:install-file -DgroupId=cn.dyina(jar包的groupId) -DartifactId=opencv-jar(jar包的artifactId) -Dversion=1.0(jar的版本號) -Dpackaging=jar -Dfile=D:\FaceLib\opencv-jar\opencv-320.jar(jar包的具體路徑)
- 添加maven依賴
<!-- 本地依賴 opencv-jar--> <dependency> <groupId>cn.dyina</groupId> <artifactId>opencv-jar</artifactId> <version>1.0</version> </dependency>
三、項目使用
- 在SpringBoot啟動類上,添加包掃描。
@SpringBootApplication(scanBasePackages = {"cn.dyina","com.jni"})
public class SpringBootBaiDuFaceSdkApplication {
//...
}
- 編寫service、controller。(以下示例代碼僅提供參考,請根據自己的業務需求進行編寫。)
@Slf4j
@Service
public class FaceService {
@Value("${face-sdk.imagesPath}")
String imagesPath;
public String registerFace(String fileName, String nickName) {
// 註冊人臉圖片
String ip_nickName = fileName.replaceFirst("[.][^.]+$", "");
// 獲取人臉特征值
Mat mat = Imgcodecs.imread(imagesPath + fileName);
long matAddr = mat.getNativeObjAddr();
// 填充人臉信息 後期將從資料庫獲取
String userInfo = nickName;
String userId = ip_nickName.replace(".","");
String groupId = "Face";
// 用人臉特征值註冊
JSONObject res = JSONObject.parseObject(Face.userAddByMat(matAddr, userId, groupId, userInfo));
log.info("user add result is:{}", res);
return res.getString("msg");
}
public String identifyFace(String fileName) {
// 調用人臉sdkAPI
Face.loadDbFace();
Mat mat1 = Imgcodecs.imread(imagesPath + fileName);
long mat1Addr = mat1.getNativeObjAddr();
int type = 0;
// 和人臉庫裡面的人臉特征值比較(人臉識別)
JSONObject res = JSONObject.parseObject(Face.identifyWithAllByMat(mat1Addr, type));
log.info("identify res is:{}", res);
if (!res.getString("errno").equals("0")) {
return res.getString("msg");
}
// 獲取人臉識別信息
double score = res.getJSONObject("data")
.getJSONArray("result")
.getJSONObject(0)
.getDouble("score");
String userId = res.getJSONObject("data")
.getJSONArray("result")
.getJSONObject(0)
.getString("user_id");
if (score > 80) {
String nickName = userId.split("_")[1];
return nickName;
} else {
log.info("根據圖片獲取人員信息失敗");
return "Match score is low";
}
}
}
/**
* 人臉識別 頁面相關介面
*/
@Slf4j
@RestController
@CrossOrigin(origins = "*", maxAge = 3600)
public class FaceController {
@Autowired
private FaceService faceService;
@Value("${face-sdk.imagesPath}")
String imagesPath;
/**
* 人臉註冊
* @param file
* @param ip
* @param nickName
* @return
* @throws IOException
*/
@PostMapping("/faceRegister")
public R<String> faceRegister(@RequestParam("photo") MultipartFile file,
@RequestParam("ip") String ip,
@RequestParam("nickName") String nickName) throws IOException {
String photo = Base64.getEncoder().encodeToString(file.getBytes());
String fileName = ip + "_" + nickName + ".jpg";
Base64ToImage.saveImage(imagesPath, fileName, photo);
// 人臉註冊
String res = faceService.registerFace(fileName, nickName);
if(!res.equals("success")){
return R.error(res,null);
}
return R.success(null);
}
/**
* 檢測人臉
* @param photo
* @param ip
* @return
*/
@PostMapping("/faceDetection")
public R<String> faceDetection(@RequestParam("photo") String photo, @RequestParam("ip") String ip) {
String fileName = ip +".jpg"; // 臨時存儲,用於檢測
Base64ToImage.saveImage(imagesPath, fileName, photo);
String res = faceService.identifyFace(fileName);
return R.success(res);
}
/**
* 查詢用戶組人臉
* @param groupId
* @return
*/
@GetMapping("/getAllFace")
public R<List> getAllFace(@RequestParam("groupId") String groupId){
log.info("====>> getAllFace");
List<String> userIdList = faceService.getAllFace(groupId);
return R.success(userIdList);
}
}
後記
-
com.jni.face
包下,除了Face.java類,其他都是示常式序,可以視情況刪除。 -
models 文件夾里的模型可以按情況刪除,詳細可以查看文檔。
-
項目啟動後,你的控制台應該會收到SDK初始化的信息。並且你的
libPath
目錄下應該生成db文件夾,人臉數據將存儲在這裡。(db文件夾將生成在庫文件所在目錄。刪除face.db後,初始化SDK時會自動生成,不需要額外操作。) -
有生產需求的,但設備量不多,可以鹹魚買序列號。(官網最低100個起購)