ФОН
Мое приложение, использующее CameraX и Google ML Kit, написано на Java. Назначение приложения - обнаружение объектов с помощью предварительного просмотра камеры в реальном времени. Я реализовал ML Kit, используя это руководство с метким названием Обнаружение и отслеживание объектов с помощью ML Kit на Android (опция базовой модели) для обнаружения объектов в последовательных кадрах в приложении. Конечная цель моего кода состоит в том, чтобы объекты обнаруживались в реальном времени вот так:
ПРОБЛЕМА
Несмотря на то, что приложение было успешно запущено, оно не могло наносить надписи на дисплей, несмотря на то, что для этого был введен код. Само приложение способно обнаруживать объекты, просто отсутствует визуальное отображение. Фактически, все, что присутствует в приложении, - это только мой предварительный просмотр камеры, без ограничивающей рамки, охватывающей какой-либо обнаруженный объект. В моем коде, показанном ниже, указано поле, и я понимаю, что я должен нарисовать boundingBox сам, и мой вопрос конкретно нацелен на то, как я буду пытаться его нарисовать.
КОД
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) {
//Log.d("TAG", "mediaImage is throwing null");
InputImage image =
InputImage.fromMediaImage(mediaImage, imageProxy.getImageInfo().getRotationDegrees());
//Pass image to an ML Kit Vision API
//...
ObjectDetectorOptions options =
new ObjectDetectorOptions.Builder()
.setDetectorMode(ObjectDetectorOptions.STREAM_MODE)
.enableClassification() // Optional
.build();
ObjectDetector objectDetector = ObjectDetection.getClient(options);
objectDetector.process(image)
.addOnSuccessListener(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();
int index = label.getIndex();
float confidence = label.getConfidence();
}
}
})
.addOnFailureListener(e -> Log.e("TAG", e.getLocalizedMessage()))
.addOnCompleteListener(result -> 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) {
// No errors need to be handled for this Future.
// This should never be reached.
}
}, 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);
}
}
Я должен добавить, что здесь был аналогичный вопрос, который столкнулся с аналогичной проблемой, хотя разница между нашими вопросами заключается в том, что этот пользователь использовал пользовательскую модель детектора объектов, тогда как я использовал базовую модель. Кроме того, этот пользователь смог решить свою проблему, выбрав оптимальную модель TensorFlow, которая была бы совместима с их уже установленным кодом.
Любая информация, необходимая для дополнения этого вопроса, будет предоставлена по запросу.
ПОПЫТКИ
ПОПЫТКА 1 [12 июня 2021 г.]: я добавил следующий код в метод onSuccess, используя этот ответ StackOverflow, чтобы попытаться нарисовать оверлей на моем дисплее приложения, и задаетесь вопросом, почему эта попытка не сработала?
.addOnSuccessListener(detectedObjects -> {
Log.d("TAG", "onSuccess" + detectedObjects.size());
for (DetectedObject detectedObject : detectedObjects) {
Rect boundingBox = detectedObject.getBoundingBox();
int left = boundingBox.left;
int top = boundingBox.top;
int right = boundingBox.right;
int bottom = boundingBox.bottom;
ShapeDrawable drawable = new ShapeDrawable();
drawable.getPaint().setColor(Color.RED);
drawable.getPaint().setStyle(Paint.Style.STROKE);
drawable.getPaint().setStrokeWidth(5f);
Integer trackingId = detectedObject.getTrackingId();
for (DetectedObject.Label label : detectedObject.getLabels()) {
String text = label.getText();
int index = label.getIndex();
float confidence = label.getConfidence();
}
}
})