From 7ef0df48dd33996c7229c9a6c5e905d9ac2214da Mon Sep 17 00:00:00 2001 From: Bastian Kohler Date: Wed, 14 Jun 2023 20:14:06 +0200 Subject: [PATCH] Refactored Detector --- .../Detection/VideoDetector.java | 93 +++++++++++++++++-- .../ueberwachungssystem/MainActivity.java | 24 ----- 2 files changed, 86 insertions(+), 31 deletions(-) diff --git a/app/src/main/java/com/example/ueberwachungssystem/Detection/VideoDetector.java b/app/src/main/java/com/example/ueberwachungssystem/Detection/VideoDetector.java index d91c3c2..dd52256 100644 --- a/app/src/main/java/com/example/ueberwachungssystem/Detection/VideoDetector.java +++ b/app/src/main/java/com/example/ueberwachungssystem/Detection/VideoDetector.java @@ -1,6 +1,9 @@ package com.example.ueberwachungssystem.Detection; +import android.Manifest; +import android.app.Activity; import android.content.Context; +import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.ImageFormat; import android.media.Image; @@ -14,6 +17,7 @@ import androidx.camera.core.ExperimentalGetImage; import androidx.camera.core.ImageAnalysis; import androidx.camera.core.Preview; import androidx.camera.lifecycle.ProcessCameraProvider; +import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import androidx.lifecycle.LifecycleOwner; @@ -47,17 +51,20 @@ public class VideoDetector extends Detector { // Calling Activity private final Context context; + // Permission handling + private static final int CAMERA_PERMISSION_REQUEST_CODE = 3691; // Camera Provider private ProcessCameraProvider cameraProvider; - private Boolean isDetectionRunning = false; - // Detection - private Mat previousImage = null; + private boolean isDetectionRunning = false; + // Debugging + private Mat previousImage = null; public ImageView imageView1 = null; public ImageView imageView2 = null; + // Parameters private static final float PIXEL_THRESHOLD = 40f; // Luminosity (brightness channel of YUV_420_888) private static final int BLUR_KERNEL_SIZE = 5; @@ -79,6 +86,15 @@ public class VideoDetector extends Detector { this.context = context; } + + /** + * Get State of the Detector + */ + public boolean isRunning() { + return isDetectionRunning; + } + + /** * Starts the Video Detection * */ @@ -87,6 +103,10 @@ public class VideoDetector extends Detector { if (isDetectionRunning) return; + if (!isCameraAccessAllowed()){ + getCameraAccess(); + } + // Open CV startup check if (!OpenCVLoader.initDebug()) { Log.e("OpenCV", "Unable to load OpenCV!"); @@ -121,6 +141,19 @@ public class VideoDetector extends Detector { } + /** + * Permission handling + */ + private boolean isCameraAccessAllowed() { + return ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED; + } + + 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) * @param cameraProvider: CameraProvider of Context passed by Constructor @@ -177,6 +210,12 @@ public class VideoDetector extends Detector { }.start(); } + + /** + * Process Image to be used for Motion Detection + * + * @param image: OpenCV Mat file that should be processed + */ private Mat processImage(Mat image){ if (previousImage == null) { previousImage = image; @@ -184,7 +223,7 @@ public class VideoDetector extends Detector { } Mat mat = addGaussianBlur(image, BLUR_KERNEL_SIZE); - mat = thresholdPixels(mat, previousImage, PIXEL_THRESHOLD); + mat = thresholdPixels(mat, previousImage); mat = dilateNonZero(mat, DILATE_KERNEL_SIZE); mat = thresholdContourArea(mat, CONTOUR_THRESHOLD); @@ -192,6 +231,12 @@ public class VideoDetector extends Detector { return mat; } + /** + * Convert Android Image to OpenCV Mat file with only y-Channel + * + * @param img: Android Image + * @return yChannel of Image in OpenCV Mat Format + */ private Mat extractYChannel(@NonNull Image img) { ByteBuffer yBuffer = img.getPlanes()[0].getBuffer(); byte[] yData = new byte[yBuffer.remaining()]; @@ -203,17 +248,28 @@ public class VideoDetector extends Detector { return yMat; } - - private Mat thresholdPixels(Mat inputMat, Mat previousImage, float luminosityThreshold){ + /** + * Threshold all Pixels + * @param inputMat: Input Image + * @param previousImage: previous Image (openCV Mat) + * @return Binary Mat Image + */ + private Mat thresholdPixels(Mat inputMat, Mat previousImage){ Mat diffImage = new Mat(); Core.absdiff(inputMat, previousImage, diffImage); Mat binaryMat = new Mat(); - Imgproc.threshold(diffImage, binaryMat, luminosityThreshold, 255, Imgproc.THRESH_BINARY); + Imgproc.threshold(diffImage, binaryMat, VideoDetector.PIXEL_THRESHOLD, 255, Imgproc.THRESH_BINARY); return binaryMat; } + /** + * Dilate Pixels of Binary Image + * @param inputMat: Input Image + * @param kernelSize: kernel Size + * @return binary Image with dilated Pixels + */ private Mat dilateNonZero(Mat inputMat, int kernelSize){ Mat dilatedMat = new Mat(); Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_ELLIPSE, new org.opencv.core.Size(kernelSize, kernelSize)); @@ -221,12 +277,25 @@ public class VideoDetector extends Detector { return dilatedMat; } + /** + * Add Gaussian Blur to OpenCV Mat Image + * @param inputMat: Input Image + * @param kernelSize: kernel Size + * @return Mat Image + */ private Mat addGaussianBlur(Mat inputMat, int kernelSize){ Mat outputMat = new Mat(); Imgproc.GaussianBlur(inputMat, outputMat, new org.opencv.core.Size(kernelSize, kernelSize), 0); return outputMat; } + + /** + * Filter Contour Areas by Size + * @param inputMat: Input Image + * @param areaThreshold: Threshold + * @return Binary Mat Image + */ private Mat thresholdContourArea(Mat inputMat, float areaThreshold){ List contours = new ArrayList<>(); Mat hierarchy = new Mat(); @@ -246,6 +315,11 @@ public class VideoDetector extends Detector { return outputMat; } + /** + * Count all Pixels that are non Zero + * @param inputImage: Input Image in OpenCV Mat Format + * @return Count of Pixels that are non zero + */ private int countNonZeroPixels(Mat inputImage) { if (inputImage != null) return Core.countNonZero(inputImage); @@ -253,6 +327,11 @@ public class VideoDetector extends Detector { return 0; } + /** + * Show OpenCV Mat on ImageView + * @param mat: current OpenCV Mat Image + * @param imageView: ImageView xml-Element + */ private void debugMat(Mat mat, ImageView imageView) { if (imageView == null || mat == null) return; diff --git a/app/src/main/java/com/example/ueberwachungssystem/MainActivity.java b/app/src/main/java/com/example/ueberwachungssystem/MainActivity.java index 6206490..3efe3ab 100644 --- a/app/src/main/java/com/example/ueberwachungssystem/MainActivity.java +++ b/app/src/main/java/com/example/ueberwachungssystem/MainActivity.java @@ -31,7 +31,6 @@ public class MainActivity extends AppCompatActivity { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); - getCameraAccess(); ImageView imageView = findViewById(R.id.imageView); ImageView ogiv = findViewById(R.id.ogiv); @@ -48,27 +47,4 @@ public class MainActivity extends AppCompatActivity { }); vd.startDetection(); } - - private boolean isCameraAccessAllowed() { - return ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED; - } - - private void getCameraAccess() { - if (!isCameraAccessAllowed()) - ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.CAMERA}, CAMERA_PERMISSION_REQUEST_CODE); - } - - @Override - public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults); - - if (requestCode == CAMERA_PERMISSION_REQUEST_CODE && grantResults.length > 0) { - boolean cameraRights = grantResults[0] == PackageManager.PERMISSION_GRANTED; - if (cameraRights) { - Toast.makeText(this, "camera permission granted", Toast.LENGTH_LONG).show(); - } else { - Toast.makeText(this, "camera permission denied", Toast.LENGTH_LONG).show(); - } - } - } } \ No newline at end of file