ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

在你可以使用 Flutter Camera 进行实时机器学习之前。

2022-09-09 10:00:08  阅读:342  来源: 互联网

标签:Image 实时 毫秒 Camera iPhone 图像 Flutter


在你可以使用 Flutter Camera 进行实时机器学习之前。

最近被指派在Flutter上实时做ML(机器学习)。在完成之前,会有一定程度的问题和障碍混在一起后我可以活一个月或更长时间。我坐下来想,好吧,让我们为这个案例写一个博客,最好保留它。以后我会回来看看,以防万一有人感兴趣。这样你就不必再浪费时间看起来像我了。我会告诉你之前必须做什么?

Flutter with Real-time ML

对于那些赶时间的人 您可以滚动到底部。我有一个示例代码向您展示如何做到这一点。但是对于那些想知道我做了什么的人,我不会重复它。您可以在下面跟随。

我要做的 ML 任务是使用 Flutter 通过应用程序检查人脸,ML 系统会检查发送到后端系统的人脸是否为真人。由自拍引起,而不是再次被拍成照片的脸部照片通常在过去我们会开设那个银行账户。我们将需要使用身份证并步行到银行分行。但是现在我们可以通过应用程序做很多事情。包括开设银行账户因此,我们需要一个过程来验证人脸是真实的。并且有一张笔直且靠近身份证的图片,我们将在这部分使用ML来帮助在这种情况下,我们将以 Flutter 为例。过程是我们将图像发送到 ML 并检查页面是否真实。当验证它是一个真实的页面时我们会将图片发送到服务器,以检查人脸是否与身份证图片相同或接近。

第一个版本

我每 1 秒循环一次自拍,在 Flutter 中将其转换为二进制 UInt8List,然后将值传递给 Native 以创建图像,然后将其发送到 ML。我想快速完成,以便测试 SDK 是否有效。整体画面是可行的。但它只会是一台强大的机器。只要因为每 1 秒的照片处理大约需要 300-400 毫秒进行二进制转换。将图像发送回Native并检查Liveness。结果,我们只剩下600毫秒可以重新开始拍照。300-400毫秒是我的iPhone 11 Pro max,相当强大。我在我的 iPhone X 上试了一下,它花了我 1200 毫秒,所以它无法在 1 秒内完成这项工作,所以它不能算作对所有设备的实时监控。最重要的是,iOS 也有声音,导致糟糕的用户体验,但我认为这对于初始测试来说很好。至少我们的测试人员能够继续测试系统。将第一个版本发送给测试人员后,将有一个条件是只测试最强的机器。我立即开始研究第二个版本。

第二版

因为赶时间拍照这对于实时的 liveness 来说还不够快,我做了更多的研究,发现 Native 使用来自 Camera 的 Live Feed 将其发送到 ML,所以我试图找出 Flutter Camera 是否有类似的东西。我找到了

