• Android 虹软人脸识别SDK-人脸对比


    准备 :

    登录官方网站,获取SDK,进行个人验证后新建项目,获取APP_ID,和SDK_KEY;

    https://ai.arcsoft.com.cn/ucenter/resource/build/index.html#/ucenter/resource/openPlatform/application

    实现 :

    激活引擎 :

     /**
         * 激活引擎
         *
         * @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:
    
    ");
                        }
                        for (int i = 0; i < faceInfoList.size(); i++) {
                            stringBuilder.append("face[")
                                    .append(i)
                                    .append("]:
    ")
                                    .append(faceInfoList.get(i))
                                    .append("
    age:")
                                    .append(ageInfoList.get(i).getAge())
                                    .append("
    gender:")
                                    .append(genderInfoList.get(i).getGender() == GenderInfo.MALE ? "MALE"
                                            : (genderInfoList.get(i).getGender() == GenderInfo.FEMALE ? "FEMALE" : "UNKNOWN"))
                                    .append("
    face3DAngle:")
                                    .append(face3DAngleList.get(i))
                                    .append("
    
    ");
                        }
                        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:
    
    ");
                        }
                        for (int i = 0; i < faceInfoList.size(); i++) {
                            stringBuilder.append("face[")
                                    .append(i)
                                    .append("]:
    ")
                                    .append(faceInfoList.get(i))
                                    .append("
    age:")
                                    .append(ageInfoList.get(i).getAge())
                                    .append("
    gender:")
                                    .append(genderInfoList.get(i).getGender() == GenderInfo.MALE ? "MALE"
                                            : (genderInfoList.get(i).getGender() == GenderInfo.FEMALE ? "FEMALE" : "UNKNOWN"))
                                    .append("
    face3DAngle:")
                                    .append(face3DAngleList.get(i))
                                    .append("
    
    ");
                        }
                        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;
        }
    }
  • 相关阅读:
    关于新人的培养与程序的测试
    关于23种设计模式的有趣见解
    看足球学习管理团队
    《Effective C#》Item 1
    测试系列之五回归测试
    VS2005 VS2008新建网站和新建项目里选Web应用程序区别
    SaaS的研究
    DropDownList控件选中项的深入研究
    用ie9浏览器若出现看视频有声音没图像的问题处理
    zencart目录页出现c.html网址的解决方法
  • 原文地址:https://www.cnblogs.com/yangchaojie/p/11102361.html
Copyright © 2020-2023  润新知