Face recognition API V2.0

Hardware Interface API

1. IDCard/ICCard

  • Connected devices

Start the monitoring service and monitor the card swiping operation, it is recommended to execute in the on Resume() method.


/*
Open the background monitoring service
*/
IDCardUtil.getInstance().bindIDCardService(Context context);

/*
The NFC module is reported in the form of key value
*/
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (IDCardUtil.getInstance().handleEvent(event)) {return true;}

return super.dispatchKeyEvent(event);
}
  • Check function support

Since the monitoring service is started asynchronously, it is not necessarily accurate to perform function support detection immediately after connecting the device. It is recommended to check the function support again in the monitoring callback of 6 on Machine Connect.

/*
Check if the device supports ID card recognition
boolean: true means support, false means not support
*/
boolean result =IDCardUtil.getInstance().isSupportIDCard();
/*
Check if the device supports ICCard recognition
boolean: true means support, false means not support
*/
boolean result = IDCardUtil.getInstance().isSupportICCard();
  • Set swipe mode

Although the ID card module supports both ID card and IC Card, it does not support simultaneous reading of both, and the card reading mode needs to be set as required NFC module only supports ICCard.

/*
According to the specified reading method when swiping the card;
There are two main types:READCARD_MODE_IDENTITY_CARD and READCARD_MODE_IC_CARD;

IDCardConfig.READCARD_MODE_IDENTITY_CARD = 0;  //IDCard
IDCardConfig.READCARD_MODE_IC_CARD = 1; //ICCard
IDCardConfig.READCARD_MODE_IDENTITY_CARD_UUID = 2; //IDCard UUID 
*/
IDCardUtil.getInstance().setModel(int readMode);
  • Set the endian mode for reading IC Card

Set the endian mode when reading the IC Card, the default is big endian.

/*
boolean:true Bigendian, false Little endian
*/
IDCardUtil.getInstance().setICCardEndianMode(boolean useBig);
  • Set up listening and callback functions

/*
Binding credit card monitoring callback
context 
callback Listen callback
*/
IDCardUtil.getInstance().setIDCardCallBack(IDCardUtil.IDCardCallBack callBack);

//Listen callback
IDCardUtil.IDCardCallBack callBack = new IDCardUtil.IDCardCallBack() {

//The monitoring service is started asynchronously, if a card reading device is found after startup, it will call back on Machine Connect
@Override
public void onMachineConnect() {
    Log.i("firefly", "onMachineConnect ");
}

//Callback when ID card is swiped
@Override
public void onSwipeIDCard(final IDCardBean info) {
    Log.i("firefly",
        "picture:"+               + "\n" +
        "name:" + info.getName() + "\n" +
        "sex:" + info.getSex() + "\n" +
        "nation:" + info.getNation() + "\n" +
        "birthDate:" + info.getBirthDateStr() + "\n" +
        "address:" + info.getAddress() + "\n" +
        "number:" + info.getNum() + "\n" +
        "issue:" + info.getIssue() + "\n" +
        "expiration date:" + info.getCreateTimeStr() + "-" + info.getValidTimeStr() + "\n" +
        "picture:"+               + info.getPhoto() + "\n" );
}

// Execute callback when swiping IC card
@Override
public void onSwipeICCard(final ICCardBean info) {
    Log.i("firefly", "onSwipeICCard IC=" + info.getIcID());
}

// When setting the card reading mode to READCARD_MODE_IDENTITY_CARD_UUID Time, swipe ID card callback
@Override
public void onSwipeIDCardUUID(final String uuid) {
    Log.i("firefly", "onSwipeIDCardUUID uuid=" + uuid);
}
};
  • Disconnect

Remove the monitoring callback and stop the monitoring service, it is recommended to execute in the on Stop () method.

IDCardUtil.getInstance().setIDCardCallBack(null);
IDCardUtil.getInstance().unBindIDCardService(Context context);

2. Fill light control

There are 4 types of fill light: infrared fill light, white fill light, red fill light and green fill light.

  • Check whether the device supports infrared fill light;

