Запись видео и одновременная обработка кадров в Android с помощью CameraX ⇐ Android
Запись видео и одновременная обработка кадров в Android с помощью CameraX
Я работаю над приложением, моя цель — распознавать лица, распознавать моргание глаз и одновременно записывать видео. Итак, для этого мне нужно записать видео и в то же время я хочу обработать кадры, чтобы обнаружить моргание лица и глаз. Для этого я использую Camerax. В этом случае существуют некоторые ограничения Android:
[*]Мы не можем одновременно записывать видео и использовать методы анализа изображений cameraX. [*].setClassificationMode(FaceDetectorOptions.CLASSIFICATION_MODE_ALL) замедлит обработку кадров, как это также упоминается в документации MLKit, поэтому в моем случае мне нужна очень быстрая обработка кадров, поэтому я тоже не могу ее использовать.
Зависимости, которые я использую:
// Зависимости CameraX защита camerax_version = "1.2.0" реализация "androidx.camera:camera-camera2:${camerax_version}" реализация "androidx.camera:camera-lifecycle:${camerax_version}" реализация "androidx.camera:camera-view:${camerax_version}" реализация "androidx.camera:camera-video:${camerax_version}" // Google mMLKit для обнаружения лиц (отдельно) реализация 'com.google.android.gms:play-services-mlkit-face-detection:17.1.0' Предварительный просмотр в XML-файле:
Настройка камеры:
@Nullable защищенный ProcessCameraProvider cameraProvider; @Nullable частный предварительный просмотрUseCase; частный VideoCapture videoCapture; частный CameraSelector cameraSelector; частная пустота initCamera() { пытаться { cameraSelector = новый CameraSelector.Builder().requireLensFacing(CameraSelector.LENS_FACING_FRONT).build(); новый ViewModelProvider(это, (ViewModelProvider.Factory) ViewModelProvider.AndroidViewModelFactory.getInstance(getApplication())) .get(CameraXViewModel.класс) .getProcessCameraProvider() .observe(getViewLifecycleOwner(), провайдер -> { cameraProvider = поставщик; BindAllCameraUseCases(); }); } catch (Исключение е) { } } /** * метод для инициализации случаев использования привязки камеры * проверит поставщика камеры, отменит предыдущие варианты использования * и вызовет дополнительный метод для привязки вариантов использования камеры */ частная недействительностьbindAllCameraUseCases () { пытаться { если (cameraProvider != ноль) { cameraProvider.unbindAll(); если (cameraProvider == null) { возвращаться; } если (previewUseCase!= ноль) { cameraProvider.unbind(previewUseCase); } BindCameraUseCases(); } } catch (Исключение е) { } } /** * метод привязки вариантов использования камеры * получит экземпляр поставщика камеры * и свяжет предварительный просмотр и вариант использования видео * вызов дополнительного метода для настройки обнаружения FaceMesh */ частная пустотаbindCameraUseCases () { пытаться { Конструктор Preview.Builder = новый Preview.Builder(); предварительный просмотрUseCase = builder.build(); предварительный просмотрUseCase.setSurfaceProvider(fragmentCameraBinding.previewView.getSurfaceProvider()); Рекордер рекордер = новый Recorder.Builder() .setQualitySelector(QualitySelector.from(Quality.LOWEST, FallbackStrategy.higherQualityOrLowerThan(Quality.LOWEST))).build(); videoCapture = VideoCapture.withOutput(рекордер); новый ViewModelProvider(это, (ViewModelProvider.Factory) ViewModelProvider.AndroidViewModelFactory.getInstance(getActivity().getApplication())) .get(CameraXViewModel.класс) .getProcessCameraProvider() .наблюдать( getViewLifecycleOwner(), провайдер -> { cameraProvider = поставщик; пытаться { cameraProvider.unbindAll(); пытаться { Камера cameraX = cameraProvider.bindToLifecycle(getViewLifecycleOwner(), cameraSelector, предварительный просмотрUseCase, videoCapture); } catch (Исключение е) { } } catch (Исключение е) { } }); } catch (Исключение е) { } } Как я уже говорил, я не могу использовать метод ImageAnaлиз для получения кадров, поэтому получаю кадры вручную следующим образом:
Растровое изображение = фрагментCameraBinding.previewView.getBitmap(); а затем я использую это растровое изображение для распознавания лиц и моргания глаз. В то же время я записываю видео, код для этого:
@Nullable защищенная строка StoragePath = ""; частный VideoCapture videoCapture; частная запись currentRecording; личный файл видеофайл; частный окончательный Consumer videoCallback = new Consumer() { @Override public void Accept(androidx.camera.video.VideoRecordEvent videoRecordEvent) { пытаться { если (videoRecordEvent экземпляр VideoRecordEvent.Start) { //запись видео началась } Еще если (videoRecordEvent экземпляр VideoRecordEvent.Finalize) { //запись видео остановлена } } catch (Исключение е) { } } }; частная пустота startRecording () { пытаться { long timeStamp = System.currentTimeMillis(); ContentValues contentValues = новый ContentValues (); contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, timeStamp); contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "видео/mp4"); Каталог файлов = requireContext().getCacheDir(); видеоФайл = ноль; пытаться { видеоФайл = Файл.createTempFile( "записанный_файл", ".mp4", каталог ); } catch (IOException e) { е.printStackTrace(); } если (видеофайл!= ноль) { StoragePath = videoFile.getPath(); FileOutputOptions fileOutputOptions = новый FileOutputOptions.Builder(videoFile).build(); currentRecording = videoCapture.getOutput().prepareRecording(requireActivity(), fileOutputOptions).start( getExecutor(), videoCallback); } } catch (Исключение е) { } } частный исполнитель getExecutor() { вернуть ContextCompat.getMainExecutor(контекст); } Чтобы остановить запись видео:
currentRecording.stop(); previewView.getBitmap, поскольку он связан с пользовательским интерфейсом, поэтому мне приходится делать это в основном потоке пользовательского интерфейса. Это требует времени, кроме того, распознавание лиц тоже требует времени. В целом мой код обрабатывает от 3 до 4 кадров в секунду, я хочу обрабатывать 16–18 кадров в секунду, поскольку устройства возвращают почти 24–25 кадров в секунду.
Я работаю над приложением, моя цель — распознавать лица, распознавать моргание глаз и одновременно записывать видео. Итак, для этого мне нужно записать видео и в то же время я хочу обработать кадры, чтобы обнаружить моргание лица и глаз. Для этого я использую Camerax. В этом случае существуют некоторые ограничения Android:
[*]Мы не можем одновременно записывать видео и использовать методы анализа изображений cameraX. [*].setClassificationMode(FaceDetectorOptions.CLASSIFICATION_MODE_ALL) замедлит обработку кадров, как это также упоминается в документации MLKit, поэтому в моем случае мне нужна очень быстрая обработка кадров, поэтому я тоже не могу ее использовать.
Зависимости, которые я использую:
// Зависимости CameraX защита camerax_version = "1.2.0" реализация "androidx.camera:camera-camera2:${camerax_version}" реализация "androidx.camera:camera-lifecycle:${camerax_version}" реализация "androidx.camera:camera-view:${camerax_version}" реализация "androidx.camera:camera-video:${camerax_version}" // Google mMLKit для обнаружения лиц (отдельно) реализация 'com.google.android.gms:play-services-mlkit-face-detection:17.1.0' Предварительный просмотр в XML-файле:
Настройка камеры:
@Nullable защищенный ProcessCameraProvider cameraProvider; @Nullable частный предварительный просмотрUseCase; частный VideoCapture videoCapture; частный CameraSelector cameraSelector; частная пустота initCamera() { пытаться { cameraSelector = новый CameraSelector.Builder().requireLensFacing(CameraSelector.LENS_FACING_FRONT).build(); новый ViewModelProvider(это, (ViewModelProvider.Factory) ViewModelProvider.AndroidViewModelFactory.getInstance(getApplication())) .get(CameraXViewModel.класс) .getProcessCameraProvider() .observe(getViewLifecycleOwner(), провайдер -> { cameraProvider = поставщик; BindAllCameraUseCases(); }); } catch (Исключение е) { } } /** * метод для инициализации случаев использования привязки камеры * проверит поставщика камеры, отменит предыдущие варианты использования * и вызовет дополнительный метод для привязки вариантов использования камеры */ частная недействительностьbindAllCameraUseCases () { пытаться { если (cameraProvider != ноль) { cameraProvider.unbindAll(); если (cameraProvider == null) { возвращаться; } если (previewUseCase!= ноль) { cameraProvider.unbind(previewUseCase); } BindCameraUseCases(); } } catch (Исключение е) { } } /** * метод привязки вариантов использования камеры * получит экземпляр поставщика камеры * и свяжет предварительный просмотр и вариант использования видео * вызов дополнительного метода для настройки обнаружения FaceMesh */ частная пустотаbindCameraUseCases () { пытаться { Конструктор Preview.Builder = новый Preview.Builder(); предварительный просмотрUseCase = builder.build(); предварительный просмотрUseCase.setSurfaceProvider(fragmentCameraBinding.previewView.getSurfaceProvider()); Рекордер рекордер = новый Recorder.Builder() .setQualitySelector(QualitySelector.from(Quality.LOWEST, FallbackStrategy.higherQualityOrLowerThan(Quality.LOWEST))).build(); videoCapture = VideoCapture.withOutput(рекордер); новый ViewModelProvider(это, (ViewModelProvider.Factory) ViewModelProvider.AndroidViewModelFactory.getInstance(getActivity().getApplication())) .get(CameraXViewModel.класс) .getProcessCameraProvider() .наблюдать( getViewLifecycleOwner(), провайдер -> { cameraProvider = поставщик; пытаться { cameraProvider.unbindAll(); пытаться { Камера cameraX = cameraProvider.bindToLifecycle(getViewLifecycleOwner(), cameraSelector, предварительный просмотрUseCase, videoCapture); } catch (Исключение е) { } } catch (Исключение е) { } }); } catch (Исключение е) { } } Как я уже говорил, я не могу использовать метод ImageAnaлиз для получения кадров, поэтому получаю кадры вручную следующим образом:
Растровое изображение = фрагментCameraBinding.previewView.getBitmap(); а затем я использую это растровое изображение для распознавания лиц и моргания глаз. В то же время я записываю видео, код для этого:
@Nullable защищенная строка StoragePath = ""; частный VideoCapture videoCapture; частная запись currentRecording; личный файл видеофайл; частный окончательный Consumer videoCallback = new Consumer() { @Override public void Accept(androidx.camera.video.VideoRecordEvent videoRecordEvent) { пытаться { если (videoRecordEvent экземпляр VideoRecordEvent.Start) { //запись видео началась } Еще если (videoRecordEvent экземпляр VideoRecordEvent.Finalize) { //запись видео остановлена } } catch (Исключение е) { } } }; частная пустота startRecording () { пытаться { long timeStamp = System.currentTimeMillis(); ContentValues contentValues = новый ContentValues (); contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, timeStamp); contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "видео/mp4"); Каталог файлов = requireContext().getCacheDir(); видеоФайл = ноль; пытаться { видеоФайл = Файл.createTempFile( "записанный_файл", ".mp4", каталог ); } catch (IOException e) { е.printStackTrace(); } если (видеофайл!= ноль) { StoragePath = videoFile.getPath(); FileOutputOptions fileOutputOptions = новый FileOutputOptions.Builder(videoFile).build(); currentRecording = videoCapture.getOutput().prepareRecording(requireActivity(), fileOutputOptions).start( getExecutor(), videoCallback); } } catch (Исключение е) { } } частный исполнитель getExecutor() { вернуть ContextCompat.getMainExecutor(контекст); } Чтобы остановить запись видео:
currentRecording.stop(); previewView.getBitmap, поскольку он связан с пользовательским интерфейсом, поэтому мне приходится делать это в основном потоке пользовательского интерфейса. Это требует времени, кроме того, распознавание лиц тоже требует времени. В целом мой код обрабатывает от 3 до 4 кадров в секунду, я хочу обрабатывать 16–18 кадров в секунду, поскольку устройства возвращают почти 24–25 кадров в секунду.
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение
-
-
Одновременная запись и чтение в Byte[] для задержки живого звука на произвольное время.
Anonymous » » в форуме JAVA - 0 Ответы
- 34 Просмотры
-
Последнее сообщение Anonymous
-
-
-
Как записать отфильтрованное видео в файл MP4 с помощью Android Camerax
Anonymous » » в форуме Android - 0 Ответы
- 17 Просмотры
-
Последнее сообщение Anonymous
-