为什么图像未被analyze()方法获取?

摘要/简而言之:机器学习对象检测应用程序无法检测对象,因为图像未被analyze()方法获取。



背景

我目前正在使用CameraX和Google ML Kit开发一款基于Java的移动应用程序。该应用程序的目的是通过实时摄像头预览来检测对象。我使用标题为“在Android上使用ML Kit检测和跟踪对象”的指南(基础模型选项)实现了ML Kit,以在应用程序中的连续帧内检测对象。

然而,在运行应用程序时,它在我的设备上启动,摄像头预览继续工作,但应用程序并未执行其预期的效果,即实际检测对象并在我的屏幕上显示。为了尝试解决这个问题,我找到了这个StackOverflow答案,它与这个问题非常相似。令我失望的是,该用户使用自定义模型(tflite)构建了他们的应用程序。这与我的不同,因为我使用的是基础模型。根据我的研究,这使用了ML Kit的设备内对象检测。所应用的代码仅限于上述文档中存在的代码。由于我的IDE(Android Studio)在语法上没有显示任何错误,我不确定为什么我的应用程序中似乎没有任何对象检测。以下是使用过的必要代码:

代码

public class MainActivity extends AppCompatActivity  {    private ListenableFuture<ProcessCameraProvider> cameraProviderFuture;    private class YourAnalyzer implements ImageAnalysis.Analyzer {        @Override        @ExperimentalGetImage        public void analyze(ImageProxy imageProxy) {            Image mediaImage = imageProxy.getImage();            if (mediaImage != null) {                InputImage image =                        InputImage.fromMediaImage(mediaImage, imageProxy.getImageInfo().getRotationDegrees());                //将图像传递给ML Kit Vision API                //...                ObjectDetectorOptions options =                        new ObjectDetectorOptions.Builder()                                .setDetectorMode(ObjectDetectorOptions.STREAM_MODE)                                .enableClassification()  // 可选                                .build();                ObjectDetector objectDetector = ObjectDetection.getClient(options);                objectDetector.process(image)                        .addOnSuccessListener(                                new OnSuccessListener<List<DetectedObject>>() {                                    @Override                                    public void onSuccess(List<DetectedObject> detectedObjects) {                                        Log.d("TAG", "onSuccess" + detectedObjects.size());                                        for (DetectedObject detectedObject : detectedObjects) {                                            Rect boundingBox = detectedObject.getBoundingBox();                                            Integer trackingId = detectedObject.getTrackingId();                                            for (DetectedObject.Label label : detectedObject.getLabels()) {                                                String text = label.getText();                                                if (PredefinedCategory.FOOD.equals(text)) { }                                                int index = label.getIndex();                                                if (PredefinedCategory.FOOD_INDEX == index) { }                                                float confidence = label.getConfidence();                                            }                                        }                                        imageProxy.close();                                    }                                }                        )                        .addOnFailureListener(                                new OnFailureListener() {                                    @Override                                    public void onFailure(@NonNull Exception e) {                                        Log.d("TAG", "onFailure" + e);                                        imageProxy.close();                                    }                                }                        );            }        }    }    @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        cameraProviderFuture = ProcessCameraProvider.getInstance(this);        PreviewView previewView = findViewById(R.id.previewView);        cameraProviderFuture.addListener(() -> {            try {                ProcessCameraProvider cameraProvider = cameraProviderFuture.get();                bindPreview(cameraProvider);            } catch (ExecutionException | InterruptedException e) {}        }, ContextCompat.getMainExecutor(this));    }    void bindPreview(@NonNull ProcessCameraProvider cameraProvider) {        PreviewView previewView = findViewById(R.id.previewView);        Preview preview = new Preview.Builder()                .build();        CameraSelector cameraSelector = new CameraSelector.Builder()                .requireLensFacing(CameraSelector.LENS_FACING_BACK)                .build();        preview.setSurfaceProvider(previewView.getSurfaceProvider());        ImageAnalysis imageAnalysis =                new ImageAnalysis.Builder()                        .setTargetResolution(new Size(1280,720))                        .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)                        .build();        imageAnalysis.setAnalyzer(ContextCompat.getMainExecutor(this), new YourAnalyzer());        Camera camera = cameraProvider.bindToLifecycle((LifecycleOwner)this, cameraSelector, preview, imageAnalysis);    }}

最终目标

如果需要任何视觉示例来理解预期效果应该是什么样,请看下面的图片。

输入图片描述

更新 [2021年4月11日]: 在我尝试通过Log.d(..)调试OnSuccess方法以确定返回对象列表的大小时,AS控制台在运行应用程序的几秒钟内打印了D/TAG: onSuccess0多达30次。这是否意味着应用程序没有检测到任何对象?自从我完全按照文档操作以来,这一直困扰着我。

更新 [2021年5月1日]:onSuccess方法中删除了DetectedObject[] results = new DetectedObject[0];这行代码。

for (DetectedObject detectedObject : results)现在使用”detectedObjects”而不是”results”,以反映文档中的代码。然而,onSuccess仍然记录D/TAG: onSuccess0,这进一步增加了关于为什么方法未获取任何数据的问题。


回答:

根据@Steven提供的这个简化的Google ML Kit示例应用程序版本,我通过实现lambda表达式并简化代码解决了这个问题,如下所示;

objectDetector.process(image)                        .addOnSuccessListener(detectedObjects -> {                            Log.d("TAG", "onSuccess" + detectedObjects.size());                        })                        .addOnFailureListener(e -> Log.e("TAG", e.getLocalizedMessage()))                        .addOnCompleteListener(result -> imageProxy.close());

在进行此更改后运行程序,应用程序成功启动,我的logcat打印出D/TAG: onSuccess1,表明确实检测到了一个对象!

然而,我确实想补充一点,这种微妙的代码编写差异让我想知道究竟是什么造成了这种差异。如果有人能解释为什么这段代码有效,而我之前发布的代码无效,我将非常感激这个解释。

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注