/*
Boolean: true means support, false means not support
*/
HardwareCtrl.isSupportInfraredFillLight();
  • Operation of infrared fill light;

/*
isChecked true means open, false close
*/
HardwareCtrl.setInfraredFillLight(isChecked);
  • Check whether the device supports the brightness adjustment of the white fill light, and obtain the range of brightness adjustment;

/*
Boolean:true Indicates that infrared fill light is supported, false indicates that it is not supported
*/
HardwareCtrl.isFillLightBrightnessSupport();

/*
Support the maximum value of brightness adjustment;
*/
HardwareCtrl.getFillLightBrightnessMax();

/*
Support the minimum value of brightness adjustment;
*/
HardwareCtrl.getFillLightBrightnessMin();
  • White fill light operation;

/*
On/Off;
isChecked true means open and set the maximum value; false close
*/
HardwareCtrl.ctrlLedWhite(isChecked);

/*
On/Off, if brightness adjustment is supported, the corresponding brightness value can be passed in when the light is turned on;
isChecked  true means open and set the maximum value; false close
*/
HardwareCtrl.ctrlLedWhite(isChecked,brightness);
  • Red fill light operation;

/*
isChecked true means open and set the maximum value; false close
*/
HardwareCtrl.ctrlLedRed(isChecked);
  • Green fill light operation;

/*
isChecked true means open and set the maximum value; false close
*/
HardwareCtrl.ctrlLedGreen(isChecked);

3. Signal control

  • “Rs485/232”

485 serial port: /dev/ttyS4; 232 serial port: /dev/ttyS3; you can view the set value changes through cat /dev/ttyS4 or cat /dev/ttyS3;

/*

Get serial number serialPort 
485 serial port: /dev/ttyS4; 232 serial port: /dev/ttyS3
*/
SerialPort serialPort = HardwareCtrl.openSerialPortSignal(new File("/dev/ttyS3"), 19200, new SerialPort.Callback() {

//rs485/232After sending the signal, the return value received
@Override
public void onDataReceived(byte[] bytes, int i) {
    String result = StringUtils.bytesToHexString(bytes, size);
    Log.i("firefly", "result = "+result);
}
});

/*
Send ‘48562311’ signal
*/
HardwareCtrl.sendSerialPortHexMsg(serialPort, "48562311")

/*
Close the serial port (it is recommended to close the serial port when the page exits)
*/
HardwareCtrl.closeSerialPortSignal(serialPort);
  • Wiegand signal operation;

/*
Wiegand Input
*/
HardwareCtrl.openRecvMiegandSignal("/dev/wiegand");

/*
Add Wiegand Input listening callback
*/
HardwareCtrl.recvWiegandSignal(new RecvWiegandCallBack() {
@Override
public void recvWiegandMsg(int i) {
    Log.i("firefly", "result = "+i);
}
});

/*
When the page exits, close Wiegand
*/
HardwareCtrl.closeRecvMiegandSignal();

/*
Wiegand 26 Output
Check the set value changes through cat /sys/devices/platform/wiegand-gpio/wiegand26.
*/
HardwareCtrl.sendWiegandSignal("123456789");

/*
Wiegand 34 Output
Check the set value changes through cat /sys/devices/platform/wiegand-gpio/wiegand34.
*/
HardwareCtrl.sendWiegand34Signal("123456789");
  • Level signal/relay signal;

/*
D0 level signal isChecked true means open, false close
*/
LevelSignalUtil.sendSignalD0(isChecked);

/*
D1 level signal isChecked true means open, false close
*/
LevelSignalUtil.sendSignalD1(isChecked);

/*
Relay signal isChecked true means open, false closed
*/
RelayUtil.sendRelaySignal(isChecked);

4. QRCode

  • QRCode Operation

/*
Check whether the device supports the QR code function;
Boolean: true means support, false means not support
*/
QrCodeUtil.getInstance().isQrCodeSupport();

