DashCam Android应用程序
该项目的主要目标是开发一个Android应用程序,该应用程序使用内置摄像头捕捉道路上的物体,并使用机器学习模型来获取相应物体的预测和位置。
您是否使用高通开发者网络上提供的某些硬件和/或软件创建了一个项目? 您想让它在高通开发者网络上展示吗? 告诉我们您的项目!
该项目旨在利用Qualcomm®神经处理SDK,该SDK允许您调整在Qualcomm®Snapdragon™移动平台上运行的AI应用程序的性能。 Qualcomm神经处理SDK用于将来自Caffe、Caffe2、ONNX和TensorFlow的训练模型转换为Snapdragon支持的格式(.dlc格式),使开发人员能够使用优化的设备端推理来启用其AI应用程序。
目标
该项目的主要目标是开发一个Android应用程序,该应用程序使用内置摄像头捕捉道路上的物体,并使用机器学习模型来获取相应物体的预测和位置。
所需材料/零件清单/工具
源代码/源代码示例/应用程序可执行文件
构建/组装说明
使用的零件
以下是此项目中使用的项目。
- 带QC Dash Cam应用程序的移动显示屏
- Snapdragon 835移动硬件开发套件
- 外部摄像头设置
部署项目
- 从GitHub存储库下载代码。
- 编译代码,并从Android Studio运行应用程序,以生成应用程序(apk)文件。
它是如何工作的?
QC_DashCam Android应用程序打开一个相机预览,收集所有帧并将其转换为位图。 网络是通过Neural Network builder构建的,通过传递caffe_mobilenet.dlc
作为输入。 然后将位图作为推理提供给模型,该模型返回对象的预测和相应对象的位置。
相机预览的先决条件。
在以下文件中授予获取相机预览帧的权限
AIML-DashCam-App/app/src/main/AndroidManifest.xml <uses-permission android:name="android.permission.CAMERA" />
为了使用camera2 API,添加以下功能
<uses-feature android:name="android.hardware.camera2" />
加载模型
用于神经网络连接和加载模型的代码片段
final SNPE.NeuralNetworkBuilder builder = new SNPE.NeuralNetworkBuilder(mApplicationContext) // Allows selecting a runtime order for the network. // In the example below use DSP and fall back, in order, to GPU then CPU // depending on whether any of the runtimes are available. .setRuntimeOrder(DSP, GPU, CPU) // Loads a model from DLC file .setModel(new File("<model-path>")) // Build the network network = builder.build();
捕获预览帧
Texture view用于渲染相机预览。 TextureView.SurfaceTextureListener
是一个接口,可用于在与此texture view关联的表面纹理可用时发出通知。
@Override public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i1) { Logger.d(TAG, "OnSurfaceTextureAvailable"); try { //id[0] indicates rear camera mCameraManager.openCamera(ids[0], mCameraCallback, mBackgroundHandler); } catch (CameraAccessException e) { e.printStackTrace(); } }
相机回调
相机回调,CameraDevice.StateCallback
用于接收有关相机设备状态的更新。 在下面的重写方法中,创建surface texture以捕获预览并获取帧。
@Override public void onOpened(@NonNull CameraDevice cameraDevice) { Logger.d(TAG, "onOpened()"); mCameraDevice = cameraDevice; mSurfaceTexture = mTextureView.getSurfaceTexture(); Surface mSurface = new Surface(mSurfaceTexture); try { mCameraDevice.createCaptureSession(Arrays.asList(mSurface), new CameraCapture(),null); } catch (CameraAccessException e) { e.printStackTrace(); } try { builder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); builder.addTarget(mSurface); } catch (CameraAccessException e) { e.printStackTrace(); } }
从Texture view获取位图
可以从TextureView
的onCaptureCompleted
回调中使用TotalCaptureResult
获取固定高度和宽度的位图。 可以压缩该位图并将其作为输入发送给模型。
@Override public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) { super.onCaptureCompleted(session, request, result); if (mNetworkLoaded) { Bitmap mBitmap = mTextureView.getBitmap(Constants.BITMAP_WIDTH, Constants.BITMAP_HEIGHT);
对象推理
位图图像转换为RGBA字节数组,大小为300 * 300 * 3。 基本图像处理取决于模型所需的输入形状的类型,然后需要将该处理后的图像转换为张量。 预测API需要类型为Float的张量格式,该格式返回对象预测和Map<String, FloatTensor>
对象中的位置。
private Map<String, FloatTensor> inferenceOnBitmap(Bitmap inputBitmap) { final Map<String, FloatTensor> outputs; try { if (mNeuralNetwork == null || mInputTensorReused == null || inputBitmap.getWidth() != getInputTensorWidth() || inputBitmap.getHeight() != getInputTensorHeight()) { return null; } // [0.3ms] Bitmap to RGBA byte array (size: 300*300*3 (RGBA..)) mBitmapToFloatHelper.bitmapToBuffer(inputBitmap); // [2ms] Pre-processing: Bitmap (300,300,4 ints) -> Float Input Tensor (300,300,3 floats) mTimeStat.startInterval(); final float[] inputFloatsHW3 = mBitmapToFloatHelper.bufferToNormalFloatsBGR(); if (mBitmapToFloatHelper.isFloatBufferBlack()) return null; mInputTensorReused.write(inputFloatsHW3, 0, inputFloatsHW3.length, 0, 0); mTimeStat.stopInterval("i_tensor", 20, false); // [31ms on GPU16, 50ms on GPU] execute the inference mTimeStat.startInterval(); outputs = mNeuralNetwork.execute(mInputTensorsMap); mTimeStat.stopInterval("nn_exec ", 20, false); } catch (Exception e) { e.printStackTrace(); return null; } return outputs; }
对象定位
模型返回相应的Float张量,从中可以推断出对象的形状及其名称。 Canvas用于在预测对象上绘制一个矩形。
private void computeFinalGeometry(Box box, Canvas canvas) { final int viewWidth = getWidth(); final int viewHeight = getHeight(); float y = viewHeight * box.left; float x = viewWidth * box.top; float y1 = viewHeight * box.right; float x1 = viewWidth * box.bottom; // draw the text String textLabel = (box.type_name != null && !box.type_name.isEmpty()) ? box.type_name : String.valueOf(box.type_id + 2); canvas.drawText(textLabel, x + 10, y + 30, mTextPaint); // draw the box mOutlinePaint.setColor(colorForIndex(box.type_id)); canvas.drawRect(x, y, x1, y1, mOutlinePaint); }
带有模型预测的应用程序的屏幕截图示例
使用说明
如何安装Android应用程序
- 您将需要一个Android手机,版本为7.0及以上。
- 在Windows / Linux系统中安装ADB。
- 按照以下说明在您的计算机上安装adb工具。 https://developer.android.com.cn/studio/command-line/adb.html
- 使用ADB工具和以下命令安装应用程序:
adb install qc_dashCam.apk
- 在手机中运行该应用程序。