隐藏

【Xamarin.Android】添加面部跟踪和实时识别到您的Android应用程序

发布:2021/10/27 13:43:55作者:管理员 来源:本站 浏览次数:956



今天的相机应用可以做的不仅仅是拍完美的照片。无论是添加过滤器到您的图像或让您调整焦点和手动曝光,应用程序可以从根本上把你变成一个专业摄影师。虽然应用商店中的众多应用程序让你用相机做很多事情,还有其他人可以实时地对你的图像进行巧妙的操作,例如在脸上添加自定义掩码,操纵你的脸看起来更老或更年轻,和更多的。今天的社交媒体应用程序有这样的智能,所以你不必打开另一个应用程序让你的自拍看起来平凡的在你与朋友和家人分享。


无论是构建一个提供有趣过滤器的用户应用程序,还是一个识别收入的企业应用程序,添加像这样的智能轮胎让你比其他人更有优势。通过像微软认知服务API这样的服务,您只需添加几行代码即可快速分析和处理照片。


在这篇文章中,您将学习如何在Android应用程序中显示一个摄像头,通过使用Google的移动视觉的APIs添加面部跟踪并使用微软认知服务的API通过前置相机来识别人脸。


Face Detection

在应用程序中添加面部跟踪


Google的移动视觉提供了一组用于“检测面部”和“扫描条码”的API。对于这个示例,我将使用面部API从应用程序中的实时摄像机流中检测人脸。


开始, 添加 Xamarin.GooglePlayServices.Vision的 NuGet包。


为了在Android上访问相机,你需要在你的Android的mainifest中添加你的用户权限请求和相机功能:


点击(此处)折叠或打开


       

   if (ActivityCompat.CheckSelfPermission(this, Manifest.Permission.Camera) == Permission.Granted)

   {

       CreateCameraSource();

       //...

   }

   else

   {

   Log.Warn(TAG, "Camera permission is not granted. Requesting permission");

   

   var permissions = new string[] { Manifest.Permission.Camera };

   

   if (!ActivityCompat.ShouldShowRequestPermissionRationale(this,

           Manifest.Permission.Camera))

   {

       ActivityCompat.RequestPermissions(this, permissions, RC_HANDLE_CAMERA_PERM);

       return;

   }

   

   Snackbar.Make(mGraphicOverlay, Resource.String.permission_camera_rationale,

           Snackbar.LengthIndefinite)

           .SetAction(Resource.String.ok, (o) => { ActivityCompat.RequestPermissions(this, permissions, RC_HANDLE_CAMERA_PERM); })

           .Show();

   }



创建相机源


通过指定的属性使用FaceDetector.Builder创建FaceDetector的一个实例。在本例中,我们使用默认的面部检测器设置,并将处理器关联到它。


点击(此处)折叠或打开


   private void CreateCameraSource()

   {

   

       var context = Application.Context;

       FaceDetector detector = new FaceDetector.Builder(context)

               .SetClassificationType(ClassificationType.All)

               .Build();

   

       detector.SetProcessor(

               new MultiProcessor.Builder(this)

                       .Build());

   

       if (!detector.IsOperational)

       {

           // Note: The first time that an app using face API is installed on a device, GMS will

           // download a native library to the device in order to do detection. Usually this

           // completes before the app is run for the first time. But if that download has not yet

           // completed, then the above call will not detect any faces.

           //

           // isOperational() can be used to check if the required native library is currently

           // available. The detector will automatically become operational once the library

           // download completes on the device.

           Log.Warn(TAG, "Face detector dependencies are not yet available.");

       }

   

       mCameraSource = new CameraSource.Builder(context, detector)

               .SetRequestedPreviewSize(640, 480)

               .SetFacing(CameraFacing.Front)

               .SetRequestedFps(30.0f)

               .Build();

   

       

   }



在上面的代码中, MultiProcessor被用来接收侦测结果,CameraSource.Builder用来创建一个指定预览尺寸,相机面对面和所需的FPS的相机源。



在相机显示一个实时图像


现在我们已经进入相机并且建立CameraSource,我们也可以通过自定义一个SurfaceView开始预览;本例中CameraSourcePreview.GraphicOverlay实例也被传递,以便在检测时绘制面部边界。


点击(此处)折叠或打开


   private void StartCameraSource()

   {

   

       // check that the device has play services available.

       int code = GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable(

               this.ApplicationContext);

       if (code != ConnectionResult.Success)

       {

           var dlg =

                   GoogleApiAvailability.Instance.GetErrorDialog(this, code, RC_HANDLE_GMS);

           dlg.Show();

       }

   

       if (mCameraSource != null)

       {

           try

           {

               mPreview.Start(mCameraSource, mGraphicOverlay);

           }

           catch (System.Exception e)

           {

               Log.Error(TAG, "Unable to start camera source.", e);

               mCameraSource.Release();

               mCameraSource = null;

           }

       }

   }