/*
Turn on QR code scanning
*/
QrCodeUtil.getInstance().init();

/*
Whether to turn on the QR code scanning fill light
QrCodeUtil.LED_STATE_AUTO // Automatic
QrCodeUtil.LED_STATE_ON // ON
QrCodeUtil.LED_STATE_OFF // OFF
*/
QrCodeUtil.getInstance().setLedState(state);

/*
Add QR code monitoring callback
*/
QrCodeUtil.getInstance().setQRCodeCallback(new QrCodeUtil.QRCodeCallback() {
// Callback method when QR code is connected
@Override
public void onConnect() {
Log.i("firefly","QRCode onConnect:");
}

// Content callback method for QR code recognition
@Override
public void onData(final String s) {
Log.i("firefly","QRCode onData:"+s);
}
});

/*
When the page exits, turn off QR code scanning
*/
QrCodeUtil.getInstance().release();

5. body temperature

  • Body temperature operation;

/*
Check whether the device supports body temperature;
Boolean: true means support, false means not support
*/
TempatureUtil.getInstance().isSupport();

/*
Turn on body temperature detection
*/
TempatureUtil.getInstance().openDevice();

/*
Add temperature detection monitoring callback
*/
TempatureUtil.getInstance().setTempatureCallback(new TempatureUtil.TempatureCallback() {
// Callback method when body temperature detection is connected
@Override
public void onConnect() {
Log.i("firefly","TempatureCallback onConnect:");
}

// Content callback method for body temperature detection
@Override
public void update(float ambientTempature, float objectTempature) {
Log.i("firefly","TempatureCallback update:ambientTempature="+ambientTempature + "objectTempature="+objectTempature);
}
});

/*
When the page exits, turn off the body temperature function
*/
TempatureUtil.getInstance().closeDevice();

6. Radar

  • Radar operation;

/*
Handling radar events, KeyEvent event
In the Android Activity page, public boolean dispatchKeyEvent(KeyEvent event), handle KeyEvent event
*/
RadarUtil.handleEvent(event);

/*
Dispatch Key Event on the Android Activity page
*/
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
int ret = RadarUtil.handleEvent(event);
if (ret == RadarUtil.EVENT_HANDLE_RADAR_IN) {// Object entry
    Log.i("firefly","EVENT_HANDLE_RADAR_IN");
    return true;
} else if (ret == RadarUtil.EVENT_HANDLE_RADAR_OUT) { // Object leaving
    Log.i("firefly","EVENT_HANDLE_RADAR_OUT");
    return true;
} else if (ret == RadarUtil.EVENT_HANDLE_NOTHING_HANDLED) { // No object
    Log.i("firefly","EVENT_HANDLE_NOTHING_HANDLED");
    return true;
}

return super.dispatchKeyEvent(event);
}



// Monitor radar signals
// The radar signal is triggered in the form of KeyEvent and processed using handleEvent (KeyEvent event)
public static final int RadarUtil.EVENT_HANDLE_NOTHING_UNHANDLE = -1; // Non-radar events are not processed
public static final int RadarUtil.EVENT_HANDLE_NOTHING_HANDLED = 0; // Non-radar events processed

// Radar key-value pair
public static final int RadarUtil.KEYCODE_RADAR_IN = 305; // Something enters
public static final int RadarUtil.KEYCODE_RADAR_OUT = 306; // There is an object leaving

// Radar event
public static final int RadarUtil.EVENT_HANDLE_RADAR_IN = 1; // Something enters
public static final int RadarUtil.EVENT_HANDLE_RADAR_OUT = 2; // There is an object leaving

Android Quick start

1. Add dependent libraries

1.Copy the aar package in the faceEngineYtlf/libs/ directory of the Demo project to the libs folder corresponding to the AS project;
2.Copy the ytlf_v2 folder in the faceEngineYtlf/src/main/assets directory of the Demo project to the src/main/assets folder corresponding to the AS project;

2. Add compile information for aar

