Android环境下基于模型的应用开发

该文件位于com.ruturaj.detectlightning包中。com.ruturaj.detectlightning.mlkit包含所有对象检测所需的类文件。

首先,从包开始:

Java package com.ruturaj.detectlightning; import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.os.Bundle; import android.util.Log; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import com.google.mlkit.common.model.LocalModel; import com.google.mlkit.vision.objects.custom.CustomObjectDetectorOptions; import com.ruturaj.detectlightning.mlkit.CameraSource; import com.ruturaj.detectlightning.mlkit.CameraSourcePreview; import com.ruturaj.detectlightning.mlkit.GraphicOverlay; import com.ruturaj.detectlightning.mlkit.ObjectDetectorProcessor; import com.ruturaj.detectlightning.mlkit.PreferenceUtils; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity implements ActivityCompat.OnRequestPermissionsResultCallback {

在类全局范围内定义了一些重要的变量和字符串:

private static final String OBJECT_DETECTION_CUSTOM = "Lightning"; private static final String TAG = "MainActivity"; private static final int PERMISSION_REQUESTS = 1; private CameraSource cameraSource = null; private CameraSourcePreview preview; private GraphicOverlay graphicOverlay; private String selectedModel = OBJECT_DETECTION_CUSTOM;

如果熟悉Android生命周期,相信知道以下方法:

@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); preview = findViewById(R.id.preview_view); if (preview == null) { Log.e(OBJECT_DETECTION_CUSTOM, "Preview is null"); } graphicOverlay = findViewById(R.id.graphic_overlay); if (graphicOverlay == null) { Log.e(OBJECT_DETECTION_CUSTOM, "graphicOverlay is null"); } if (allPermissionsGranted()) { createCameraSource(selectedModel); } else { getRuntimePermissions(); } }

调用CameraSource类,将相机视图显示在屏幕上,使用模型:

if (allPermissionsGranted()) { createCameraSource(selectedModel); } else { getRuntimePermissions(); }

当模型在assets文件夹中运行时,调用LocalModel类来构建模型并检测对象。CustomObjectDetectorOptions通常用于相机视野中最重要对象的实时检测。

try { if (OBJECT_DETECTION_CUSTOM.equals(model)) { Log.e(OBJECT_DETECTION_CUSTOM, "Using Custom Object Detector Processor"); LocalModel localModel = new LocalModel.Builder().setAssetFilePath("model.tflite").build(); CustomObjectDetectorOptions customObjectDetectorOptions = PreferenceUtils.getCustomObjectDetectorOptionsForLivePreview(this, localModel); cameraSource.setMachineLearningFrameProcessor(new ObjectDetectorProcessor(this, customObjectDetectorOptions)); } else { Log.e(OBJECT_DETECTION_CUSTOM, "Unknown model: " + model); } } catch (Exception e) { Log.e(OBJECT_DETECTION_CUSTOM, "Can not create image processor: " + model, e); Toast.makeText(getApplicationContext(), "Can not create image processor: " + e.getMessage(), Toast.LENGTH_LONG).show(); }

一旦权限被授予,应用程序显示预览,就开始启动相机:

private void startCameraSource() { if (cameraSource != null) { try { if (preview == null) { Log.e(TAG, "resume: Preview is null"); } if (graphicOverlay == null) { Log.e(TAG, "resume: graphOverlay is null"); } preview.start(cameraSource, graphicOverlay); } catch (IOException e) { Log.e(TAG, "Unable to start camera source.", e); cameraSource.release(); cameraSource = null; } } }

以下代码维护AndroidUI生命周期,以防中断:

@Override public void onResume() { super.onResume(); Log.e(TAG, "onResume"); createCameraSource(selectedModel); startCameraSource(); }

应用暂停的处理方式如下:

@Override protected void onPause() { super.onPause(); preview.stop(); }

杀死应用会销毁相机预览:

@Override public void onDestroy() { super.onDestroy(); if (cameraSource != null) { cameraSource.release(); } }

onCreate调用后授予所需的权限:

private String[] getRequiredPermissions() { try { PackageInfo info = this.getPackageManager().getPackageInfo(this.getPackageName(), PackageManager.GET_PERMISSIONS); String[] ps = info.requestedPermissions; if (ps != null && ps.length > 0) { return ps; } else { return new String[0]; } } catch (Exception e) { return new String[0]; } }

私有方法allPermissionsGranted

private boolean allPermissionsGranted() { for (String permission : getRequiredPermissions()) { if (!isPermissionGranted(this, permission)) { return false; } } return true; }

私有方法getRuntimePermissions

private void getRuntimePermissions() { List allNeededPermissions = new ArrayList<>(); for (String permission : getRequiredPermissions()) { if (!isPermissionGranted(this, permission)) { allNeededPermissions.add(permission); } } if (!allNeededPermissions.isEmpty()) { ActivityCompat.requestPermissions(this, allNeededPermissions.toArray(new String[0]), PERMISSION_REQUESTS); } }

处理权限请求结果:

@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { Log.i(TAG, "Permission granted!"); if (allPermissionsGranted()) { createCameraSource(selectedModel); } super.onRequestPermissionsResult(requestCode, permissions, grantResults); }

私有静态方法isPermissionGranted

private static boolean isPermissionGranted(Context context, String permission) { if (ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED) { Log.i(TAG, "Permission granted: " + permission); return true; } Log.i(TAG, "Permission NOT granted: " + permission); return false; }

代码中有很多Log.e…的实例。这只是为了让Logcat检查在视觉上更加突出。当做e- Error日志时,轨迹以红色出现 - 很容易看到。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485