android集成face++的人脸识别

github地址

https://github.com/sunbo-ui/faceDiscern

  • 第一次自己手动集成人脸识别,期间报错不断,报错的地方很多,但记住的不多.哈哈哈,有多少写多少吧~(此项目仅在小米10上测试成功)
首先是调用照相机
  • 拍照并获取缩略图,拍照并获取缩略图不需要任何权限,只需要调用相机然后获取结果即可
       // android 7.0系统解决拍照的问题
        StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
        StrictMode.setVmPolicy(builder.build());
        builder.detectFileUriExposure()    
  • 使用http请求报错not permitted by network security policy
    • 在res建立xml/network_security_config.xml'
    • 以及在androidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
     <!--默认允许所有网址使用非安全连接-->
    <base-config cleartextTrafficPermitted="true" />
</network-security-config>
 <application
        android:networkSecurityConfig="@xml/network_security_config"
  ..../>
  • 开始使用照相机,
    这里一开始有个bug,就是直接调用相机,这样做,onActivityResult方法返回的图像会默认被压缩一遍,使得显示到页面的图像会非常小.
/直接调用相机/
...
Intent takePhotoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);//用来打开相机的Intent
startActivityForResult(takePhotoIntent,REQ_CODE);//启动相机
...

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if(requestCode==REQ_CODE&&resultCode==RESULT_OK){
            /*缩略图信息是储存在返回的intent中的Bundle中的,
            * 对应Bundle中的键为data,因此从Intent中取出
            * Bundle再根据data取出来Bitmap*/
            Bundle extras = data.getExtras();
            Bitmap bitmap = (Bitmap) extras.get("data");
            mPicture.setImageBitmap(bitmap);
        }
    }
  • 改进方法,使用 intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(phoPath)));
if(!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
    Toast.makeText(MainActivity.this, "sdcard未使用~", Toast.LENGTH_SHORT).show();
      return;
 }
 //调用摄像头
 Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
 phoPath = getFileName();
 intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(phoPath)));
 startActivityForResult(intent, CAMERA_REQUEST);//跳转
--------------------
  //返回结果的方法
    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode) {
            case CAMERA_REQUEST:
                if (resultCode == Activity.RESULT_OK) {
                    //将保存在本地的图片取出并显示在界面上
                    bitmap = BitmapFactory.decodeFile(phoPath);
                    //将处理过的图片显示在界面上,并保存到本地
                    imageView.setImageBitmap(bitmap);
                    getImageFile();//获取图片信息,人脸识别用的
                }
                break;
        }
    }
保存图片到手机
  • 添加动态权限
  //动态获取权限
        ActivityCompat.requestPermissions(MainActivity.this,
                new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE,
                        Manifest.permission.READ_EXTERNAL_STORAGE},
                1);
  • 保存
    /**
     * 保存图片到图库
     */
    public void saveImageToGallery(Bitmap mBitmap) {
        if (mBitmap == null) {
            Toast.makeText(MainActivity.this, "还没有照片可以保存哦~", Toast.LENGTH_SHORT).show();
            return;
        }
        if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            Toast.makeText(MainActivity.this, "sdcard未使用~", Toast.LENGTH_SHORT).show();
            return;
        }
        // 首先保存图片
        File appDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getAbsoluteFile();
        if (!appDir.exists()) {
            appDir.mkdir();
        }
        String fileName = System.currentTimeMillis() + ".jpg";
        File file = new File(appDir, fileName);
        try {
            FileOutputStream fos = new FileOutputStream(file);
            mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
            fos.flush();
            fos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            Toast.makeText(MainActivity.this, "保存失败~", Toast.LENGTH_SHORT).show();
            return;
        } catch (IOException e) {
            e.printStackTrace();
            Toast.makeText(MainActivity.this, "保存失败~", Toast.LENGTH_SHORT).show();
            return;
        }
        // 其次把文件插入到系统图库
        try {
            MediaStore.Images.Media.insertImage(getApplication().getContentResolver(), file.getAbsolutePath(), fileName, null);
            Toast.makeText(MainActivity.this, "保存成功~", Toast.LENGTH_SHORT).show();
        } catch (FileNotFoundException e) {
            Toast.makeText(MainActivity.this, "保存失败~", Toast.LENGTH_SHORT).show();
            e.printStackTrace();
        } // 最后通知图库更新
        getApplication().sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + "")));
        bitmap.recycle();
    }

通过face++官方文档使用okhttp+gson来获取数据
  • 一个注意点:face++需要的图片数据我选择的是image_base64,需要转成base64以及需要控制图片大小,因为系统相机返回的图像太大,就选择手动压缩拉一下
//相机返回的方法中调用过方法
   public void getImageFile() {
        zip();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bitmapZip.compress(Bitmap.CompressFormat.JPEG, 100, baos);
        byte[] bitmapBytes = baos.toByteArray();
        //转成base64设置到ImageView
        image_file = Base64.encodeToString(bitmapBytes, Base64.DEFAULT);
        try {
            baos.flush();
            baos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void zip() {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true; // 只获取图片的大小信息,而不是将整张图片载入在内存中,避免内存溢出
        BitmapFactory.decodeFile(phoPath, options);
        int height = options.outHeight;
        int width = options.outWidth;
        int inSampleSize = 2; // 默认像素压缩比例,压缩为原图的1/2
        int minLen = Math.min(height, width); // 原图的最小边长
        if (minLen > 100) { // 如果原始图像的最小边长大于100dp(此处单位我认为是dp,而非px)
            float ratio = (float) minLen / 100.0f; // 计算像素压缩比例
            inSampleSize = (int) ratio;
        }
        options.inJustDecodeBounds = false; // 计算好压缩比例后,这次可以去加载原图了
        options.inSampleSize = inSampleSize; // 设置为刚才计算的压缩比例
        bitmapZip = BitmapFactory.decodeFile(phoPath, options); // 解码文件
    }
    if (image_file == null || "".equals(image_file)) {
                    Toast.makeText(MainActivity.this, "请先拍个照~", Toast.LENGTH_SHORT).show();
                    return;
                }
                OkHttpClient okHttpClient = new OkHttpClient();
                //2.创建一个RequestBody,可以用add添加键值对
                RequestBody requestBody = new FormBody.Builder()
                        .add("api_key", api_key)
                        .add("api_secret", api_secret)
                        .add("return_attributes", "gender,age,beauty,skinstatus")
                        .add("image_base64", image_file)
                        .build();
                //3.创建Request对象,设置URL地址,将RequestBody作为post方法的参数传入
                Request request = new Request.Builder().url(url).post(requestBody).build();
                //4.创建一个call对象,参数就是Request请求对象
                okHttpClient.newCall(request).enqueue(new Callback() {
                    @Override
                    public void onFailure(Call call, IOException e) {
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                e.printStackTrace();
                                Toast.makeText(MainActivity.this, "请求网络数据失败", Toast.LENGTH_SHORT).show();
                            }
                        });
                    }
                    //请求成功时调用该方法
                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                getData(response);
                            }
                        });
                    }
                });
  • getData(response)方法则是使用实体内部类接收json数据
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容