implementation(name: 'arctern-release', ext: 'aar')
implementation(name: 'iface-release', ext: 'aar')
implementation(name: 'faceEngineYtlfExternal', ext: 'aar')

Add the following code to build.gradle's dependencies

For details, please refer to the technical case Demo project configuration or doc/FireflyApi_instructions.png ;

3. Setting permissions

Add the following permissions in the AndroidManifest.xml file

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-feature android:name="android.hardware.camera" android:required="true"/>
<uses-permission android:name="android.permission.CAMERA"/>

4. Defining FaceAPP variables in your program

When using YTLF Face Manager, you need to indicate the root path of the local SD card file storage directory, for example: “/sdcard/firefly/”; When the SDK is started for the first time, it will check whether there are files such as models and license public keys in the local SD card. If not, then by default, the necessary files will be copied from the App assets directory to the rootPath directory;

// Specify the local SD card file storage directory
YTLFFaceManager.getInstance().initPath(String rootPath);

5.Calling Face API interface through YTLFFaceManager

Face recognition

V2.0 adopts the asynchronous processing method of the thread pool to improve the utilization of the system and reduce the response time of services such as face detection and face tracking.

This SDK development guide will guide you how to install and configure the development environment, and how to perform secondary development and system integration by calling the interface (API) provided by the SDK. Users can call the API provided by the SDK according to requirements to achieve the purpose of using services such as face detection / tracking, living body recognition, face recognition, and other services.

1. SDK Access

1.1 SDK Initialize

When using YTLF Face Manager, you need to indicate the root path of the local SD card file storage directory, for example: “/sdcard/firefly/”; When the SDK is started for the first time, it will check whether there are files such as models and license public keys in the local SD card. If not, then by default, the necessary files will be copied from the App assets directory to the rootPath directory;

// Specify the local SD card file storage directory
YTLFFaceManager.getInstance().initPath(String rootPath);

1.2 Activating License

During initialization, it will check whether there is a local key, if not, it will be activated online, and the activation status will be called back after activation. It is divided into synchronous and asynchronous activation methods. ;

// Asynchronous mode
YTLFFaceManager.getInstance().initLicenseByAsync(String apiKey, new InitLicenseListener(){
    @Override
    public void onLicenseSuccess() {
                toast("success");
    }

    @Override
    public void onLicenseFail(final int code,final String msg) {
                toast("failure");
    }
});


// Synchronization mode true means successful activation
boolean result = YTLFFaceManager.getInstance().initLicense(String apiKey);

1.3 Get unique device code

Get the signature of the current device, the unique encoding of the device;

/*
String :Returns the current device's signature, which is the device's current unique code
*/
String signature = YTLFFaceManager.getInstance().getSignature();

2. SDK StartUp

When starting the SDK, it will detect the operating environment and initialize the SDK. There are synchronous and asynchronous startup methods.;

2.1 Start the SDK synchronously

/*
Determine the config_path through FACE_PATH, which is the directory where the Config.json file is stored
eg:  sdcard/firefly/ytlf_v2/config.json"

Int: 0 Means success, 1 means failure
*/
int result = YTLFFaceManager.getInstance().startFaceSDK();

/*
config_json Specify the contents of config.json

Int:0 Means success, 1 means failure
*/
int result = YTLFFaceManager.getInstance().startFaceSDKByConfigJson(String config_json);

2.2 Start SDK asynchronously

To prevent too much time when initializing and starting the SDK, causing the main thread to be blocked, you can use the asynchronous method to start the SDK;

/*
config_json Specify the contents of config.json
runSDKCallback Callback method after asynchronous start
*/
YTLFFaceManager.getInstance().startFaceSDKByAsynchronous(String config_json, new RunSDKCallback(){
@Override
public void onRunSDKListener(int i) {   //Int:0 Means success, 1 means failure

}
});

3. Face real-time data submission