在颤振相机中 https://pub.dev/packages/camera 有一个函数叫startImageStream 流式传输图像。

 controller.startImageStream((cameraImage)异步{  
 // 将图像输入 ML });

我们得到的是 CameraImage,通常如果我们对该图像进行 ML。大多数人会使用 Firebase,它已经继承了一个 CameraImage,所以很容易做很多工作。

但在某些情况下,我们的工作可能不适合 Firebase,我们必须使用自己的 ML。当然,大多数 SDK 都不是为 Flutter 设计的,导致 Flutter 格式的 CameraImage 无法使用。所以我们需要将一些数据处理成这些 SDK 使用的格式。这对 Flutter 来说是个大问题,因为大部分 SDK 都接受 RGB 格式的图片,比如 JPG 或 PNG。Flutter 的 CameraImage 也可以转换 JPG,但是只有 Android 和 iOS 需要转换。自己下载的。从阅读文档看来,Flutter Camera 只支持 YUV420 和 BGRA8888 两种格式,我决定还是用 BGRA8888 更好,因为 YUV420 从阅读 Documents 看起来更像是视频。

Camera Image Documentation

既然Android已经是JPG格式了,就没事了,我们什么都不用做,只有iOS我们这里要做JPG,研究了一下,找到了这个GitHub。

我跟着他,按我的要求把 JPG 拿回来了,但表现不如预期。如果您尝试仅使用一张图像,则没有问题。但是因为我们必须一直处理并不断发送照片,导致 iOS 出现抖动,无法按预期流动。其中,查看后发现Camera Image每20-30毫秒发送一次图像。

为此,我添加了Throttling功能,即不管发送多少Camera Image。我会改为每 500 毫秒运行一次,但在 30 毫秒和 500 毫秒之间进行测试后,在我的情况下似乎没有太大区别。它看起来仍然是实时的。因为当我们检查我们的脸在屏幕的中央,并没有太大的移动。让用户无法区分我们每 500 毫秒而不是 30 毫秒处理一次,iOS 仍然生涩。哪怕再好一点

厌倦了iOS,让我们换个安卓休息一下吧。它看起来更具未来感,因为它已经是JPG,至少对于一个平台来说是这样。所以当我们点Camera Image为JPG的时候,性能很好,流畅,Flutter端没问题,但是在Kotlin的部分做image的时候被推到stick。问题是ooh

为什么Camera Image出来的图片是旋转了90度!!!

我惊呆了,人类世界哪里有用例?即使我们正在拍摄一张直脸的照片,我们也想要一张旋转 90 度的照片?!?!但是世界各地的人们都在使用 Flutter Camera,一定有一些事情让他们这样做。因此,我使用 Kotlin 中的 Matrix 查找 Kotlin 代码,将其再旋转 270 度以使其笔直,并从该二进制文件生成位图。结果是可以在一定水平上执行的中档Android。但会抽搐一点由于我们做了很多事情,包括创建照片、旋转照片,而 ML 又开始工作了,这需要大量的精力。但最终,它比我以前做的连续照片要好。 Android 现在已经足够了。它可以工作,但仍然滞后,所以让我们到此为止。

现在,回到 iOS,让我们看看如何让它不那么抽搐。现在让我们坐下来看看 Flutter 中的 Threading,我一直在关注这篇文章。

[

Dart 中的并发

Dart 支持使用 async-await、isolate 和诸如 Future 和 Stream 之类的类进行并发编程。此页面提供...

飞镖开发

](https://dart.dev/guides/language/concurrency)

通常我不必在 Flutter 中搞乱线程,因为 等待 它不会阻塞 UI 线程,这与我经常使用线程来执行计算密集型任务的 iOS 不同。

我尝试了使用 Flutter 中的 Image Lib 将 BGRA 转换为 RGB 的 Threading and Isolate。

[

图片 |飞镖包

为服务器和 Web 应用程序提供加载、操作和保存具有各种图像文件格式的图像的能力,包括……

发布开发

](https://pub.dev/packages/image)

试了之后,天哪,果然是另一个世界。iPhone X流畅流畅,像黄油一样光滑(感谢防弹少年团)

做了第二个版本后,iOS和Android Mid-Tier都运行良好,于是我和一大群人一起试了试,我只试了3-4台设备,看起来还是不错的。

但是在对一大群 20 台设备进行试验时,Android 的一个大问题是 Flag JPG 无法正常工作。 图像格式组.jpeg 将在研究中的某些设备上崩溃有些人真的

[

为什么在相机流式传输时日志中出现无效的“格式”?

感谢您为 Stack Overflow 提供答案!请务必回答问题。提供详细信息并分享...

stackoverflow.com

](https://stackoverflow.com/questions/69785612/why-am-i-getting-invalid-format-in-logs-while-camera-streaming#comment128143146_69785612)

我从以下机器收到错误。 GetYUVPlaneInfo:传递的格式无效:0x21

小米Note 8机器在打开Image Stream for JPG时会死机,但是如果设置为Default YUV420则没有问题。让我担心它是否只是这个。或者如果你去市场可能有其他设备。

尝试查找信息后我决定我应该使用 YUV420,因为它是 Camera Image 中的默认格式,这应该不是问题。但是,我不想为 Flutter 冒险 JPG,所以我不得不想办法在 Native 上将 YUV420 转换为 RGB JPG。我在网上找到了下面的示例代码。

 列表<int>strides = Int32List(image.planes.length * 2); 整数索引 = 0; 列表<Uint8List>数据 = image.planes.map((平面){ 跨步[索引] = (plane.bytesPerRow); 索引++; strides[index] = (plane.bytesPerPixel)!; 索引++; 返回平面.字节; }).toList(); 等待_channel.invokeMethod<Uint8List> ("checkLiveness", { “平台”:数据, “高度”:图像.高度, '宽度':图像.宽度, “跨步”:跨步 });

我为编写此代码的人感到抱歉。我想感谢创建这部分的人。但是我找不到原版。如果有人找到分享此部分的人请通知我。我将编辑文章以添加信用。

对于 Android 端,我在下面的链接中找到了从 YUV 转换为 JPG 的代码。

[

将 YUV_420_888 转换为 JPEG 并保存文件导致图像失真

我在我的 git repo 中使用了 https://stackoverflow.com/a/40152147/2949966 中提供的 ImageUtil 类……

stackoverflow.com

](https://stackoverflow.com/questions/44022062/converting-yuv-420-888-to-jpeg-and-saving-file-results-distorted-image)

当一切都完成它像往常一样工作正常。但还是有点抽搐因为主要工作现在,我们只修复了 Crash 问题,并没有影响任何性能,是时候让我改进这部分了。

我们先从Android说起,我对Kotlin Coroutine做了一些研究并使用了它,发现使用Threading之后,Android比以前流畅多了。现在,我拥有的每一个Android。即便是像OPPO a3s,2018年,售价4000泰铢左右的老机,还是很流畅的。以安卓结束,结果我很满意,就是iOS的排队。

然后来了…… 最终版本

现在是时候看看我们可以用旧版本的 iOS 做什么了iPhone X上没问题,XS可以正常使用但仔细观察,虽然 Isolate 帮助应用不卡顿,但对于 iPhone 6s 来说,转换 BGRA 大约需要 1.5 秒。这不包括必须将其发送到 Liveness,而较旧的机器又需要 1.5 秒也是。这意味着自从我们开始发送图片系统最多需要 3 秒才能完成所有检查,使其无法按预期工作。所以我决定将转换后的部分拉到 Native 上,看看我们是否可以将 1.5s 减少到 0.5s,但结果令人震惊。我能够将处理时间从 1.5 秒减少到只有 0.01 秒!!!如何在 Swift 中转换我在本文底部的 GitHub 存储库中进行了分享。但下面是用于转换图像的示例代码。

**私人的** **功能** bytesToPixelBuffer(宽度:Int,高度:Int,baseAddress:UnsafeMutableRawPointer,bytesPerRow:Int)-> CVBuffer? { **曾是** dstPixelBuffer:CVBuffer? CVPixelBufferCreateWithBytes(kCFAllocatorDefault,宽度,高度,kCVPixelFormatType_32BGRA,baseAddress,bytesPerRow, **零** , **零** , **零** , &dst像素缓冲区) **返回** dstPixelBuffer ?? **零** } **私人的** **功能** createImage(来自pixelBuffer:CVPixelBuffer)-> CGImage? { **曾是** CGImage:CGImage? VTCreateCGImageFromCVPixelBuffer(pixelBuffer, 选项: **零** , 图像输出: &cgImage) **返回** CG图像 } **私人的** **功能** createUIImageFromRawData(data: Data, imageWidth: Int, imageHeight: Int, bytes: Int) -> UIImage? { data.withUnsafeBytes { rawBufferPointer **在** **让** rawPtr = rawBufferPointer.baseAddress! **让** 地址 = UnsafeMutableRawPointer(mutating:rawPtr) **警卫** **让** pxBuffer = bytesToPixelBuffer(宽度:imageWidth,高度:imageHeight,baseAddress:地址,bytesPerRow:字节), **让** cgiImage = createImage(来自:pxBuffer) **别的** { **返回** **零** } **返回** UIImage(cgImage:cgiImage) }

最后一个我无法修复的部分来了,那就是 Flutter Image Stream。

在性能方面,即使我创建一个什么都没有的简单项目,不做任何工作,做出 Flutter Camera 和 Stream Image,Low Tier 仍然落后。于是在Preview页面尝试不开启Image Stream功能,发现相机和其他机器一样流畅。没问题它表明我们不能在旧机器上打开 Image Stream。但是如果打不开,Liveness怎么办?

当我想到它时,我们实际上打开了 Image Stream,但我们每 500 毫秒只需要一张图像。如果我们打开相机并立即将其关闭怎么办?我尝试只打开 50 毫秒,结果发现在 50 毫秒内我们得到了大约 1-2 张照片,这对于 Liveness 来说已经足够了。然后我们立即关闭它。iPhone 7 看起来很流畅。iPhone 6s 和iPhone. 6s Plus 好多了,生涩几乎察觉不到。我做了下面的实验来看看 Flutter Camera 的性能,在这个例子中是一个只有 Camera 的 Flutter App。没有任何工作

性能检查

iPhone 11 Pro Max — 53% CPU、190MB 内存每 20-40 毫秒获取一张图像

iPhone 6s — 118% CPU,160MB 内存每 20-30 毫秒获取一张图像

iPhone 6s Plus — 138% CPU、187 MB 内存每 20-50 毫秒获取一张图像。

关闭相机流的 iPhone 6s Plus,只是相机预览,使用 46% 的 CPU

开启和关闭 Image Stream 的 iPhone 6s Plus 的 CPU 似乎在 50%-70% 左右。

虽然 Android Oppo A3s Low-Tier (2018) Andriod 8.1.0, 2GB Ram 的性能仍然比 iPhone 6s 好很多,即使我一直打开 Image Stream,它也只使用 14% 的 CPU 和大约 320 MB Ram。

所以让我们试试如果我在 Native Camera 中轻松打开 iPhone 6s Plus 的相机,它会看到它使用了 57% 的 CPU,39.1 MB 等于 CPU。我们使用相同,但 RAM 会非常不同。

来到最后一步我们还有一个问题,就是上面分享的 UIImage 图片。我们在使用镜像的时候,遇到了线程1的问题:EXC_BAD_ACCESS。

我使用 CGDataProvider_BufferIsNotBigEnough 搜索了相关关键字。找到解决办法似乎他们中的大多数人根本没有与我的问题相匹配的答案。有人告诉我,我用的是大图。或者头发太旧但即使是我的 iPhone 11 Pro Max 也有问题。好吧,可能不是。很多事情我都想办法解决,放一些小图,喂图放慢一些,但都没有消失,这让我头晕目眩。我不知道该怎么继续,我已经迷茫了1-2天,并且尝试过错误和错误。直到最后我才明白 SDK 会返回我们反馈给我们的图像。表明我们输入的图像不可用。所以我试着从那个部分搜索。并且发现插入的图片发送的UIImage是一个Reference,而不是Value Type,所以我们只好把它拷贝出来作为Value Type来使用,于是我们得到了关于Deep Copy PixelBuffer的Keywords继续google。反复试验,直到结束。它完成了。解决所有问题。真的。

我正在猜测

ไม่มีข้อโต้แย้งใดๆ

TL;博士 妈妈求你不要在 Flutter 中做 Real-time ML,去本地做,然后把结果发回 Flutter。我觉得这个方法要容易得多。而不是像我一样在 Flutter 中找出不同的方法。

哦,所以我不提倡在 Flutter 中这样做?是的,我不支持如果使用 Flutter 的目的是为了让我们的工作变得简单。工作更快如果你不能做到这一点,那我们为什么要使用它?别担心,Flutter 并不是世界上终极的全能语言。能做到的,我们都能做到。做不到的,不用勉强。

下面是我实现的一个示例代码,用于将所有Camera Image图像转换为JPG以供SDK使用。如果有人坚持我想在Flutter中做,因为各种原因,我可以采取示例方面。下面可以用来学习。

[

GitHub — theamorn/flutter-stream-image

一个新的 Flutter 项目。该项目是 Flutter 应用程序的起点。一些资源可以帮助您入门……

github.com

](https://github.com/theamorn/flutter-stream-image)

下面是一个示例视频,展示了 Flutter Stream Performance 在每台机器上的表现。

下面是一个在 Flutter 中使用的例子,它看起来像这样。

结论

Flutter Camera 不适合旧设备,因为 Flutter 会一直发送图片。让它工作起来很费劲,但是如果 Flutter Camera 可以得到一个参数,表示你要发回的图像是多少帧率,那就很好了,因为在某些用例中我们确实需要高细节的图像,但有些用例不需要。您需要实时速度。就像我的这个案例我宁愿每 200 毫秒获取一张图片,也不愿获取 20-30 毫秒的格式,如果解决这个问题,可以将功耗降低多达 90%!

我认为已经被请求了 2 年的人想到了。

[

在 Camera 插件中设置自定义帧率和比特率 · Issue #54339 ·flutter/flutter

新功能没有损坏;请求新的能力。相机插件p:由...开发的第一方插件

github.com

](https://github.com/flutter/flutter/issues/54339)

从反馈来看,短期内不太可能上线。我想如果你真的想要实时,就去Native吧。其实,如果有机会,我想打开PR修复它。

看过这篇文章,有兴趣在工作中使用 Liveness 的朋友,无论是 Flutter 还是 Native,请联系 KBTG 或我。我会将此事发送给相关团队。KBTG Face Liveness 已通过 ISO 30107-3 标准,由 iBeta 测试,是 SDK Liveness 的世界标准。

根据网站

[

ISO 30107–3 演示攻击检测测试方法和确认信

访问帖子了解更多信息。

www.ibeta.com

](https://www.ibeta.com/iso-30107-3-presentation-attack-detection-confirmation-letters/)

对于任何对这样的好故事感兴趣的技术人员。或者想了解KBTG的新产品,可以关注官网的详细介绍。 www.kbtg.tech

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明

本文链接:https://www.qanswer.top/22874/54230909

标签:Image,实时,毫秒,Camera,iPhone,图像,Flutter
来源: https://www.cnblogs.com/amboke/p/16671731.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有