基于Android和TensorFlow Lite的实时危险检测系统

在之前的系列文章中,已经为Android准备了训练有素的网络模型,创建了使用TensorFlow Lite的项目,并为解决方案的其他组件进行了工作。但直到现在,开发一直是使用静态图像进行的。在本篇文章中,将从使用静态图像切换到使用摄像头的实时视频流。编写的大部分代码无需修改即可工作。如果已经按照之前的文章进行操作,那么应该已经设置了应用程序的权限,以允许访问摄像头。

设置UI

本项目部分的UI将在AndroidStudio创建的全屏活动中构建。界面的内容将包含几个项目。一个TextureView在布局上显示摄像头的视频。InfoOverlayView,一个在本系列文章的前一篇文章中创建的视图,用于在视频流上方渲染高亮显示。

<androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/fullscreen_content" android:keepScreenOn="true"> <TextureView android:id="@+id/camera_preview" /> <net.j2i.drivinghazards.InfoOverlayView /> </androidx.constraintlayout.widget.ConstraintLayout>

TextureView不会自动显示视频流。相反,必须编写代码以更新来自视频摄像头的图像。当TextureView更新时,可以检索正在显示的帧的Bitmap,然后将该Bitmap传递给Detector。当TextureView准备好显示内容时,它会通知SurfaceTextureListener。创建一个SurfaceTextureListener并选择并打开摄像头。SurfaceTextureListener的接口如下所示。

class SurfaceTextureListener { fun onSurfaceTextureAvailable( surface: SurfaceTexture, width: Int, height: Int ) fun onSurfaceTextureSizeChanged( surface: SurfaceTexture, width: Int, height: Int ) override fun onSurfaceTextureDestroyed(surface: SurfaceTexture): Boolean override fun onSurfaceTextureUpdated(surface: SurfaceTexture) }

onSurfaceTextureAvailable和onSurfaceTextureUpdated函数是最感兴趣的函数。在onSurfaceTextureAvailable中打开摄像头,并在onSurfaceTextureUpdated中接收更新。

选择正确的摄像头

在这个简化的onSurfaceTextureAvailable实现中,应用程序获取摄像头ID列表,并逐个检查它们,直到找到不是前置摄像头的摄像头。对于大多数设备,将只有两个摄像头。一些设备支持通过USB连接第三个摄像头到手机上。如果想要使用支持外部摄像头的设备上的外部摄像头,并忽略内置摄像头,选择逻辑可以更改为过滤具有LENS_FACING属性值为LENS_FACING_FRONT的摄像头。函数openCamera是在代码中定义的函数,稍后将详细介绍。

override fun onSurfaceTextureAvailable( surface: SurfaceTexture, width: Int, height: Int ) { val cm = getSystemService(CAMERA_SERVICE) as CameraManager for (cameraID in cm.cameraIdList) { val characteristics = cm.getCameraCharacteristics(cameraID!!) if (characteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT) { continue //Skip front facing camera } mCameraID = cameraID openCamera() return } }

在openCamera函数中,使用CameraManager打开选定的硬件摄像头。UI布局中的TextView中的SurfaceTexture对象被分配了大小。还构建了预览的配置,设置了预览的宽度、高度和方向。

val manager = getSystemService(CAMERA_SERVICE) as CameraManager manager.openCamera(mCameraID!!, mCameraStateCallback!!, mBackgroundHandler) val texture = camera_preview!!.surfaceTexture texture!!.setDefaultBufferSize(previewSize!!.width, previewSize!!.height) val previewSurface = Surface(texture) mPreviewCaptureRequestBuilder = mCameraDevice!!.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW) mPreviewCaptureRequestBuilder!!.set(CaptureRequest.JPEG_ORIENTATION, mCameraOrientation) mPreviewCaptureRequestBuilder!!.addTarget(previewSurface)

图像捕获会话

配置完成后,可以开始捕获会话。摄像头将激活,将开始接收来自它的更新图像帧。

mCameraDevice!!.createCaptureSession( Arrays.asList(previewSurface), object : CameraCaptureSession.StateCallback() { override fun onConfigured(session: CameraCaptureSession) { if (mCameraDevice == null) return mPreviewCaptureRequest = mPreviewCaptureRequestBuilder!!.build() mCameraCaptureSession = session mCameraCaptureSession!!.setRepeatingRequest( mPreviewCaptureRequest!!, mSessionCaptureCallback, mBackgroundHandler ) } }, null )

更新的帧被传递回前面声明的SurfaceTextureListener。在其onSurfceTextureUpdated方法中,只需几行代码,就可以获取帧的Bitmap。这个Bitmap可以传递给检测器以寻找危险。

override fun onSurfaceTextureUpdated(surface: SurfaceTexture) { val bitmap = Bitmap.createBitmap( camera_preview!!.width, camera_preview!!.height, Bitmap.Config.ARGB_8888 ) camera_preview!!.getBitmap(bitmap) }

获取速度更新

在本系列文章的早期部分,提到不希望在车辆未移动时检测到危险时检测器发送警报。Detector实例必须接收当前速度的更新。在以下代码中,声明了一个LocationListener,它仅更新检测器的速度。然后使用位置提供程序请求将位置更新发送到位置侦听器。

fun requestLocation() { locationListener = LocationListener { location -> detector.currentSpeedMPS = location.speed } val locationManager = this.getSystemService(LOCATION_SERVICE) as LocationManager val provider = locationManager.getProvider(LocationManager.GPS_PROVIDER) val criteria = Criteria() criteria.accuracy = Criteria.ACCURACY_FINE val providerName = locationManager.getBestProvider(criteria, true) val isProviderEnabled = locationManager.isProviderEnabled(providerName!!) if (isProviderEnabled) locationManager.requestLocationUpdates( providerName, 1000, 1f, locationListener!! ) }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485