Android 虹软人脸识别SDK-人脸对比
准备 :
登录官方网站,获取SDK,进行个人验证后新建项目,获取APP_ID,和SDK_KEY;
实现 :
激活引擎 :
/**
* 激活引擎
*
* @param view
*/
public void activeEngine(final View view) {
if (!checkPermissions(NEEDED_PERMISSIONS)) {
ActivityCompat.requestPermissions(this, NEEDED_PERMISSIONS, ACTION_REQUEST_PERMISSIONS);
return;
}
if (view != null) {
view.setClickable(false);
}
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
FaceEngine faceEngine = new FaceEngine();
//申请的APP_ID 和SDK_key
int activeCode = faceEngine.active(FaceMainActivity.this, Constants.APP_ID, Constants.SDK_KEY);
emitter.onNext(activeCode);
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Integer activeCode) {
if (activeCode == ErrorInfo.MOK) {
showToast("OK");
} else if (activeCode == ErrorInfo.MERR_ASF_ALREADY_ACTIVATED) {
showToast("Not Active");
} else {
showToast("shibai");
}
if (view != null) {
view.setClickable(true);
}
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
}
初始化引擎 :
private void initEngine() {
faceEngine = new FaceEngine();
faceEngineCode = faceEngine.init(this, FaceEngine.ASF_DETECT_MODE_IMAGE, FaceEngine.ASF_OP_0_HIGHER_EXT,
16, 10, FaceEngine.ASF_FACE_RECOGNITION | FaceEngine.ASF_FACE_DETECT | FaceEngine.ASF_AGE | FaceEngine.ASF_GENDER | FaceEngine.ASF_FACE3DANGLE | FaceEngine.ASF_LIVENESS);
VersionInfo versionInfo = new VersionInfo();
faceEngine.getVersion(versionInfo);
Log.i(TAG, "initEngine: init: " + faceEngineCode + " version:" + versionInfo);
if (faceEngineCode != ErrorInfo.MOK) {
Toast.makeText(this, "TEST", Toast.LENGTH_SHORT).show();
}
}
注册相机事件 :
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
File outImage = new File(getExternalCacheDir(), "output_image.jpg");
try {
if (outImage.exists()) {
outImage.delete();
}
outImage.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
if (Build.VERSION.SDK_INT >= 24) {
uri = FileProvider.getUriForFile(FaceMainActivity.this, "com.example.gdzc.cameraalbumtest.fileprovider", outImage);
} else {
uri = Uri.fromFile(outImage);
}
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
startActivityForResult(intent, TAKE_POTHO);
}
});
显示提示返回结果信息 :
/**
* 展示提示信息并且关闭提示框
*
* @param stringBuilder 带格式的提示文字
*/
private void showNotificationAndFinish(final SpannableStringBuilder stringBuilder) {
runOnUiThread(new Runnable() {
@Override
public void run() {
if (tvNotice != null) {
tvNotice.setText(stringBuilder.toString());
}
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
}
}
});
}
/**
* 追加提示信息
*
* @param stringBuilder 提示的字符串的存放对象
* @param styleSpan 添加的字符串的格式
* @param strings 字符串数组
*/
private void addNotificationInfo(SpannableStringBuilder stringBuilder, ParcelableSpan styleSpan, String... strings) {
tvNotice.append(stringBuilder.toString());
if (stringBuilder == null || strings == null || strings.length == 0) {
return;
}
int startLength = stringBuilder.length();
for (String string : strings) {
stringBuilder.append(string);
}
int endLength = stringBuilder.length();
if (styleSpan != null) {
stringBuilder.setSpan(styleSpan, startLength, endLength, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
人脸验证 :
首先人脸验证需要一个参照的人脸数据,与之后的人脸进行匹配,返回结果为通过与不通过。
//人脸比对数据显示
if (faceInfoList.size() > 0) {
if (type == TYPE_MAIN) {
int size = showInfoList.size();
showInfoList.clear();
showInfoAdapter.notifyItemRangeRemoved(0, size);
ivMainImage.setImageBitmap(mainBitmap);
mainFeature = new FaceFeature();
int res = faceEngine.extractFaceFeature(nv21, width, height, FaceEngine.CP_PAF_NV21, faceInfoList.get(0), mainFeature);
if (res != ErrorInfo.MOK) {
mainFeature = null;
}
ivMainImage.setImageBitmap(bitmap);
StringBuilder stringBuilder = new StringBuilder();
if (faceInfoList.size() > 0) {
stringBuilder.append("face info:\n\n");
}
for (int i = 0; i < faceInfoList.size(); i++) {
stringBuilder.append("face[")
.append(i)
.append("]:\n")
.append(faceInfoList.get(i))
.append("\nage:")
.append(ageInfoList.get(i).getAge())
.append("\ngender:")
.append(genderInfoList.get(i).getGender() == GenderInfo.MALE ? "MALE"
: (genderInfoList.get(i).getGender() == GenderInfo.FEMALE ? "FEMALE" : "UNKNOWN"))
.append("\nface3DAngle:")
.append(face3DAngleList.get(i))
.append("\n\n");
}
tvMainImageInfo.setText(stringBuilder);
} else if (type == TYPE_ITEM) {
FaceFeature faceFeature = new FaceFeature();
int res = faceEngine.extractFaceFeature(nv21, width, height, FaceEngine.CP_PAF_NV21, faceInfoList.get(0), faceFeature);
if (res == 0) {
FaceSimilar faceSimilar = new FaceSimilar();
int compareResult = faceEngine.compareFaceFeature(mainFeature, faceFeature, faceSimilar);
if (compareResult == ErrorInfo.MOK) {
String resStr = "";
BigDecimal bigDecimal = new BigDecimal(faceSimilar.getScore());
if (bigDecimal.compareTo(new BigDecimal(0.8)) >= 0) {
resStr = "通过";
}else{
resStr = "不通过";
}
ItemShowInfo showInfo = new ItemShowInfo(bitmap, ageInfoList.get(0).getAge(), genderInfoList.get(0).getGender(), faceSimilar.getScore(),resStr);
showInfoList.add(showInfo);
showInfoAdapter.notifyItemInserted(showInfoList.size() - 1);
} else {
showToast("error");
}
}
}
} else {
if (type == TYPE_MAIN) {
mainBitmap = null;
}
}
} else {
showToast("can not get nv21 from bitmap!");
}
通过对比结果,对比结果值越接近1就越相似,此处识别通过标准为0.8。

代码 :
对比 :
package com.example.ttlock.activity;
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.FileProvider;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.arcsoft.face.AgeInfo;
import com.arcsoft.face.ErrorInfo;
import com.arcsoft.face.Face3DAngle;
import com.arcsoft.face.FaceEngine;
import com.arcsoft.face.FaceFeature;
import com.arcsoft.face.FaceInfo;
import com.arcsoft.face.FaceSimilar;
import com.arcsoft.face.GenderInfo;
import com.example.ttlock.R;
import com.example.ttlock.adapter.widget.ShowInfoAdapter;
import com.example.ttlock.model.ItemShowInfo;
import com.example.ttlock.utils.ImageUtil;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class MultiImageActivity extends AppCompatActivity {
private static final String TAG = "MultiImageActivity";
private static final int ACTION_CHOOSE_MAIN_IMAGE = 0x201;
private static final int ACTION_ADD_RECYCLER_ITEM_IMAGE = 0x202;
public static final int TAKE_POTHO = 1;
private static final int ACTION_REQUEST_PERMISSIONS = 0x001;
private Uri uri;
private ImageView ivMainImage;
private TextView tvMainImageInfo;
/**
* 选择图片时的类型
*/
private int TYPE_MAIN = 0;
private int TYPE_ITEM = 1;
/**
* 主图的第0张人脸的特征数据
*/
private FaceFeature mainFeature;
private ShowInfoAdapter showInfoAdapter;
private List<ItemShowInfo> showInfoList;
private FaceEngine faceEngine;
private int faceEngineCode = -1;
private Bitmap mainBitmap;
Toast toast = null;
private static String[] NEEDED_PERMISSIONS = new String[]{
Manifest.permission.READ_PHONE_STATE
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.activity_multi_image);
/**
* 在选择图片的时候,在android 7.0及以上通过FileProvider获取Uri,不需要文件权限
*/
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
List<String> permissionList = new ArrayList<>(Arrays.asList(NEEDED_PERMISSIONS));
permissionList.add(Manifest.permission.READ_EXTERNAL_STORAGE);
NEEDED_PERMISSIONS = permissionList.toArray(new String[0]);
}
if (!checkPermissions(NEEDED_PERMISSIONS)) {
ActivityCompat.requestPermissions(this, NEEDED_PERMISSIONS, ACTION_REQUEST_PERMISSIONS);
} else {
initEngine();
}
initView();
}
private void initView() {
ivMainImage = findViewById(R.id.iv_main_image);
tvMainImageInfo = findViewById(R.id.tv_main_image_info);
RecyclerView recyclerFaces = findViewById(R.id.recycler_faces);
showInfoList = new ArrayList<>();
showInfoAdapter = new ShowInfoAdapter(showInfoList, this);
recyclerFaces.setAdapter(showInfoAdapter);
recyclerFaces.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
recyclerFaces.setLayoutManager(new LinearLayoutManager(this));
}
private void initEngine() {
faceEngine = new FaceEngine();
faceEngineCode = faceEngine.init(this, FaceEngine.ASF_DETECT_MODE_IMAGE, FaceEngine.ASF_OP_0_HIGHER_EXT,
16, 6, FaceEngine.ASF_FACE_RECOGNITION | FaceEngine.ASF_AGE | FaceEngine.ASF_FACE_DETECT | FaceEngine.ASF_GENDER | FaceEngine.ASF_FACE3DANGLE);
Log.i(TAG, "initEngine: init " + faceEngineCode);
if (faceEngineCode != ErrorInfo.MOK) {
Toast.makeText(this, "f", Toast.LENGTH_SHORT).show();
}
}
private void unInitEngine() {
if (faceEngine != null) {
faceEngineCode = faceEngine.unInit();
Log.i(TAG, "unInitEngine: " + faceEngineCode);
}
}
@Override
protected void onDestroy() {
unInitEngine();
super.onDestroy();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
//
// if (data == null || data.getData() == null) {
// showToast("failed");
// return;
// }
// if (requestCode == ACTION_CHOOSE_MAIN_IMAGE) {
// mainBitmap = ImageUtil.getBitmapFromUri(data.getData(), this);
// if (mainBitmap == null) {
// showToast("failed");
// return;
// }
// processImage(mainBitmap, TYPE_MAIN);
// } else if (requestCode == ACTION_ADD_RECYCLER_ITEM_IMAGE) {
// Bitmap bitmap = ImageUtil.getBitmapFromUri(data.getData(), this);
// if (bitmap == null) {
// showToast("failed");
// return;
// }
// if (mainFeature == null) {
// return;
// }
// processImage(bitmap, TYPE_ITEM);
// }
switch (requestCode) {
case ACTION_CHOOSE_MAIN_IMAGE:
try {
mainBitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
// imageView.setImageBitmap(mBitmap);
//将图片解析成Bitmap对象,并把它显现出来
processImage(mainBitmap, TYPE_MAIN);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
break;
case ACTION_ADD_RECYCLER_ITEM_IMAGE:
Bitmap bitmap = null;
try {
bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
if (bitmap == null) {
showToast("failed");
return;
}
if (mainFeature == null) {
return;
}
processImage(bitmap, TYPE_ITEM);
default:
break;
}
}
public void processImage(Bitmap bitmap, int type) {
if (bitmap == null) {
return;
}
if (faceEngine == null) {
return;
}
//NV21宽度必须为4的倍数,高度为2的倍数
bitmap = ImageUtil.alignBitmapForNv21(bitmap);
if (bitmap == null) {
return;
}
int width = bitmap.getWidth();
int height = bitmap.getHeight();
//bitmap转NV21
final byte[] nv21 = ImageUtil.bitmapToNv21(bitmap, width, height);
if (nv21 != null) {
List<FaceInfo> faceInfoList = new ArrayList<>();
//人脸检测
int detectCode = faceEngine.detectFaces(nv21, width, height, FaceEngine.CP_PAF_NV21, faceInfoList);
if (detectCode != 0 || faceInfoList.size() == 0) {
showToast("face detection finished, code is " + detectCode + ", face num is " + faceInfoList.size());
return;
}
//绘制bitmap
bitmap = bitmap.copy(Bitmap.Config.RGB_565, true);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setStrokeWidth(10);
paint.setColor(Color.YELLOW);
if (faceInfoList.size() > 0) {
for (int i = 0; i < faceInfoList.size(); i++) {
//绘制人脸框
paint.setStyle(Paint.Style.STROKE);
canvas.drawRect(faceInfoList.get(i).getRect(), paint);
//绘制人脸序号
paint.setStyle(Paint.Style.FILL_AND_STROKE);
paint.setTextSize(faceInfoList.get(i).getRect().width() / 2);
canvas.drawText("" + i, faceInfoList.get(i).getRect().left, faceInfoList.get(i).getRect().top, paint);
}
}
int faceProcessCode = faceEngine.process(nv21, width, height, FaceEngine.CP_PAF_NV21, faceInfoList, FaceEngine.ASF_AGE | FaceEngine.ASF_GENDER | FaceEngine.ASF_FACE3DANGLE);
Log.i(TAG, "processImage: " + faceProcessCode);
if (faceProcessCode != ErrorInfo.MOK) {
showToast("face process finished, code is " + faceProcessCode);
return;
}
//年龄信息结果
List<AgeInfo> ageInfoList = new ArrayList<>();
//性别信息结果
List<GenderInfo> genderInfoList = new ArrayList<>();
//三维角度结果
List<Face3DAngle> face3DAngleList = new ArrayList<>();
//获取年龄、性别、三维角度
int ageCode = faceEngine.getAge(ageInfoList);
int genderCode = faceEngine.getGender(genderInfoList);
int face3DAngleCode = faceEngine.getFace3DAngle(face3DAngleList);
if ((ageCode | genderCode | face3DAngleCode) != ErrorInfo.MOK) {
showToast("at lease one of age、gender、face3DAngle detect failed! codes are: " + ageCode
+ " ," + genderCode + " ," + face3DAngleCode);
return;
}
//人脸比对数据显示
if (faceInfoList.size() > 0) {
if (type == TYPE_MAIN) {
int size = showInfoList.size();
showInfoList.clear();
showInfoAdapter.notifyItemRangeRemoved(0, size);
ivMainImage.setImageBitmap(mainBitmap);
mainFeature = new FaceFeature();
int res = faceEngine.extractFaceFeature(nv21, width, height, FaceEngine.CP_PAF_NV21, faceInfoList.get(0), mainFeature);
if (res != ErrorInfo.MOK) {
mainFeature = null;
}
ivMainImage.setImageBitmap(bitmap);
StringBuilder stringBuilder = new StringBuilder();
if (faceInfoList.size() > 0) {
stringBuilder.append("face info:\n\n");
}
for (int i = 0; i < faceInfoList.size(); i++) {
stringBuilder.append("face[")
.append(i)
.append("]:\n")
.append(faceInfoList.get(i))
.append("\nage:")
.append(ageInfoList.get(i).getAge())
.append("\ngender:")
.append(genderInfoList.get(i).getGender() == GenderInfo.MALE ? "MALE"
: (genderInfoList.get(i).getGender() == GenderInfo.FEMALE ? "FEMALE" : "UNKNOWN"))
.append("\nface3DAngle:")
.append(face3DAngleList.get(i))
.append("\n\n");
}
tvMainImageInfo.setText(stringBuilder);
} else if (type == TYPE_ITEM) {
FaceFeature faceFeature = new FaceFeature();
int res = faceEngine.extractFaceFeature(nv21, width, height, FaceEngine.CP_PAF_NV21, faceInfoList.get(0), faceFeature);
if (res == 0) {
FaceSimilar faceSimilar = new FaceSimilar();
int compareResult = faceEngine.compareFaceFeature(mainFeature, faceFeature, faceSimilar);
if (compareResult == ErrorInfo.MOK) {
String resStr = "";
BigDecimal bigDecimal = new BigDecimal(faceSimilar.getScore());
if (bigDecimal.compareTo(new BigDecimal(0.8)) >= 0) {
resStr = "通过";
}else{
resStr = "不通过";
}
ItemShowInfo showInfo = new ItemShowInfo(bitmap, ageInfoList.get(0).getAge(), genderInfoList.get(0).getGender(), faceSimilar.getScore(),resStr);
showInfoList.add(showInfo);
showInfoAdapter.notifyItemInserted(showInfoList.size() - 1);
} else {
showToast("error");
}
}
}
} else {
if (type == TYPE_MAIN) {
mainBitmap = null;
}
}
} else {
showToast("can not get nv21 from bitmap!");
}
}
/**
* 从本地选择文件
*
* @param action 可为选择主图{@link #ACTION_CHOOSE_MAIN_IMAGE}或者选择item图{@link #ACTION_ADD_RECYCLER_ITEM_IMAGE}
*/
public void chooseLocalImage(int action) {
// Intent intent = new Intent(Intent.ACTION_PICK);
// intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
// startActivityForResult(intent, action);
File outImage = new File(getExternalCacheDir(), "output_image.jpg");
try {
if (outImage.exists()) {
outImage.delete();
}
outImage.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
if (Build.VERSION.SDK_INT >= 24) {
uri = FileProvider.getUriForFile(MultiImageActivity.this, "com.example.gdzc.cameraalbumtest.fileprovider", outImage);
} else {
uri = Uri.fromFile(outImage);
}
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
startActivityForResult(intent, action);
}
public void addItemFace(View view) {
if (faceEngineCode != ErrorInfo.MOK) {
showToast("引擎未初始化,错误码为" + faceEngineCode);
return;
}
if (mainBitmap == null) {
showToast("\"请先选择主图\"");
return;
}
chooseLocalImage(ACTION_ADD_RECYCLER_ITEM_IMAGE);
}
public void chooseMainImage(View view) {
if (faceEngineCode != ErrorInfo.MOK) {
showToast("引擎未初始化,错误码为" + faceEngineCode);
return;
}
chooseLocalImage(ACTION_CHOOSE_MAIN_IMAGE);
}
private void showToast(String s) {
if (toast == null) {
toast = Toast.makeText(this, s, Toast.LENGTH_SHORT);
toast.show();
} else {
toast.setText(s);
toast.show();
}
}
private boolean checkPermissions(String[] neededPermissions) {
if (neededPermissions == null || neededPermissions.length == 0) {
return true;
}
boolean allGranted = true;
for (String neededPermission : neededPermissions) {
allGranted &= ContextCompat.checkSelfPermission(this, neededPermission) == PackageManager.PERMISSION_GRANTED;
}
return allGranted;
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == ACTION_REQUEST_PERMISSIONS) {
boolean isAllGranted = true;
for (int grantResult : grantResults) {
isAllGranted &= (grantResult == PackageManager.PERMISSION_GRANTED);
}
if (isAllGranted) {
initEngine();
} else {
showToast("权限被拒绝");
}
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
tools:context=".activity.MultiImageActivity">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_margin="20dp"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center">
<Button
android:id="@+id/bt_choose_main_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="chooseMainImage"
android:text="注册"/>
<ImageView
android:id="@+id/iv_main_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minHeight="100dp"
android:maxHeight="200dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/tv_main_image_info"/>
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#88000000"/>
<LinearLayout
android:layout_margin="20dp"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center">
<Button
android:id="@+id/bt_add_item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="addItemFace"
android:text="验证"/>
<android.support.v7.widget.RecyclerView
android:minHeight="300dp"
android:id="@+id/recycler_faces"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</LinearLayout>
</ScrollView>
RecyclerView 适配器:
package com.example.ttlock.adapter.widget;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.example.ttlock.R;
import com.example.ttlock.model.ItemShowInfo;
import java.util.List;
public class ShowInfoAdapter extends RecyclerView.Adapter<ShowInfoAdapter.ShowInfoHolder> {
private List<ItemShowInfo> showInfoList;
private LayoutInflater inflater;
public ShowInfoAdapter(List<ItemShowInfo> showInfoList, Context context) {
this.showInfoList = showInfoList;
this.inflater = LayoutInflater.from(context);
}
@NonNull
@Override
public ShowInfoHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
View itemView = inflater.inflate(R.layout.item_show_info, viewGroup, false);
ImageView ivHeadImage = itemView.findViewById(R.id.iv_item_head_img);
TextView tvNotification = itemView.findViewById(R.id.tv_item_notification);
ShowInfoHolder holder = new ShowInfoHolder(itemView);
holder.ivHeadImage = ivHeadImage;
holder.tvNotification = tvNotification;
return holder;
}
@Override
public void onBindViewHolder(@NonNull ShowInfoHolder showInfoHolder, int i) {
showInfoHolder.tvNotification.setText(showInfoList.get(i).getIsOk());
showInfoHolder.ivHeadImage.setImageBitmap(showInfoList.get(i).getBitmap());
}
@Override
public int getItemCount() {
return showInfoList==null?0:showInfoList.size();
}
class ShowInfoHolder extends RecyclerView.ViewHolder{
ImageView ivHeadImage;
TextView tvNotification;
ShowInfoHolder(@NonNull View itemView) {
super(itemView);
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="110dp"
android:paddingTop="10dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/iv_item_head_img"
android:layout_margin="10dp"
android:layout_width="80dp"
android:layout_height="80dp" />
<TextView
android:layout_gravity="center_vertical"
android:id="@+id/tv_item_notification"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
item :
package com.example.ttlock.model;
import android.graphics.Bitmap;
import com.arcsoft.face.GenderInfo;
public class ItemShowInfo {
private Bitmap bitmap;
private int age;
private int gender;
private float similar;
private String isOk;
public ItemShowInfo() {
}
public ItemShowInfo(Bitmap bitmap, int age, int gender, float similar, String isOk) {
this.bitmap = bitmap;
this.age = age;
this.gender = gender;
this.similar = similar;
this.isOk = isOk;
}
public String getIsOk() {
return isOk;
}
public void setIsOk(String isOk) {
this.isOk = isOk;
}
public Bitmap getBitmap() {
return bitmap;
}
public void setBitmap(Bitmap bitmap) {
this.bitmap = bitmap;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getGender() {
return gender;
}
public void setGender(int gender) {
this.gender = gender;
}
public float getSimilar() {
return similar;
}
public void setSimilar(float similar) {
this.similar = similar;
}
@Override
public String toString() {
return
" age=" + age +
", gender=" + (gender == GenderInfo.MALE ? "MALE" : (gender == GenderInfo.FEMALE ? "FEMALE" : "UNKNOWN")) +
", similar=" + similar;
}
}
Android 虹软人脸识别SDK-人脸对比的更多相关文章
- Android 关于虹软人脸识别SDK引擎使用总结
虹软 最近开放了人脸识别的SDK引擎(免费的哦),刚好有Android版的,就体验了一波.下面来说说Android版的SDK使用心得: ArcFace 虹软人脸认知引擎简介 目前开放的版本有人脸比对( ...
- 虹软人脸识别SDK接入Milvus实现海量人脸快速检索
一.背景 人脸识别是近年来最热门的计算机视觉领域的应用之一,而且现在已经出现了非常多的人脸识别算法,如:DeepID.FaceNet.DeepFace等等.人脸识别被广泛应用于景区.客运.酒店.办公室 ...
- java 虹软ArcFace 2.0,java SDK使用、人脸识别-抽取人脸特征并做比对
java人脸识别 虹软ArcFace 2.0,java SDK使用.人脸识别-抽取人脸特征并做比对 虹软产品地址:http://ai.arcsoft.com.cn/product/arcface.ht ...
- AI人脸识别SDK接入 — 参数优化篇(虹软)
引言 使用了虹软公司免费的人脸识别算法,感觉还是很不错的,当然,如果是初次接触的话会对一些接口的参数有些疑问的.这里分享一下我对一些参数的验证结果(这里以windows版本为例,linux.andro ...
- 虹软AI 人脸识别SDK接入 — 参数优化篇
引言 使用了免费的人脸识别算法,感觉还是很不错的,但是初次接触的话会对一些接口的参数有些疑问的.这里分享一下我对一些参数的验证结果(这里以windows版本为例,linux.android基本一样), ...
- 虹软人脸识别SDK在网络摄像头中的实际应用
目前在人脸识别领域中,网络摄像头的使用很普遍,但接入网络摄像头和人脸识别SDK有一定门槛,在此篇中介绍过虹软人脸识别SDK的接入流程,本文着重介绍网络摄像头获取视频流并处理的流程(红色框内),以下内容 ...
- Java版 人脸识别SDK demo
虹软人脸识别SDK之Java版,支持SDK 1.1+,以及当前最新版本2.0,滴滴,抓紧上车! 前言 由于业务需求,最近跟人脸识别杠上了,本以为虹软提供的SDK是那种面向开发语言的,结果是一堆dll· ...
- Java版 人脸识别SDK dem
虹软人脸识别SDK之Java版,支持SDK 1.1+,以及2.0版本,滴滴,抓紧上车! 前言由于业务需求,最近跟人脸识别杠上了,本以为虹软提供的SDK是那种面向开发语言的,结果是一堆dll······ ...
- Java离线人脸识别SDK 支持arcface 2.0 最新版
虹软人脸识别SDK之Java版,支持SDK 1.1+,以及当前最新版本2.0,滴滴,抓紧上车! JDK SDK Win release license status 前言 由于业务需求,最近跟人脸识别 ...
- 百度离线人脸识别sdk的使用
1.1下载sdk运行 百度离线人脸识别sdk的使用 1.2配置环境 添加至项目,可以拖动复制或者以类库形式添加face-resource此文件夹 放到根目录上一层 激活文件与所有dll引用放到根目录嫌 ...
随机推荐
- MagicBook屏幕频闪解决方案(Windows、MacOS)
对于已经看到这篇文章的小伙伴们,就不解释何为PWM调光频闪了. MagicBook笔记本性价比高,但屏幕素质确实很一般,我们人眼看不出来的频闪,实际对眼睛损害很大,如图(需要设置快门参数,如1/400 ...
- js查询checkbox已选择的值
$("input[id^=ck]").each(function(index,e){ if($(e).is(":checked")) { userArray.p ...
- django基础知识之自连接:
自连接 对于地区信息,属于一对多关系,使用一张表,存储所有的信息 类似的表结构还应用于分类信息,可以实现无限级分类 新建模型AreaInfo,生成迁移 class AreaInfo(models.Mo ...
- 小白开学Asp.Net Core 《七》
小白开学Asp.Net Core <七> — — 探究中间件(MiddleWare) 1.何为中间件? 中间件是组装到应用程序管道中以处理请求和响应的家伙,管道中的每个组件都要满足以下两个 ...
- GitHub代码阅读神器,你值有拥有!
(题图:from github) Github作为全球最大的程序员聚集地,已经成为学习开发技能的绝佳伴侣(如果你是程序员,但你还没有账户的话,这里建议你去signup,毕竟能增加成长的机会,不能错过 ...
- Golang 受欢迎的原因:大道至简
前言 Golang自2009年发布第一个版本,2012年发布1.0版本.在这10年的时间里,不断有开发者加入Golang的阵营中,不断共建Golang生态.其中比较有代表性的Golang编写软件作品是 ...
- 剑指offer第二版-7.重建二叉树
描述:输入某二叉树的前序遍历和中序遍历结果,重建该二叉树.假设前序遍历或中序遍历的结果中无重复的数字. 思路:前序遍历的第一个元素为根节点的值,据此将中序遍历数组拆分为左子树+root+右子树,前序遍 ...
- python通过TimedRotatingFileHandler按时间切割日志
通过TimedRotatingFileHandler按时间切割日志 线上跑了一个定时脚本,每天生成的日志文件都写在了一个文件中.但是日志信息不可能输出到单一的一个文件中. 原因有二:1.日志文件越来越 ...
- EnjoyingSoft之Mule ESB开发教程第一篇:初识Mule ESB
目录 1. Mule ESB基本介绍 2. Mule ESB社区版和企业版 3. Mule ESB常用场景 4. Mule ESB软件安装 客户端安装 服务端安装 5. 第一个Mule ESB应用- ...
- 关于下载安装Photoshop CS6遇到的一些问题
关于安装Photoshop CS6顺带安装AdobeBridge CS6和Aobe Extension Manager CS6的问题 Bridge是PS的一款插件,它能兼容大多数AODBE公司的软件, ...