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

使用 AI 危险检测向 Android 驾驶员发出警报

starIconstarIconstarIconstarIconstarIcon

5.00/5 (2投票s)

2021年1月8日

CPOL

3分钟阅读

viewsIcon

6185

在本系列“Android 上的 AI 危险检测”的下一篇文章中,我们将探讨如何避免不必要地警告用户,以及如何快速提醒他们。

这是关于使用 Android 构建实时危险检测器的系列文章的第四篇。 在之前的文章中,我们探讨了如何在屏幕上突出显示对象。 我们还注意到,并非检测到的每个对象都是我们想要提醒用户的。 检测器识别的其他对象包括鸟类和其他车辆,这两者都不是我们想要提醒用户的内容。 检测器确实可以识别人和各种动物。 我们会希望收到这些对象的警报。 如果汽车没有移动,那么可能根本不需要提醒用户;当汽车等待时,行人穿过街道是一种场景,识别出的实体进入了手机的视野,但在这种情况下,我们希望系统不要发出警报。

为了避免不必要地提醒用户,我们将创建一个选择加入列表,其中包含应生成警报的对象。 除了 TensorFlow Lite 模型和标签文件之外,我还添加了一个名为 concerns.txt 的新文件。 concerns.txt 的每一行都包含从 labels.txt 复制的一行,该行是检测器将发出警报的内容的标签。 检测器以与加载标签相同的方式将这些加载到列表中。

if(concernList.size() == 0) {
   InputStream concernStream = context.getAssets().open("concerns.txt");
   BufferedReader br = new BufferedReader(new InputStreamReader(concernStream));
   String line;
   while(null != (line = br.readLine())) {
       Log.i(TAG, String.format("Concern: %s", line));
       concernList.add(line);
   }
}

声音是提醒用户的一种选择。 如果设备有立体声扬声器,我们可以通过生成通过左扬声器、右扬声器或两个扬声器播放的声音来利用它们,从而快速指示危险的大致方向。 为了实现这一点,我制作了三个声音文件并将它们添加到了项目的资源中。 这些声音文件位于文件夹 app/src/res/raw 中。 声音文件已添加到我们可以在代码中引用的资源中。 我定义了一些常量来保存声音文件的 ID,以便更轻松地引用它们。 还需要一个变量来引用 MediaPlayerMediaPlayer 将负责播放声音。

val ALARM_LEFT: Int = R.raw.left_sound
val ALARM_RIGHT: Int = R.raw.right_sound
val ALARM_CENTER: Int = R.raw.center_sound
var soundPlayer: MediaPlayer? = null

使用其中一个声音值创建一个 MediaPlayer 对象,会为我们提供一个可以播放警报声音的对象。

防止持续警报

为了防止在驾驶员未移动时发送警报,用户必须超过最低速度。 如果用户低于此速度,则不会生成声音警报。 Android 的位置服务以米/秒为单位返回速度。 在考虑驾驶速度时,我更倾向于考虑公里/小时。 为了设置最低速度,我定义了一个常量来设置最低公里/小时,另一个常量使用第一个常量来表示相同的速度(以米/秒为单位)。

val MIN_ALERT_KMPH:Float = 10.0f
val  MIN_ALERT_MPS:Float = MIN_ALERT_KMPH*1000.0f/(60.0f*60.0f)

检测器将收到有关车辆当前速度的更新。 对于测试界面(用于调试和测试),速度将在代码中设置,而不依赖于车辆的实际移动。

为了避免持续提醒用户关于危险,设置了一个冷却时间,然后才会发出另一个警报。 当我们尝试发出警报时,我们首先检查是否已经存在一个尚未过期的警报。 如果到期时间尚未过去,则不会发出警报。 尝试发出警报也会重置冷却时间。

var coolDownExpiry:Long = 0
val COOL_DOWN_TIME = 10000

fun resetCooldown() {
   coolDownExpiry = Date().time + COOL_DOWN_TIME
}
fun hasCooldownExpired():Boolean {
   val now = Date().time
   return now > coolDownExpiry
}



fun alert(direction: Int) {
   // using the when statement to filter out invalid
   // values should they be passed to this function
   if(hasCooldownExpired() && currentSpeedMPS>MIN_ALERT_MPS) {
       when (direction) {
           ALARM_CENTER, ALARM_RIGHT, ALARM_LEFT -> {
               soundPlayer = MediaPlayer.create(context, direction)
               soundPlayer!!.start()
           }
       }
   }
   resetCooldown()
}

该应用程序所需的大部分功能现在都已到位。 最后要添加的几件事是碰撞检测以及紧急警报,并让应用程序使用实时摄像头流而不是用户选择的图像。 在本系列的下一篇文章中,我们将探讨碰撞检测和通知。

© . All rights reserved.