Качество изображения и частота кадров, которые я получаю при использовании API-интерфейса camera2, не соответствуют тому, которое я получаю, когда я вручную записываю видео с помощью приложения камеры в файл.
Я пытаюсь сделать реальныйвремя обработки изображений с помощью OpenCV на Android.Я вручную записал видео, используя встроенное приложение камеры, и все работало отлично: качество изображения было хорошим, частота кадров была стабильной 30 кадров в секунду.
Моя минимальная версия SDK - 22, поэтому я используюповторяющиеся запросы API Camera2.Я настроил его вместе с ImageReader и форматом YUV_420_888
.Я пробовал шаблоны запросов захвата PREVIEW
и RECORD
, пытался вручную установить 18 параметров запроса захвата в компоновщике (например, отключить автоматический баланс белого, установить быстрый режим коррекции цвета), но FPS былеще около 8-9, и качество изображения было плохим.Другой телефон дал те же результаты, несмотря на его максимум.FPS = 16,67 (вместо 30).
Виноват не моя обработка изображения (что происходит в другом потоке, кроме чтения буфера изображения): я проверял FPS, когда ничего не делал скадр (я даже не отображал изображение), оно все еще было около 8-9.
Вы можете увидеть соответствующий код для этого здесь:
//constructor:
HandlerThread thread = new HandlerThread("MyApp:CameraCallbacks", Process.THREAD_PRIORITY_MORE_FAVORABLE);
thread.start();
captureCallbackHandler = new Handler(thread.getLooper());
//some UI event:
cameraManager.openCamera(cameraId, new CameraStateCallback()), null);
//CameraStateCallback#onOpened:
//size is 1280x720, same as the manually captured video's
imageReader = ImageReader.newInstance(size.getWidth(), size.getHeight(), ImageFormat.YUV_420_888, 1);
imageReader.setOnImageAvailableListener(new ImageAvailableListener(), captureCallbackHandler);
camera.createCaptureSession(Collections.singletonList(imageReader.getSurface()), new CaptureStateCallback(), captureCallbackHandler);
//CaptureStateCallback#onConfigured:
CaptureRequest.Builder builder = activeCamera.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
builder.addTarget(imageReader.getSurface());
//setting the FPS range has no effect: this phone only has one option
session.setRepeatingRequest(builder.build(), null, captureCallbackHandler);
//ImageAvailableListener#onImageAvailable:
long current = System.nanoTime();
deltaTime += (current - last - deltaTime) * 0.1;
Log.d("MyApp", "onImageAvailable FPS: " + (1000000000 / deltaTime));
//prints around 8.7
last = current;
try (Image image = reader.acquireLatestImage()) { }