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 dd52256..17b0f13 100644 --- a/app/src/main/java/com/example/ueberwachungssystem/Detection/VideoDetector.java +++ b/app/src/main/java/com/example/ueberwachungssystem/Detection/VideoDetector.java @@ -30,6 +30,7 @@ import org.opencv.core.CvType; import org.opencv.core.Mat; import org.opencv.core.MatOfPoint; import org.opencv.core.Scalar; +import org.opencv.core.Size; import org.opencv.imgproc.Imgproc; import java.nio.ByteBuffer; @@ -66,10 +67,6 @@ public class VideoDetector extends Detector { // Parameters - private static final float PIXEL_THRESHOLD = 40f; // Luminosity (brightness channel of YUV_420_888) - private static final int BLUR_KERNEL_SIZE = 5; - private static final int DILATE_KERNEL_SIZE = 5; - private static final float CONTOUR_THRESHOLD = 250; private static final float ALARM_THRESHOLD = 0.5f; // Percent of pixels changed private static final long START_DELAY = 1000; // milliseconds private static final android.util.Size IMAGE_RES = new android.util.Size(640, 480); @@ -140,7 +137,6 @@ public class VideoDetector extends Detector { isDetectionRunning = false; } - /** * Permission handling */ @@ -172,29 +168,25 @@ public class VideoDetector extends Detector { Image image = imageProxy.getImage(); assert image != null; - if (image != null) { + Mat currentMat = extractYChannel(image); - Mat mat = extractYChannel(image); + Mat mat = currentMat.clone(); + debugMat(mat, imageView2); - debugMat(mat, imageView2); - mat = processImage(mat); - debugMat(mat, imageView1); + Mat processed = processImage(mat); - int n = 0; - n = countNonZeroPixels(mat); + debugMat(processed, imageView1); - int pixelCount = image.getWidth() * image.getHeight(); - float percentChanged = (float)n / pixelCount; - // report violation - if (percentChanged * 100 > ALARM_THRESHOLD) { - reportViolation("Video", n); - } + int n = countNonZeroPixels(processed); + int pixelCount = image.getWidth() * image.getHeight(); + float percentChanged = (float)n / pixelCount; + // report violation + if (percentChanged * 100 > ALARM_THRESHOLD) { + reportViolation("Video", n); } } imageProxy.close(); }); - - // Create Preview Preview preview = new Preview.Builder().build(); // Specify which Camera to use @@ -217,26 +209,42 @@ public class VideoDetector extends Detector { * @param image: OpenCV Mat file that should be processed */ private Mat processImage(Mat image){ + + // Preprocess Image + Mat preprocessed = image.clone(); + preprocessed = addGaussianBlur(preprocessed, new Size(21, 21)); + preprocessed = addBlur(preprocessed, new Size(3, 3)); + if (previousImage == null) { - previousImage = image; + previousImage = preprocessed; return null; } - Mat mat = addGaussianBlur(image, BLUR_KERNEL_SIZE); - mat = thresholdPixels(mat, previousImage); - mat = dilateNonZero(mat, DILATE_KERNEL_SIZE); - mat = thresholdContourArea(mat, CONTOUR_THRESHOLD); + // Process Image + Mat processed = preprocessed.clone(); + processed = thresholdPixels(processed, previousImage, 25); + processed = dilateBinaryMat(processed, new Size(3,3)); + processed = dilateBinaryMat(processed, new Size(3,3)); + processed = thresholdContourArea(processed, 500); - previousImage = image.clone(); - return mat; + previousImage = preprocessed.clone(); + return processed; + } + + + /** OpenCV helper methods **/ + private Mat addGaussianBlur(Mat inputMat, Size kernelSize){ + Mat outputMat = new Mat(); + Imgproc.GaussianBlur(inputMat, outputMat, kernelSize, 0); + return outputMat; + } + + private Mat addBlur(Mat inputMat, Size kernelSize){ + Mat outputMat = new Mat(); + Imgproc.blur(inputMat, outputMat, kernelSize); + return outputMat; } - /** - * 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()]; @@ -248,54 +256,14 @@ public class VideoDetector extends Detector { return yMat; } - /** - * Threshold all Pixels - * @param inputMat: Input Image - * @param previousImage: previous Image (openCV Mat) - * @return Binary Mat Image - */ - private Mat thresholdPixels(Mat inputMat, Mat previousImage){ + private Mat thresholdPixels(Mat inputMat, Mat previousImage, int threshold){ Mat diffImage = new Mat(); Core.absdiff(inputMat, previousImage, diffImage); - Mat binaryMat = new Mat(); - Imgproc.threshold(diffImage, binaryMat, VideoDetector.PIXEL_THRESHOLD, 255, Imgproc.THRESH_BINARY); - + Imgproc.threshold(diffImage, binaryMat, 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)); - Imgproc.dilate(inputMat, dilatedMat, kernel); - 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(); @@ -315,11 +283,13 @@ 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 Mat dilateBinaryMat(Mat inputMat, Size kernelSize){ + Mat dilatedMat = new Mat(); + Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_ELLIPSE, kernelSize); + Imgproc.dilate(inputMat, dilatedMat, kernel); + return dilatedMat; + } + private int countNonZeroPixels(Mat inputImage) { if (inputImage != null) return Core.countNonZero(inputImage); @@ -327,11 +297,8 @@ 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;