From 1576719d10e3246acaae7eaf82b2eb63a49b4b03 Mon Sep 17 00:00:00 2001 From: Bastian Kohler Date: Tue, 16 May 2023 22:35:50 +0200 Subject: [PATCH] Added onDetectionListener to VideoDecoder --- .../ueberwachungssystem/MainActivity.java | 11 + .../{ => VideoDetection}/VideoDetector.java | 325 +++++++++--------- 2 files changed, 182 insertions(+), 154 deletions(-) rename app/src/main/java/com/example/ueberwachungssystem/{ => VideoDetection}/VideoDetector.java (83%) diff --git a/app/src/main/java/com/example/ueberwachungssystem/MainActivity.java b/app/src/main/java/com/example/ueberwachungssystem/MainActivity.java index edef9f4..a32cf6e 100644 --- a/app/src/main/java/com/example/ueberwachungssystem/MainActivity.java +++ b/app/src/main/java/com/example/ueberwachungssystem/MainActivity.java @@ -15,13 +15,17 @@ import androidx.lifecycle.LifecycleOwner; import android.Manifest; import android.content.pm.PackageManager; import android.os.Bundle; +import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; +import com.example.ueberwachungssystem.VideoDetection.DetectionReport; +import com.example.ueberwachungssystem.VideoDetection.VideoDetector; import com.google.common.util.concurrent.ListenableFuture; +import java.util.Calendar; import java.util.concurrent.ExecutionException; @ExperimentalGetImage @@ -47,8 +51,15 @@ public class MainActivity extends AppCompatActivity { VideoDetector vd = new VideoDetector(this); vd.setPreviewView(previewView); + vd.setOnDetectionListener(new VideoDetector.OnDetectionListener() { + @Override + public void onDetection(DetectionReport detectionReport) { + Log.d("Listener", detectionReport.detectionType); + } + }); vd.startDetection(); + previewButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { diff --git a/app/src/main/java/com/example/ueberwachungssystem/VideoDetector.java b/app/src/main/java/com/example/ueberwachungssystem/VideoDetection/VideoDetector.java similarity index 83% rename from app/src/main/java/com/example/ueberwachungssystem/VideoDetector.java rename to app/src/main/java/com/example/ueberwachungssystem/VideoDetection/VideoDetector.java index 5f852b3..f7d4b95 100644 --- a/app/src/main/java/com/example/ueberwachungssystem/VideoDetector.java +++ b/app/src/main/java/com/example/ueberwachungssystem/VideoDetection/VideoDetector.java @@ -1,154 +1,171 @@ -package com.example.ueberwachungssystem; - -import android.content.Context; -import android.graphics.ImageFormat; -import android.media.Image; -import android.util.Log; -import android.util.Size; - -import androidx.annotation.NonNull; -import androidx.camera.core.CameraSelector; -import androidx.camera.core.ExperimentalGetImage; -import androidx.camera.core.ImageAnalysis; -import androidx.camera.core.ImageProxy; -import androidx.camera.core.Preview; -import androidx.camera.lifecycle.ProcessCameraProvider; -import androidx.camera.view.PreviewView; -import androidx.core.content.ContextCompat; -import androidx.lifecycle.LifecycleOwner; - -import com.google.common.util.concurrent.ListenableFuture; - -import java.nio.ByteBuffer; -import java.util.concurrent.ExecutionException; - -@ExperimentalGetImage -public class VideoDetector { - // Calling Activity - private final Context context; - // Camera Provider - private ProcessCameraProvider cameraProvider; - private Boolean isDetectionRunning = false; - // Preview Camera Image - private PreviewView previewView = null; - // Check Violation - private final float DELTA_LUMINOSITY_THRESHOLD = 10f; - private float lastLuminosity = 0f; - private Boolean isViolated = false; - - - /** Constructor */ - public VideoDetector(Context context) { this.context = context; } - - - - /** Return State of Video Detector */ - public Boolean isRunning() { return isDetectionRunning; } - - /** Return the status of Violation */ - public boolean getViolationStatus() - { - return isViolated; - } - - /** Starts Video Detection */ - public void startDetection() { - isDetectionRunning = true; - // Request Camera Provider - final ListenableFuture cameraProviderFuture = ProcessCameraProvider.getInstance(context); - //Check for Camera availability - cameraProviderFuture.addListener(new Runnable() { - @Override - public void run() { - try { - cameraProvider = cameraProviderFuture.get(); - bindLuminosityAnalysis(cameraProvider); - } catch (ExecutionException | InterruptedException e) { - // No errors need to be handled for this Future. This should never be reached. - } - } - },ContextCompat.getMainExecutor(context)); - } - - /** Stops Video Detection */ - public void stopDetection() { - cameraProvider.unbindAll(); - isDetectionRunning = false; - } - - /** Set PreviewView to show Image */ - public void setPreviewView(PreviewView previewView) { - this.previewView = previewView; - } - - /** Binds the Luminosity Analyzer (configure and run Analysis) */ - private void bindLuminosityAnalysis(@NonNull ProcessCameraProvider cameraProvider) { - // Configure and create Image Analysis - ImageAnalysis.Builder builder = new ImageAnalysis.Builder(); - builder.setTargetResolution(new Size(640, 480)); - builder.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST); - ImageAnalysis imageAnalysis = builder.build(); - - // Set Analyzer - imageAnalysis.setAnalyzer(ContextCompat.getMainExecutor(context), new ImageAnalysis.Analyzer() { - @Override - public void analyze(@NonNull ImageProxy imageProxy) { - if (imageProxy.getFormat() == ImageFormat.YUV_420_888) { - Image image = imageProxy.getImage(); - assert image != null; - - // Analyze frame - float luminosity = calculateLuminosity(image); - Log.d("Video Detector", String.valueOf(luminosity)); - if (luminosity != 0) - checkForViolation(luminosity, lastLuminosity); - lastLuminosity = luminosity; - } - imageProxy.close(); - } - }); - // Create Preview - Preview preview = new Preview.Builder().build(); - // Specify which Camera to use - CameraSelector cameraSelector = new CameraSelector.Builder().requireLensFacing(CameraSelector.LENS_FACING_BACK).build(); - // Update PreviewView if set - if (previewView != null) - preview.setSurfaceProvider(previewView.getSurfaceProvider()); - - cameraProvider.bindToLifecycle((LifecycleOwner) context, cameraSelector, imageAnalysis, preview); - } - - /** Return Luminosity from Image */ - private float calculateLuminosity (Image image) { - int width = image.getWidth(); - int height = image.getHeight(); - - Image.Plane[] planes = image.getPlanes(); - ByteBuffer luminosityBuffer = planes[0].getBuffer(); - - int yRowStride = image.getPlanes()[0].getRowStride(); - int yPixelStride = image.getPlanes()[0].getPixelStride(); - - int luminosity; - float sum = 0; - - for (int y = 0; y < height; ++y) { - for (int x = 0; x < width; x++) { - int index = (y * yRowStride) + (x * yPixelStride); - luminosity = (luminosityBuffer.get(index) & 0xff); - sum += luminosity; - } - } - return sum / (width * height); - } - - /** Check if delta Luminosity exceeds threshold */ - private void checkForViolation(float luminosity, float previousLuminosity) { - float deltaLuminosity = Math.abs(luminosity - previousLuminosity); - if (deltaLuminosity > DELTA_LUMINOSITY_THRESHOLD) { - isViolated = true; - Log.d("Violation", "Violation"); - } - Log.d("Delta", String.valueOf(Math.abs(previousLuminosity - luminosity))); - } -} +package com.example.ueberwachungssystem.VideoDetection; + +import android.content.Context; +import android.graphics.ImageFormat; +import android.media.Image; +import android.util.Log; +import android.util.Size; + +import androidx.annotation.NonNull; +import androidx.camera.core.CameraSelector; +import androidx.camera.core.ExperimentalGetImage; +import androidx.camera.core.ImageAnalysis; +import androidx.camera.core.ImageProxy; +import androidx.camera.core.Preview; +import androidx.camera.lifecycle.ProcessCameraProvider; +import androidx.camera.view.PreviewView; +import androidx.core.content.ContextCompat; +import androidx.lifecycle.LifecycleOwner; + +import com.google.common.util.concurrent.ListenableFuture; + +import java.nio.ByteBuffer; +import java.util.concurrent.ExecutionException; + + +@ExperimentalGetImage +public class VideoDetector { + // Calling Activity + private final Context context; + // Camera Provider + private ProcessCameraProvider cameraProvider; + private Boolean isDetectionRunning = false; + // Preview Camera Image + private PreviewView previewView = null; + // Check Violation + private final float DELTA_LUMINOSITY_THRESHOLD = 0.5f; + private float previousLuminosity = 0f; + // On Detection Listener + private OnDetectionListener listener; + + + + /** Constructor */ + public VideoDetector(Context context) { this.context = context; } + + + /** On Detection Listener - runs when a violation is reported */ + public interface OnDetectionListener { + public void onDetection(DetectionReport detectionReport); + } + public void setOnDetectionListener(OnDetectionListener listener) { + this.listener = listener; + } + public void reportViolation(float amplitude) { + DetectionReport detectionReport = new DetectionReport("123", "Video", amplitude); + if (listener != null) + listener.onDetection(detectionReport); + } + + + /** Return State of Video Detector */ + public Boolean isRunning() { + return isDetectionRunning; + } + + + /** Starts Video Detection */ + public void startDetection() { + isDetectionRunning = true; + // Request Camera Provider + final ListenableFuture cameraProviderFuture = ProcessCameraProvider.getInstance(context); + //Check for Camera availability + cameraProviderFuture.addListener(new Runnable() { + @Override + public void run() { + try { + cameraProvider = cameraProviderFuture.get(); + bindLuminosityAnalysis(cameraProvider); + } catch (ExecutionException | InterruptedException e) { + // No errors need to be handled for this Future. This should never be reached. + } + } + },ContextCompat.getMainExecutor(context)); + } + + + /** Stops Video Detection */ + public void stopDetection() { + cameraProvider.unbindAll(); + isDetectionRunning = false; + } + + + /** Set PreviewView to show Image */ + public void setPreviewView(PreviewView previewView) { + this.previewView = previewView; + } + + + /** Binds the Luminosity Analyzer (configure and run Analysis) */ + private void bindLuminosityAnalysis(@NonNull ProcessCameraProvider cameraProvider) { + // Configure and create Image Analysis + ImageAnalysis.Builder builder = new ImageAnalysis.Builder(); + builder.setTargetResolution(new Size(640, 480)); + builder.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST); + ImageAnalysis imageAnalysis = builder.build(); + + // Set Analyzer + imageAnalysis.setAnalyzer(ContextCompat.getMainExecutor(context), new ImageAnalysis.Analyzer() { + @Override + public void analyze(@NonNull ImageProxy imageProxy) { + if (imageProxy.getFormat() == ImageFormat.YUV_420_888) { + Image image = imageProxy.getImage(); + assert image != null; + + // Analyze frame + float luminosity = calculateLuminosity(image); + Log.d("Video Detector", String.valueOf(luminosity)); + checkForViolation(luminosity, previousLuminosity); + previousLuminosity = luminosity; + } + imageProxy.close(); + } + }); + // Create Preview + Preview preview = new Preview.Builder().build(); + // Specify which Camera to use + CameraSelector cameraSelector = new CameraSelector.Builder().requireLensFacing(CameraSelector.LENS_FACING_BACK).build(); + // Update PreviewView if set + if (previewView != null) + preview.setSurfaceProvider(previewView.getSurfaceProvider()); + + cameraProvider.bindToLifecycle((LifecycleOwner) context, cameraSelector, imageAnalysis, preview); + } + + + /** Return Luminosity from Image */ + private float calculateLuminosity (Image image) { + int width = image.getWidth(); + int height = image.getHeight(); + + Image.Plane[] planes = image.getPlanes(); + ByteBuffer luminosityBuffer = planes[0].getBuffer(); + + int yRowStride = image.getPlanes()[0].getRowStride(); + int yPixelStride = image.getPlanes()[0].getPixelStride(); + + int luminosity; + float sum = 0; + + for (int y = 0; y < height; ++y) { + for (int x = 0; x < width; x++) { + int index = (y * yRowStride) + (x * yPixelStride); + luminosity = (luminosityBuffer.get(index) & 0xff); + sum += luminosity; + } + } + return sum / (width * height); + } + + + /** Check if delta Luminosity exceeds threshold */ + private void checkForViolation(float luminosity, float previousLuminosity) { + float deltaLuminosity = Math.abs(luminosity - previousLuminosity); + if (deltaLuminosity > DELTA_LUMINOSITY_THRESHOLD) { + reportViolation(deltaLuminosity); + Log.d("Violation", "Violation"); + } + Log.d("Delta", String.valueOf(Math.abs(previousLuminosity - luminosity))); + } +}