Android Arcore 简单的实现人脸增强,人脸识别,加遮照,精确单目测距计算屏幕到人的距离


title: Android Arcore 简单的实现人脸增强,人脸识别,加遮照,精确单目测距计算屏幕到人的距离
categories:

  • Android
    tags:
  • arCore
  • 人脸增强
  • 人脸识别
    date: 2020-05-29 10:12:46

本人博客转载去标明原文

前言

午后略困,倒杯咖啡,把之前挖的坑补上,今天来说一说arcore,arcore是google提供的一个增强现实的服务
,该服务的目的是做相机增强现实,,,ar,然而里面有个人脸增强的模块,可以我们用来实现人脸识别,和人脸增强
ARCore官网
gif

jpg
图片可以看到效果,arcore识别人脸,建模3d,以鼻子后面位置为脸部中心点,
而相机的位置则是模型的宇宙中心,给人脸打上468个点,精确贴合

注意

该服务虽然好用,功能强大,但是对于我大天朝来说,需要点要求
1。minSdk 版本24,也就是最少要7.0以上才支持
2。需要有支持ar的硬件,
3。需要有ARCore的服务,如果没有可以下载和升级,有些市场有有些可能需要VPN
楼主测试使用的是小米8测试机
好了下面就开始使用吧

使用

在项目的build.gradle中确保repositories中有google在

    repositories {
        google()
    }  

然后在app的build中引用arcore 我这里用的是1.15.0版本,

    implementation 'com.google.ar:core:1.15.0'
    // Provides ArFragment, and other UX resources.
    implementation 'com.google.ar.sceneform.ux:sceneform-ux:1.15.0'

    // Alternatively, use ArSceneView without the UX dependency.
    implementation 'com.google.ar.sceneform:core:1.15.0'
扩展ArFragment

要实现人脸增强,我们需要扩展Arfragment更改相机,以及session
具体代码如下:

/**
 public class FaceArFragment extends ArFragment {

  @Override
  protected Config getSessionConfiguration(Session session) {
    Config config = new Config(session);
    config.setAugmentedFaceMode(AugmentedFaceMode.MESH3D);
    return config;
  }

  @Override
  protected Set<Session.Feature> getSessionFeatures() {
    return EnumSet.of(Session.Feature.FRONT_CAMERA);
  }

  @Override
  protected void handleSessionException(UnavailableException sessionException) {
    String message;
    if (sessionException instanceof UnavailableArcoreNotInstalledException) {
      message = "请安装ARCore";
    } else if (sessionException instanceof UnavailableApkTooOldException) {
      message = "请升级ARCore";
    } else if (sessionException instanceof UnavailableSdkTooOldException) {
      message = "请升级app";
    } else if (sessionException instanceof UnavailableDeviceNotCompatibleException) {
      message = "当前设备部不支持AR";
    } else {
      message = "未能创建AR会话,请查看机型适配,arcore版本与系统版本";
      String var3 = String.valueOf(sessionException);
    }
    Toast.makeText(getContext(),"==" + message,Toast.LENGTH_LONG).show();
  }


  /**
   * Override to turn off planeDiscoveryController. Plane trackables are not supported with the
   * front camera.
   */
  @Override
  public View onCreateView(
      LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    FrameLayout frameLayout =
        (FrameLayout) super.onCreateView(inflater, container, savedInstanceState);

    getPlaneDiscoveryController().hide();
    getPlaneDiscoveryController().setInstructionView(null);

    return frameLayout;
  }
}

然后自己的布局:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".AugmentedFacesActivity">

  <fragment android:name="com.google.ar.sceneform.samples.augmentedfaces.FaceArFragment"
      android:id="@+id/face_fragment"
      android:layout_width="match_parent"
      android:layout_height="match_parent" />
  <TextView
      android:id="@+id/mTv"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="@string/app_name"/>

</FrameLayout>
设置人脸face—mesh

设置人脸face—mesh—ModelRenderable和faceMeshTexture

  private ModelRenderable faceRegionsRenderable;
  private Texture faceMeshTexture;
ModelRenderable.builder()
        .setSource(this, R.raw.fox_face)
        .build()
        .thenAccept(
            modelRenderable -> {
              faceRegionsRenderable = modelRenderable;
              modelRenderable.setShadowCaster(false);
              modelRenderable.setShadowReceiver(false);
            });

    // Load the face mesh texture.
    Texture.builder()
        .setSource(this, R.drawable.fox_face_mesh_texture)
        .build()
        .thenAccept(texture -> faceMeshTexture = texture);

    ArSceneView sceneView = arFragment.getArSceneView();
核心检测

然后对Arfragment的代码 其中包括算精确距离的方法

sceneView.setCameraStreamRenderPriority(Renderable.RENDER_PRIORITY_FIRST);

    Scene scene = sceneView.getScene();

    scene.addOnUpdateListener(
        (FrameTime frameTime) -> {
          if (faceRegionsRenderable == null || faceMeshTexture == null) {
            return;
          }

          Collection<AugmentedFace> faceList =
              sceneView.getSession().getAllTrackables(AugmentedFace.class);
          // Make new AugmentedFaceNodes for any new faces.
          for (AugmentedFace face : faceList) {
            if (!faceNodeMap.containsKey(face)) {
              AugmentedFaceNode faceNode = new AugmentedFaceNode(face);

              faceNode.setParent(scene);
              faceNode.setFaceRegionsRenderable(faceRegionsRenderable);
              faceNode.setFaceMeshTexture(faceMeshTexture);
              faceNodeMap.put(face, faceNode);
            }
          }

          // Remove any AugmentedFaceNodes associated with an AugmentedFace that stopped tracking.
          Iterator<Map.Entry<AugmentedFace, AugmentedFaceNode>> iter =
              faceNodeMap.entrySet().iterator();
          while (iter.hasNext()) {
            Map.Entry<AugmentedFace, AugmentedFaceNode> entry = iter.next();
            AugmentedFace face = entry.getKey();


            Pose left = face.getRegionPose(AugmentedFace.RegionType.FOREHEAD_LEFT);
            Pose right = face.getRegionPose(AugmentedFace.RegionType.FOREHEAD_RIGHT);
//              face.getm
               // AugmentedFace node
//              face.createAnchor(left);
//              face.createAnchor(right);
            float lx = left.tx();
            float ly = left.ty();
            float lz = left.tz();
            float rx = right.tx();
            float ry = right.ty();
            float rz = right.tz();
            double llength = Math.sqrt(lx * lx + ly * ly + lz * lz);
            double rlength = Math.sqrt(rx * rx + ry * ry + rz * rz);
            BigDecimal b1 = new BigDecimal(llength);
            BigDecimal r1 = new BigDecimal(rlength);
            double spec = b1.add(r1).divide(new BigDecimal("2")).multiply(new BigDecimal("100")).floatValue();
            Log.d("wzz","-----" + llength + "----" + rlength);
            Log.d("wzz","-----" + b1.add(r1).divide(new BigDecimal("2")));
            Log.d("wzz","-----" + decimalFormat.format((b1.add(r1).divide(new BigDecimal("2")))) + "m");
              mTv.setText("到屏幕距离: " + decimalFormat.format(spec) + "cm");

            if (face.getTrackingState() == TrackingState.STOPPED) {
                drawLine(face.createAnchor(left),face.createAnchor(right));
                AugmentedFaceNode  faceNode = entry.getValue();
              faceNode.setParent(null);
              iter.remove();
            }
          }
        });

好了到这就可以实现了,是不是贼简单,
关于人脸识别的坑,基本上都完结了,(pass opencv 2d to 3d)
有任何问题欢迎评论,讨论

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值