Perform face detection and tracking based on the data passed into the detector, and return the results of face detection and face tracking in real time.Note: The face direction of the data input to the face detector should be positive, that is, the face angle Should be 0 degrees and no other angle; Currently, RGB and IR video streams are used for face detection tracking and related detection of living bodies.When it is not necessary to turn on the IR camera or do not need living body detection, IR data parameters can pass RGB parameters, but not NULL;

//Get video stream from camera callback function, input RGB video stream and IR video stream in real time
YTLFFaceManager.getInstance().doDelivery(ArcternImage img_rgb,  ArcternImage img_ir)

//Set the RGB and IR monitor callback function
YTLFFaceManager.getInstance().setOnDetectCallBack(new DetectCallBack() {
//  RGB:
@Override
public void onDetectListener(ArcternImage arcternImage, ArcternRect[] arcternRects, float[] confidences) {

}

//  IR:
@Override
public void onLivingDetectListener(ArcternImage arcternImage, ArcternRect[] arcternRects, float[] confidences) {

}
});

/*Parameter Description:
arcternImage RGB/IR Face image data detected
arcternRects  RGB/IR Collection of detected face frames
confidences RGB/IR Detect the confidence of each face
*/

4. Face real-time tracking callback

If there is data returned from the callback interface, then the real-time data is being detected and tracked;

//Set real-time face detection tracking callback
YTLFFaceManager.getInstance().setOnTrackCallBack(new TrackCallBack() {

/*Face real-time detection and tracking
arcternImage Face image data detected
trackIds  Face tracking in images ID
arcternRects Detected face position
*/
@Override
public void onTrackListener(ArcternImage arcternImage, long[] trackIds, ArcternRect[] arcternRects) {

}
});

5. Real-time face attribute detection

When performing real-time face detection tracking, add a face attribute detection callback method, which can receive face attributes in real time, including live detection value, quality, face angle, mask, and image color.

//Set real-time face attribute detection callback
YTLFFaceManager.getInstance().setOnAttributeCallBack(new AttributeCallBack() {

/*The face belongs to the monitoring callback:
arcternImage Face image data detected
arcternRects Detected face position
trackIds  Face tracking in images ID
arcternAttribute All attributes of all faces in the image
*/
@Override
public void onAttributeListener(ArcternImage arcternImage, long[] trackIds, ArcternRect[] arcternRects, ArcternAttribute[][] arcternAttributes, int[] landmarks) {
StringBuilder s = new StringBuilder();
for (int i = 0; i < arcternRects.length; i++) {
for (int j = 0; j < arcternAttributes[i].length; j++) {
    ArcternAttribute attr = arcternAttributes[i][j];
    switch (j) {
        case ArcternAttribute.ArcternFaceAttrTypeEnum.POSE_PITCH:
            s.append("Face angle:\n With the x axis as the center, the angle of the face up and down:").append(attr.confidence);
            break;
        case ArcternAttribute.ArcternFaceAttrTypeEnum.POSE_YAW:
            s.append("\n Rotate the face left and right around the y-axis:").append(attr.confidence);
            break;
        case ArcternAttribute.ArcternFaceAttrTypeEnum.POSE_ROLL:
            s.append("\n Taking the center point as the center, the x-y plane rotation angle:").append(attr.confidence);
            break;
            
        case ArcternAttribute.ArcternFaceAttrTypeEnum.QUALITY:
            s.append("\nFace quality:").append(attr.confidence);
            break;
            
        case ArcternAttribute.ArcternFaceAttrTypeEnum.LIVENESS_IR:
            if (attr.label != -1) {
                if (attr.confidence >= 0.5) {
                    s.append("\nBiopsy: live body ").append(attr.confidence);
                } else {
                    s.append("\nBiopsy: non-living ").append(attr.confidence);
                }
            }
            break;
            
        case ArcternAttribute.ArcternFaceAttrTypeEnum.IMAGE_COLOR:
            if (attr.label == ArcternAttribute.LabelFaceImgColor.COLOR) {
                s.append("\nColor picture ").append(attr.confidence);
            } else {
                s.append("\nBlack and white ").append(attr.confidence);
            }
            break;
            
        case ArcternAttribute.ArcternFaceAttrTypeEnum.FACE_MASK:
            if (attr.label == ArcternAttribute.LabelFaceMask.MASK) {
                s.append("\nMask ").append(attr.confidence);
            } else {
                s.append("\nWithout mask ").append(attr.confidence);
            }
            break;
    }
}
}
}
});

