From 76442888f7c215c630d070675fe6c887d0c842a3 Mon Sep 17 00:00:00 2001 From: Bastian Kohler Date: Sat, 17 Jun 2023 19:44:08 +0200 Subject: [PATCH] Working Video Detector + Recorder WIP: Use Case logic --- app/src/main/AndroidManifest.xml | 1 - .../Detection/Detector.java | 4 + .../Detection/VideoDetector.java | 147 +++++++++++++----- .../ueberwachungssystem/MainActivity.java | 19 +-- app/src/main/res/layout/activity_main.xml | 2 +- 5 files changed, 121 insertions(+), 52 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index b5bb284..3ea0c3b 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -4,7 +4,6 @@ - cameraProviderFuture = ProcessCameraProvider.getInstance(context); - //Check for Camera availability cameraProviderFuture.addListener(() -> { try { cameraProvider = cameraProviderFuture.get(); - bindCameraProvider(cameraProvider); - isDetectionRunning = true; - } catch (ExecutionException | InterruptedException e) { - // No errors need to be handled for this Future. This should never be reached. - } + isDetecting = true; + bindCameraProvider(UseCase.ImageAnalysis); + } catch (ExecutionException | InterruptedException e) {} }, ContextCompat.getMainExecutor(context)); } /** Stops the Video Detection */ @Override public void stopDetection() { - if (!isDetectionRunning || imageAnalysis == null) + if (!isDetecting || imageAnalysis == null) return; cameraProvider.unbind(imageAnalysis); - isDetectionRunning = false; + cameraProvider.unbind(preview); + isDetecting = false; allowReportViolation = false; } /** Permission handling */ - private boolean isCameraAccessAllowed() { - return ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED; + private boolean hasPermissions() { + return ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED && + ContextCompat.checkSelfPermission(context, Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED; + } + private void getPermissions() { + if (!hasPermissions()) + ActivityCompat.requestPermissions((Activity) context, new String[]{android.Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO}, PERMISSION_REQUEST_CODE); } - private void getCameraAccess() { - if (!isCameraAccessAllowed()) - ActivityCompat.requestPermissions((Activity) context, new String[]{android.Manifest.permission.CAMERA}, CAMERA_PERMISSION_REQUEST_CODE); - } /** Binds the Luminosity Analyzer (configure and run Analysis) */ - private void bindCameraProvider(@NonNull ProcessCameraProvider cameraProvider) { - // Create Preview - //Preview preview = new Preview.Builder().build(); + private void bindCameraProvider(UseCase useCase) { // Specify which Camera to use CameraSelector cameraSelector = new CameraSelector.Builder().requireLensFacing(CameraSelector.LENS_FACING_BACK).build(); - - cameraProvider.bindToLifecycle((LifecycleOwner) context, cameraSelector, imageAnalysis); - - // Delay till violation is allowed - startViolationTimer(); + if(useCase == UseCase.ImageAnalysis && !cameraProvider.isBound(videoCapture)) { + cameraProvider.unbindAll(); + cameraProvider.bindToLifecycle((LifecycleOwner) context, cameraSelector, imageAnalysis, preview); + startViolationTimer(); + } + if(useCase == UseCase.VideoCapture) { + if(cameraProvider.isBound(imageAnalysis)) { + cameraProvider.unbindAll(); + cameraProvider.bindToLifecycle((LifecycleOwner) context, cameraSelector, imageAnalysis, videoCapture); + } else { + cameraProvider.unbindAll(); + cameraProvider.bindToLifecycle((LifecycleOwner) context, cameraSelector, videoCapture); + } + } } @@ -170,7 +192,6 @@ public class VideoDetector extends Detector { @Override public void onTick(long millisUntilFinished) { } - @Override public void onFinish() { allowReportViolation = true; @@ -212,15 +233,63 @@ public class VideoDetector extends Detector { @SuppressLint("RestrictedApi") private VideoCapture setupVideoCapture() { return new VideoCapture.Builder() - .setVideoFrameRate(30) .setTargetRotation(Surface.ROTATION_0) .build(); } + @SuppressLint("RestrictedApi") + public void startRecording() { + // Check States + if (isRecording){ + extendDetection(); + return; + } + + // Return On Request Permissions + if (!hasPermissions()) { + getPermissions(); + return; + } + + final ListenableFuture cameraProviderFuture = ProcessCameraProvider.getInstance(context); + cameraProviderFuture.addListener(() -> { + try { + cameraProvider = cameraProviderFuture.get(); + isRecording = true; + bindCameraProvider(UseCase.VideoCapture); + + File vidFile = new File(context.getFilesDir() + "/" + outputName); + if (ActivityCompat.checkSelfPermission(context, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) { + return; + } + videoCapture.startRecording( + new VideoCapture.OutputFileOptions.Builder(vidFile).build(), + context.getMainExecutor(), + new VideoCapture.OnVideoSavedCallback() { + @Override + public void onVideoSaved(@NonNull VideoCapture.OutputFileResults outputFileResults) { + Toast.makeText(context, "recording saved", Toast.LENGTH_SHORT).show(); + } + @Override + public void onError(int videoCaptureError, @NonNull String message, @Nullable Throwable cause) { + Toast.makeText(context, "recording failed", Toast.LENGTH_SHORT).show(); + } + } + ); + } catch (ExecutionException | InterruptedException e) {} + }, ContextCompat.getMainExecutor(context)); + } + + @SuppressLint("RestrictedApi") + public void stopRecording(){ + videoCapture.stopRecording(); + cameraProvider.unbind(videoCapture); + if (isDetecting) + bindCameraProvider(UseCase.ImageAnalysis); + } /** Process Image to be used for Motion Detection */ private Mat processImage(Image image){ - // Image Transformation Mat imageMat = OpenCVHelper.extractYChannel(image); @@ -245,7 +314,6 @@ public class VideoDetector extends Detector { processed = OpenCVHelper.dilateBinaryMat(processed, new Size(3,3)); processed = OpenCVHelper.thresholdContourArea(processed, 500); - // Output previousImage = preprocessed.clone(); // Show Output Image @@ -254,13 +322,16 @@ public class VideoDetector extends Detector { return processed; } - public void debugProcessing(ImageView inputImageView, ImageView outputImageView){ + public void debugProcessing(@NonNull ImageView inputImageView, @NonNull ImageView outputImageView){ this.inputImageView = inputImageView; this.outputImageView = outputImageView; } - - + public void setPreviewView(@NonNull PreviewView previewView) { + // Create Preview + if (this.preview != null) + this.preview.setSurfaceProvider(previewView.getSurfaceProvider()); + } diff --git a/app/src/main/java/com/example/ueberwachungssystem/MainActivity.java b/app/src/main/java/com/example/ueberwachungssystem/MainActivity.java index fb73468..5e33822 100644 --- a/app/src/main/java/com/example/ueberwachungssystem/MainActivity.java +++ b/app/src/main/java/com/example/ueberwachungssystem/MainActivity.java @@ -3,6 +3,7 @@ package com.example.ueberwachungssystem; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.camera.core.ExperimentalGetImage; +import androidx.camera.view.PreviewView; import android.os.Bundle; import android.view.View; @@ -16,9 +17,6 @@ import com.example.ueberwachungssystem.Detection.VideoDetector; @ExperimentalGetImage public class MainActivity extends AppCompatActivity { - private static final int CAMERA_PERMISSION_REQUEST_CODE = 101; - - @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -27,16 +25,12 @@ public class MainActivity extends AppCompatActivity { ImageView inputImageView = findViewById(R.id.inputImageView); ImageView outputImageView = findViewById(R.id.outputImageView); + PreviewView previewView = findViewById(R.id.previewView); VideoDetector vd = new VideoDetector(this); + vd.setPreviewView(previewView); vd.debugProcessing(inputImageView, outputImageView); - vd.setOnDetectionListener(new Detector.OnDetectionListener(){ - @Override - public void onDetection(@NonNull DetectionReport detectionReport) { - detectionReport.log("OnDetection"); - } - }); @@ -46,13 +40,14 @@ public class MainActivity extends AppCompatActivity { public void onClick(View v) { if (toggleButton.isChecked()) { - vd.startDetection(); + //vd.startDetection(); + vd.startRecording(); } else { - vd.stopDetection(); + //vd.stopDetection(); + vd.stopRecording(); } } }); - } } \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index aa0ac96..57571c5 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -13,7 +13,7 @@