隨着人臉識別技術的不斷髮展,尤爲是在部分算法平臺對外開放算法以後,人臉識別的應用門檻獲得了極大下降。可是從算法到一款真正可落地的人臉識別產品,在完整的應用開發中,不只須要考慮底層算法的運行邏輯,也須要上層業務邏輯完整自洽。而這個從0到1的過程,每每會讓大部分中下企業及開發者,在項目商用化落地過程當中無從下手。html
所以,在這裏推薦一款開源的人臉識別應用套件ArcFaceGo。基於該套件,能夠快速甚至零代碼搭建人臉識別閘機通行、刷臉考勤以及近來大火的人臉識別測溫等應用。同時,利用它的開源屬性,也徹底可以在此基礎上開發成一款符合自身業務需求的產品,並投入商用。算法
【簡單易用 ArcFaceGo****應用套件構成】網絡
在應用套件中,已經內置了虹軟視覺開放平臺的離線人臉識別SDK。涵蓋人臉檢測、人臉比對、活體檢測、人臉屬性分析等一系列核心算法,即便無網絡狀態下也能夠運行。在虹軟視覺開放平臺完成下載後,能夠看到該應用套件由人臉識別軟件APK、中心管理端兩部分構成。ide
中心管理端:擁有人員註冊、考勤統計、出入查詢等功能,也能夠雲端進一步對接已有的業務平臺。模塊化
人臉識別設備端應用APK****:負責採集人臉信息、進行身份比對,並向中心管理端報備識別結果以及通知相關聯通控制器。在該部分其代碼中,已經針對人臉檢測、人臉比對、活體檢測等算法,模塊化的集成了相應算法運轉邏輯。開發者無需考慮各算法之間複雜運轉流程,只需傳入camera數據流,即可以回調識別結果。性能
同時,針對人臉圖像傳輸、處理中須要用到的多媒體圖像技術,在代碼中也一樣模塊化的封裝好了NV2一、RGBA、BGR等不一樣顏色格式自動轉化及圖像的四字節對齊等功能。ui
在運行性能方面,該開源應用套件在底層算法邏輯中維護「人臉底庫」,能夠充分提高人臉識別速度,以RK3288 -10000人爲例,相比在上層邏輯中進行人臉比對須要100ms ,而目前僅需10ms。this
【適配靈活 可應用於各種實際場景****】.net
基於開源代碼,開發者能夠自行定義交互界面及交互邏輯,並開發應用於各種場景的人臉識別應用。好比智慧辦公的人臉識別考勤機、智慧社區的人臉識別出入閘機、智慧商業的VIP迎賓系統、智慧醫院的人臉識別掛號機、智慧酒店的人臉識別入住等等產品。htm
1.針對具體場景,可視化適配硬件
不一樣場景的不一樣應用,也意味着須要適配不一樣的分辨率設備,適配單攝、雙攝、寬動態等各種攝像頭。ArcFaceGo****人臉識別應用套件提供了可視化的硬件適配頁面,方便預覽顯示及識別設置。
用戶也能自行改寫該部分代碼,譬如不但願用戶自行調節相關參數,以致於影響識別效果,甚至能夠將該部分功能進行封裝,以避免用戶誤觸。
2.可供對接硬件的多種廣播形式。
Action | 描述 |
---|---|
com.arcsoft.arcfacesingle.ACTION_IDENTIFY_SUCCESSFUL | 人員識別成功 |
com.arcsoft.arcfacesingle.ACTION_IDENTIFY_SUCCESS_PERSON_SERIAL | 人員識別成功後,會向外發送「personSerial」惟一標識號」 |
com.arcsoft.arcfacesingle.ACTION_OPEN_DOOR | 開門(在人員識別成功後會發送該廣播) |
com.arcsoft.arcfacesingle.ACTION_CLOSE_DOOR | 關門(發送開門廣播後,延遲一段時間會發送該廣播) |
com.arcsoft.arcfacesingle.ACTION_FACE_DETECT_HAS_FACE | 檢測到人臉框 |
com.arcsoft.arcfacesingle.ACTION_FACE_DETECT_NO_FACE | 人臉框丟失 |
場景1
在室內走廊或樓梯過道等光線不佳的地方,能夠對接ACTION_FACE_DETECT_HAS_FACE和ACTION_FACE_DETECT_NO_FACE廣播,在檢測到人臉時打開補光燈,這樣能夠提升識別率。
場景2
在一些單次受權經過的場景好比取藥房,可對接ACTION_IDENTIFY_SUCCESS_PERSON_SERIAL廣播,在受權而且識別經過以後能夠刪除該人受權以達到目的。
【人臉識別測溫機開發實例】
疫情期間,不少智慧門禁設備都會增長測溫模組,在經過人臉識別實現身份權限管理的同時,一併測量體溫。
目前這類產品的市場反響很是火熱,不管是要實現抗疫常態化的國內,仍是感染人數持續暴增的國外,都對該產品有迫切需求。
這款應用套件能夠與測溫模塊快速集成,以實現測溫結果與識別身份綁定的效果。具體如何實現,如下是代碼示例。
如下是具體實現的代碼示例,以主流的HTPA32x32d爲例。
private ConcurrentMap<Integer, Float> temperatureMap = new ConcurrentHashMap<>();
private byte[] rawData = new byte[2048];
private ReadThread.ReadListener readListener = (data, size) -> {synchronized (temperatureLocker) {
System.arraycopy(data, 1, rawData, 0, 2048);
}
};
public void start() {
ReadThread readThread = new ReadThread();
readThread.setListener(readListener);
readThread.start();
FaceEngine faceEngine = new FaceEngine();
Config config = new Config();
faceEngine.setRecognizeCallback(this);
faceEngine.init(this, config);
}
@Override
public void onRecognizeComplete(RecognitionResult recognitionResult) {
FaceInfo faceInfo = recognitionResult.faceInfo;
if (recognitionResult.result == ErrorInfo.MOK) {
if(temperatureMap.get(faceInfo.faceId)<=37.3) {
//溫度低於預警值而且識別成功,進行後續操做
}
}
}
@Override
public void onCameraPreview(byte[] bytes, ICamera iCamera) {
FaceInfo faceInfo = new FaceInfo();
faceEngine.faceRecognize(rgbData, irData, width, height, true, faceInfo);
if (faceInfo.faceId != -1 && temperatureMap.get(faceInfo.faceId) != null) {
//把額頭區域映射至32x32溫度矩陣中,取出對應的溫度
float temperature = getTemperature(faceInfo.forehead, rawData);
temperatureMap.put(faceInfo.faceId, temperature);
}
}
public class ReadThread extends Thread {private static final String HEIMANN_PATH = "/dev/ttyS2";
private static final int BAUDRATE = 115200;
private static final byte[] command = {(byte) 0XEE, (byte) 0xE1, (byte) 0x01, (byte) 0x55, (byte) 0xFF, (byte) 0xFC, (byte) 0xFD, (byte) 0xFF};
private FileOutputStream outputStream;
private FileInputStream inputStream;
private Object locker = new Object();
public ReadThread() {
try {mSerialPort = SerialPort
.newBuilder(HEIMANN_PATH, BAUDRATE)
.parity(0)
.dataBits(8)
.stopBits(1)
.build();
mInputStream = (FileInputStream) mSerialPort.getInputStream();
mOutputStream = (FileOutputStream) mSerialPort.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
}
public void sendCommand(byte[] data) {
if (mOutputStream != null) {
try {synchronized (locker) {
mOutputStream.write(data);
offset = 0;
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void run() {
super.run();
while (!isInterrupted()) {
int size;
try {synchronized (locker) {
if (mInputStream == null) {
return;
}
size = mInputStream.available();
if (size > 0) {
mInputStream.read(rawData, offset, size);
offset += size;
}
}
if (offset == rawData.length) {
if (getListener() != null) {
getListener().onDataReceived(rawData, offset);
}
offset = 0;
}
if (offset == 0) {
SystemClock.sleep(50);
sendCommand(command);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
對該產品感興趣的話能夠到虹軟視覺開放平臺進一步瞭解哦~