65.9K
CodeProject 正在变化。 阅读更多。
Home

在 Android AI 危险检测中使用 TensorFlow Lite 结果

starIconstarIconstarIconstarIconstarIcon

5.00/5 (2投票s)

2021年1月7日

CPOL

3分钟阅读

viewsIcon

5595

在本系列文章“Android上的AI危险检测”中,我们将解释结果并向用户提供相关信息。

这是关于在Android上使用TensorFlow Lite进行实时危险检测系列文章的第三篇。在上一篇文章中,我们将训练好的模型添加到Android项目中,并创建了一个用于传入图像的用户界面。

从TensorFlow Lite模型传递的信息是一个数字数组。这些数字本身并没有多大意义。出于我们的目的,我们不需要模型输出的所有信息。模型输出三个多维数组。最后一个数组包含我们想要的信息。最后一个数组有五个维度。每个维度的尺寸为[1][13][13][3][85]。数组中的元素是浮点数。

这个YOLO的实现将图像分成13列和13行。每一行或每一列中的每个单元格都是32x32像素。在每个单元格中,YOLO最多可以识别三个物体。有了这些知识,您可以很容易地推断出大小为13(列和行)的两个维度和大小为3(对于三个识别的物体中的每一个)的维度的含义。

最后一个维度,大小为85,需要更详细的解释。此数组中的前四个元素定义一个边界框(X,Y,宽度,高度)。第五个元素包含一个介于零和一之间的值,表示该框包含匹配项的置信度。接下来的80个元素包含匹配项是此YOLO模型识别的80个元素之一的概率。值最高的位置将分配给该物体。

识别物体

此模型还带有一个标签文件。要识别某个位置识别的物体,我们可以查看与物体索引匹配的行号。这80个元素中的第一个元素用于标签文件第一行中识别的物体。这80个元素中的第二个元素用于文本文件的第二行,以此类推。如果您使用的是使用不同训练集构建的YOLO模型,则此维度上的大小可能不同。使用此信息,我们现在可以在找到的物体周围绘制边界框。

有一些在屏幕上渲染轮廓的方法。我选择的方法是创建一个基于`View`的类并覆盖其`onDraw`方法。在`onDraw`方法中,视图接收一个用于渲染的画布。传递给此方法的画布具有由硬件功能支持的优点。通过其他方法(例如通过创建位图)获取画布会导致画布仅使用软件渲染。

此视图的大部分将透明地呈现。通过将其定位在显示正在处理的图像的视图上,可以与图像一起显示其他信息。

class InfoOverlayView(context: Context?, attr: AttributeSet?) :
   View(context, attr) {

   public enum class HighlightType(val highlightType: Int) {
       Warning(0x01),
       Attention(0x02)
   }

   var warningPaint: Paint
   var attentionPaint: Paint
   var highlightList: MutableList<Rect>
   var attentionList: MutableList<Rect>
   public override fun onDraw(canvas: Canvas) {
       super.onDraw(canvas)
       for(r in attentionList) {
           canvas.drawRect(r, attentionPaint)
       }
       for (r in highlightList) {
           canvas.drawRect(r, warningPaint)
       }
   }

   public fun clear() {
       highlightList.clear()
       attentionList.clear()
       invalidate()
   }

       public fun addHighlight(area:Rect, type:HighlightType) {
           when(type) {
               HighlightType.Warning -> highlightList.add(area)
               HighlightType.Attention->attentionList.add(area)
           }
           invalidate()
       }

   init {
       warningPaint = Paint()
       warningPaint.color = -0x7f010000
       warningPaint.style = Paint.Style.STROKE
       warningPaint.strokeWidth = 16f

       attentionPaint = Paint()
       attentionPaint.color=0x7fFFFF00
       attentionPaint.style = Paint.Style.STROKE
       attentionPaint.strokeWidth = 16f

       highlightList = ArrayList()
       attentionList = ArrayList()
   }
}

当我们想要突出显示一个区域时,我们可以使用`Rect`定义该区域并将其传递给`addHighlight`方法。此方法允许我们标记一个区域以表示警告(以红色呈现)或我们正在关注的内容(以绿色呈现)。每当将矩形添加到`View`时,`View`都会通过调用`invalidate`来标记自身需要重新渲染。

我们现在可以向用户显示屏幕上的识别结果。但是我们可能不想警告用户检测器识别的每一个物体。例如,检测器可以识别其他车辆。车辆预计会在路上,不应该触发任何警告。还有一些物体并不代表危险,因为它们不在车辆的行驶路径上。

界面不会仅仅依靠视觉效果来向用户提供反馈。如果用户可以收到音频警告,这样他们就不需要将视线从道路上移开,那就太好了。在本系列的下一篇文章中,我们将探讨如何避免不必要地警告用户,以及如何快速提醒他们。

© . All rights reserved.