调用StartCameraSource()最好的地方是在Activity的OnResume()中,在OnPause()中停止预览。它将确保只有在用户使用应用程序时才使用相机资源。

人脸检测


从相机源接收的每个图像帧可以包含多个面,并且每个面对应由由多处理器创建的跟踪器表示的明显的面部标识。

实现iFactory捕捉每个面


MultiProcessor要求实现IFactory,在相机检测到一个人脸时以便回调。在本例中,在MainActivity中实现了IFactory,包含了Create():


点击(此处)折叠或打开


   public Tracker Create(Java.Lang.Object item)

   {

       return new GraphicFaceTracker(mGraphicOverlay, mCameraSource);

   }



在上面的代码中,在每检测到一张人脸时都会创建GraphicFaceTracker的一个实例,每个构建人脸框图形对象在使用构造函数通过GraphicOverlay查看视频流。


下面是GraphicFaceTracker的一个实现:


点击(此处)折叠或打开


   class GraphicFaceTracker : Tracker

   {

       private GraphicOverlay mOverlay;

       private FaceGraphic mFaceGraphic;

   

       public GraphicFaceTracker(GraphicOverlay overlay)

       {

           mOverlay = overlay;

           mFaceGraphic = new FaceGraphic(overlay);

       }

   

       public override void OnNewItem(int id, Java.Lang.Object item)

       {

           mFaceGraphic.SetId(id);

       }

   

       public override void OnUpdate(Detector.Detections detections, Java.Lang.Object item)

       {

           var face = item as Face;

           mOverlay.Add(mFaceGraphic);

           mFaceGraphic.UpdateFace(face);

       }

   

       public override void OnMissing(Detector.Detections detections)

       {

           mOverlay.Remove(mFaceGraphic);

       }

   

       public override void OnDone()

       {

           mOverlay.Remove(mFaceGraphic);

       }

   }




在第一次检测到一张脸时会创建FaceGraphic的一个实例,在脸发生变化时会更新,当脸离开时会隐藏。


正是这样,我们成功地在应用程序中自定义的相机表面上创建了人脸跟踪!接下来,我们将识别帧内的人。

从实时流中识别脸


从实时视频帧中识别脸,每当检测到新的人脸并将其发送给微软认知服务API来识别此人时,我们就捕捉图像。人脸识别需要人工智能和高效的机器学习算法,提供给您的服务和免费开始。如果你是认知服务新手,我强烈推荐阅读博客文章,增加对移动应用程序的面部识别。

捕获检测到的人脸


捕捉新发现的人脸,首先改变GraphicFaceTracker实现CameraSource.IPictureCallback。


点击(此处)折叠或打开


   class GraphicFaceTracker : Tracker, CameraSource.IPictureCallback

   {

       //...

   }


修改OnNewItem()捕捉面部图像帧


点击(此处)折叠或打开


   public override void OnNewItem(int id, Java.Lang.Object item)

   {

       mFaceGraphic.SetId(id);

       if (mCameraSource != null && !isProcessing)

           mCameraSource.TakePicture(null, this);

   }




识别捕获帧中的人


最后,使用助手类ImageAnalyzer  和iveCamHelper (这些抽象了COGs API调用),我们从视频流中识别一个人。


点击(此处)折叠或打开


   public void OnPictureTaken(byte[] data)

   {

       Task.Run(async () =>

       {

           try

           {

               isProcessing = true;

   

               Console.WriteLine("face detected: ");

   

               var imageAnalyzer = new ImageAnalyzer(data);

               await LiveCamHelper.ProcessCameraCapture(imageAnalyzer);

           }

   

           finally

           {

               isProcessing = false;

           }

       });

   }


https://s3.amazonaws.com/blog.xamarin.com/wp-content/uploads/2017/06/12050912/En-Face.mp4

结束语


人脸识别在许多场景中被广泛使用,包括安全性,自然用户界面、机器人技术等等。通过使用这些服务和平台API的组合,你可以建立无与伦比的移动应用程序,智能和五星级用户提供经验。在这个博客文章,我们使用谷歌移动视觉API来检测视频流和微软认知服务中的人脸以识别帧内的人。在iOS上构建相同的示例,请阅读如何在iOS应用程序中显示相机 和 添加面部识别到您的移动应用程序。


在这篇文章中构建并解释的示例是由谷歌开发人员关于面部跟踪的文档启发的。


对于iOS和Android从我的GitHub的回购下载样本。 注意:对于这个演示,我编写了代码来识别框架中的一个单独的面。不过,请随意修改并使之变得更好。