7. Get the landmarks coordinates of the eyes, mouth, nose, etc. of the face

Extract facial feature values ​​based on the Arctern Image of the face, which can be used to obtain the landmarks coordinates of the face, such as eyes, mouth, nose, etc.;

/*
Specify Arctern Image to extract facial feature values, including landmarks
*/
ArcternAttrResult ArcternAttrResult = YTLFFaceManager.getInstance().doFeature(ArcternImage arcternImage))

8. Extract face feature values ​​from specified image files

Extract face feature values ​​based on detected faces, which can be used for face comparison;

/*Specify image files to extract face feature values:
imagePath The map's address
etractCallBack  Face feature extraction callback
*/
YTLFFaceManager.getInstance().doFeature(imagePath, new ExtractCallBack() {

/*
acternImage Extract feature image
bytes  Set of face feature values ​​for multiple faces
arcternRects  Face detection result set
*/
@Override
public void onExtractFeatureListener(ArcternImage arcternImage, byte[][] bytes, ArcternRect[] arcternRects) {

if (features.length > 0) {
debugLog("bitmapFeature.length: " + features[0].length);
} else {
Tools.debugLog("Characteristic value is empty !");
}
});

9. Image Bitmap for feature value extraction

According to the face image Bitmap to extract the face feature value, it can be used for face comparison;

/*Specify face image Bitmap to extract face feature values:
bitmap Picture Bitmap data
etractCallBack  Face feature extraction callback
*/
YTLFFaceManager.getInstance().doFeature(Bitmap bitmap, new ExtractCallBack() {

/*
acternImage Extract feature image
bytes  Set of face feature values ​​for multiple faces
arcternRects  Face detection result set
*/
@Override
public void onExtractFeatureListener(ArcternImage arcternImage, byte[][] bytes, ArcternRect[] arcternRects) {

if (features.length > 0) {
debugLog("bitmapFeature.length: " + features[0].length);
} else {
Tools.debugLog("Characteristic value is empty !");
}
});

10. Face feature comparison

Compare the two feature values ​​to get the similarity between the two face feature values;

/*
feature1 First face feature value
Feature2  Second face feature value

return float :Return the similarity of face comparison
*/
float result = YTLFFaceManager.getInstance().doFeature(byte[] feature1,  byte[] feature2)

11. Face database management

11.1 Face storage

Add the extracted face feature values ​​and related IDs to the SDK face database;

/*
id Face ID
feature  Eigenvalues ​​of faces

0 Means success, 1 means failure
*/
int result = YTLFFaceManager.getInstance().dataBaseAdd(long id, byte[] feature)

11.2 Face library delete

According to the specified ID, delete the face information of the SDK face database;

/*
id Face ID

0 Means success, 1 means failure
*/
int result = YTLFFaceManager.getInstance().dataBaseDelete(long id)

11.3 Face library update

According to the specified ID, update the face information of the SDK face database;

/*
id Face ID
feature  Eigenvalues ​​of faces

0 Means success, 1 means failure
*/
int result = YTLFFaceManager.getInstance().dataBaseUpdate(long id, byte[] feature)

11.4 Add feature values ​​to faces in batches

According to the specified multiple IDs, batch update multiple face information corresponding to the SDK face database;

/*
id Face ID Array
feature  Array of multiple face feature values

0 Means success, 1 means failure
*/
int result = YTLFFaceManager.getInstance().dataBaseAdd(long[] id, byte[][] feature)

11.5 Face data removal

Delete all face information of SDK face database;

/*
0 Means success, 1 means failure
*/
int result = YTLFFaceManager.getInstance().dataBaseClear()