Compare commits

...

35 Commits

Author SHA1 Message Date
df1fefef5f added Toggle Button to start Cam Detection 2023-06-15 16:59:17 +02:00
5bcd465ecc Merge branch 'master' into ko
# Conflicts:
#	app/build.gradle
#	app/src/main/AndroidManifest.xml
#	app/src/main/res/layout/activity_main.xml
#	gradle/wrapper/gradle-wrapper.properties
2023-06-15 16:20:40 +02:00
11dbcd0362 Merge branch 'bk_video' of siebenhaarmi76624/MDT5_1_Ueberwachungssystem_G1 into master 2023-06-02 15:51:55 +00:00
047d45f1cb Added comments to VideoDetector class 2023-06-02 17:48:41 +02:00
95919a6602 preparing branch for merge 2023-06-02 14:56:57 +02:00
19d1bfe1e3 Refactor 2023-05-29 10:43:51 +02:00
e9da712882 Merge remote-tracking branch 'origin/bk_video' into bk_video 2023-05-28 22:30:58 +02:00
804c5aba36 Removed old Luminosity detection 2023-05-28 22:30:22 +02:00
c5577b125f Changed VideoDetector.java to detect based on changed pixel count instead of average luminosity 2023-05-28 22:30:22 +02:00
6100d17bd2 Refactored in Main 2023-05-28 22:30:22 +02:00
74a291bdd6 Removed olf Luminosity detection 2023-05-28 22:28:23 +02:00
ba6765b1fb Changed VideoDetector.java to detect based on changed pixel count instead of average luminosity 2023-05-28 22:20:56 +02:00
9fce3be6a8 Refactored some stuff in Main 2023-05-28 22:19:30 +02:00
9892fc35bc Refactor of Detector.java 2023-05-28 22:19:05 +02:00
62a528d33b Implemented VideoDetector as a child class of abstract class Detector 2023-05-28 21:16:17 +02:00
37617dbd54 Fixed a bug in Detector.java 2023-05-25 10:54:08 +02:00
569bd43163 Adjusted some values in xml and video detector for showcase 2023-05-25 10:20:11 +02:00
fdb0036ea6 Added comments to abstract class "Detector" 2023-05-25 10:19:21 +02:00
f9797f2dca Added Abstract class Detector 2023-05-24 23:51:49 +02:00
ba75c58a23 Refactor 2023-05-24 22:16:54 +02:00
3d799ae461 Rebuild Demo in Main Activity 2023-05-18 15:05:09 +02:00
2501662737 Fixed a bug in the video decoder 2023-05-18 12:02:18 +02:00
d04d166e14 Added log function to detection report 2023-05-18 12:01:45 +02:00
1576719d10 Added onDetectionListener to VideoDecoder 2023-05-16 22:35:50 +02:00
362af75b9a Added DetectionReportCalss 2023-05-16 22:34:32 +02:00
bef5d03494 Added functions for checking luminosity violation 2023-05-16 19:15:57 +02:00
80ebf77eb6 Removed empty Text File 2023-05-16 17:48:33 +02:00
c4ed247a05 added Functions to VideoDetector:
startDetection(), stopDetection(), isRunning()
2023-05-16 17:42:10 +02:00
323786859e added Video Decoder Class 2023-05-12 18:45:13 +02:00
354bf937b2 added camerax libraries to build.gradle 2023-05-12 09:37:58 +02:00
39bb37f5c3 removed VideoDetection.java 2023-05-11 21:46:15 +02:00
b198dc2e06 small refactor 2023-05-11 21:33:40 +02:00
BepsiKohler
d83cd3dc32 Added camera access permission 2023-05-11 20:58:01 +02:00
065acefeb9 Merge branch 'ms' of siebenhaarmi76624/MDT5_1_Ueberwachungssystem_G1 into master 2023-05-11 13:29:40 +00:00
dda3d5693a Initial commit Project Version 0 2023-05-11 15:08:50 +02:00
10 changed files with 329 additions and 12 deletions

View File

View File

@ -3,11 +3,11 @@ plugins {
} }
android { android {
namespace 'de.oklein.android.ueberwachungssystem' namespace 'com.example.ueberwachungssystem'
compileSdk 33 compileSdk 33
defaultConfig { defaultConfig {
applicationId "de.oklein.android.ueberwachungssystem" applicationId "com.example.ueberwachungssystem"
minSdk 28 minSdk 28
targetSdk 33 targetSdk 33
versionCode 1 versionCode 1
@ -31,10 +31,18 @@ android {
dependencies { dependencies {
implementation 'androidx.appcompat:appcompat:1.6.1' implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.9.0' implementation 'com.google.android.material:material:1.8.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
testImplementation 'junit:junit:4.13.2' testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
implementation "androidx.startup:startup-runtime:1.1.1"
// Required for CameraX
def camerax_version = "1.2.2"
implementation "androidx.camera:camera-core:${camerax_version}"
implementation "androidx.camera:camera-camera2:${camerax_version}"
implementation "androidx.camera:camera-lifecycle:${camerax_version}"
implementation "androidx.camera:camera-video:${camerax_version}"
implementation "androidx.camera:camera-view:${camerax_version}"
implementation "androidx.camera:camera-extensions:${camerax_version}"
} }

View File

@ -1,4 +1,4 @@
package de.oklein.android.ueberwachungssystem; package com.example.ueberwachungssystem;
import android.content.Context; import android.content.Context;
@ -21,6 +21,6 @@ public class ExampleInstrumentedTest {
public void useAppContext() { public void useAppContext() {
// Context of the app under test. // Context of the app under test.
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
assertEquals("de.oklein.android.ueberwachungssystem", appContext.getPackageName()); assertEquals("com.example.ueberwachungssystem", appContext.getPackageName());
} }
} }

View File

@ -0,0 +1,36 @@
package com.example.ueberwachungssystem.Detection;
import android.util.Log;
import java.util.Calendar;
/** Detection Report Class */
public class DetectionReport {
public String timeStamp;
public String detectionType;
public float detectedValue;
public String detectorID;
public DetectionReport(String detectorID, String detectionType, float detectedAmplitude) {
this.timeStamp = String.valueOf(Calendar.getInstance().getTime());
this.detectionType = detectionType;
this.detectedValue = detectedAmplitude;
this.detectorID = detectorID;
}
/** Get Detection Report in String format */
public String toString() {
String time = "Time: " + "[" + this.timeStamp + "]";
String type = "Type: " + "[" + this.detectionType + "]";
String value = "Value: " + "[" + this.detectedValue + "]";
String id = "ID: " + "[" + this.detectorID + "]";
return String.join("\t", time, type, value, id);
}
/** Debug Report */
public void log(String tag) {
Log.d(tag, this.toString());
}
}

View File

@ -0,0 +1,38 @@
package com.example.ueberwachungssystem.Detection;
import androidx.annotation.NonNull;
abstract public class Detector {
private OnDetectionListener listener;
/** Constructor - takes context of current activity */
public Detector() {}
/** On Detection Listener - runs when violation is reported */
public interface OnDetectionListener {
void onDetection(@NonNull DetectionReport detectionReport);
}
public void setOnDetectionListener(@NonNull OnDetectionListener listener) {
this.listener = listener;
}
/** Triggers onDetectionListener - call this to trigger violation/alarm */
public void reportViolation(String detectorID, String detectionType, float amplitude) {
if (listener != null) {
DetectionReport detectionReport = new DetectionReport(detectorID, detectionType, amplitude);
listener.onDetection(detectionReport);
} else {
throw new IllegalStateException("No listener set for violation reporting");
}
}
/** Starts Detection (abstract method: needs to be overridden in child class) */
public abstract void startDetection();
/** Stops Detection (abstract method: needs to be overridden in child class) */
public abstract void stopDetection();
}

View File

@ -0,0 +1,196 @@
package com.example.ueberwachungssystem.Detection;
import android.content.Context;
import android.graphics.ImageFormat;
import android.media.Image;
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.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;
/**
* Video Detector inherits some methods from abstract Detector class (more info there)
*
*
* USE FROM MAIN ACTIVITY:
*
* VideoDetector vd = new VideoDetector(this);
* vd.setPreview(previewView); //THIS IS OPTIONAL!
* vd.setOnDetectionListener(new Detector.OnDetectionListener{...});
* vd.startDetection();
* vd.stopDetection
*
* */
@ExperimentalGetImage
public class VideoDetector extends Detector {
// Calling Activity
private final Context context;
// Camera Provider
private ProcessCameraProvider cameraProvider;
private Boolean isDetectionRunning = false;
// Preview Camera Image
private PreviewView previewView = null;
// Detect Violation
private static final float PIXEL_THRESHOLD = 30f; // Luminosity (brightness channel of YUV_420_888)
private static final float ALARM_THRESHOLD = 0.2f; // Percent of pixels changed
private ByteBuffer previousBuffer = null;
/**
* Constructor
* @param context: the context of calling activity (usually "this")
* */
public VideoDetector(Context context) {
super();
this.context = context;
}
/**
* Starts the Video Detection
* */
@Override
public void startDetection() {
if (isDetectionRunning)
return;
// Request Camera Provider
final ListenableFuture<ProcessCameraProvider> cameraProviderFuture = ProcessCameraProvider.getInstance(context);
//Check for Camera availability
cameraProviderFuture.addListener(() -> {
try {
cameraProvider = cameraProviderFuture.get();
bindAnalysis(cameraProvider);
isDetectionRunning = true;
previousBuffer = null;
} catch (ExecutionException | InterruptedException e) {
// No errors need to be handled for this Future. This should never be reached.
}
},ContextCompat.getMainExecutor(context));
}
/**
* Stops the Video Detection
* */
@Override
public void stopDetection() {
if (!isDetectionRunning)
return;
cameraProvider.unbindAll();
isDetectionRunning = false;
}
/**
* Set PreviewView to show video feed while detecting
* this is optional and does not need to be called
* */
public void setPreviewView(PreviewView previewView) {
this.previewView = previewView;
}
/**
* Binds the Luminosity Analyzer (configure and run Analysis)
* @param cameraProvider: CameraProvider of Context passed by Constructor
* */
private void bindAnalysis(@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);
builder.setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_YUV_420_888);
ImageAnalysis imageAnalysis = builder.build();
// Set Analyzer
imageAnalysis.setAnalyzer(ContextCompat.getMainExecutor(context), imageProxy -> {
if (imageProxy.getFormat() == ImageFormat.YUV_420_888) {
Image image = imageProxy.getImage();
assert image != null;
// Changed Pixel Detection
int pixelChanged = getChangedPixelCount(image);
int width = image.getWidth();
int height = image.getHeight();
float percentPixelChanged = (float) 100f * pixelChanged / (width * height);
if (percentPixelChanged > ALARM_THRESHOLD)
reportViolation("0", "Video", percentPixelChanged);
}
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);
}
/**
* Calculate Amount of Pixels changed using a threshold
* @param image
* */
private int getChangedPixelCount(Image image) {
Image.Plane[] planes = image.getPlanes();
ByteBuffer buffer = planes[0].getBuffer();
if (previousBuffer == null) {
previousBuffer = ByteBuffer.allocate(buffer.capacity());
buffer.rewind();
previousBuffer.put(buffer);
previousBuffer.rewind();
return 0;
}
int width = image.getWidth();
int height = image.getHeight();
int yRowStride = image.getPlanes()[0].getRowStride();
int yPixelStride = image.getPlanes()[0].getPixelStride();
int changedPixelCount = 0;
// Count changed pixels
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; x++) {
int index = (y * yRowStride) + (x * yPixelStride);
int luminosity = (buffer.get(index) & 0xff);
int previousLuminosity = (previousBuffer.get(index) & 0xff);
int diff = Math.abs(luminosity - previousLuminosity);
if (diff > PIXEL_THRESHOLD)
changedPixelCount++;
}
}
// Reset and copy Byte Buffer
buffer.rewind();
previousBuffer.rewind();
previousBuffer.put(buffer);
return changedPixelCount;
}
}

View File

@ -1,4 +1,4 @@
package de.oklein.android.ueberwachungssystem.Logger; package com.example.ueberwachungssystem.Logger;
import android.util.Log; import android.util.Log;
import android.widget.TextView; import android.widget.TextView;

View File

@ -1,5 +1,7 @@
package de.oklein.android.ueberwachungssystem; package com.example.ueberwachungssystem;
import androidx.annotation.NonNull;
import androidx.camera.core.ExperimentalGetImage;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction; import androidx.fragment.app.FragmentTransaction;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
@ -13,13 +15,25 @@ import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ScrollView; import android.widget.ScrollView;
import android.widget.TextView; import android.widget.TextView;
import android.widget.ToggleButton;
import com.example.ueberwachungssystem.Detection.DetectionReport;
import com.example.ueberwachungssystem.Detection.Detector;
import com.example.ueberwachungssystem.Detection.VideoDetector;
import org.w3c.dom.Text; import org.w3c.dom.Text;
public class MainActivity extends AppCompatActivity { @ExperimentalGetImage
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Fragment aktuellesFragment; private Fragment aktuellesFragment;
private TextView alarm; private TextView alarm;
private String text = "Das ist ein Alarm des Sensors"; private String text = "Das ist ein Alarm des Sensors";
//Buttons
private ToggleButton toggleKamera;
private ToggleButton btnAudio;
private ToggleButton btnBewegung;
//Detektoren
VideoDetector vd = new VideoDetector(this);
private void log(String nachricht) { private void log(String nachricht) {
Log.d(this.getClass().getSimpleName(), nachricht); Log.d(this.getClass().getSimpleName(), nachricht);
} }
@ -30,6 +44,31 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main); setContentView(R.layout.activity_main);
alarm = findViewById(R.id.Alarm); alarm = findViewById(R.id.Alarm);
alarm.setText(text); alarm.setText(text);
toggleKamera = findViewById(R.id.toggleKamera);
toggleKamera.setOnClickListener(this);
vd.setOnDetectionListener(new Detector.OnDetectionListener() {
@Override
public void onDetection(@NonNull DetectionReport detectionReport) {
DetectionReport dr = detectionReport;
String drString = dr.toString();
}
});
//boolean isRunning = vd.isRunning();
}
@Override
public void onClick(View v) {
if (v == toggleKamera) {
if (toggleKamera.isChecked()) {
vd.startDetection();
} else {
vd.stopDetection();
}
}
} }
public void onClickZeigeFragment1(View view) { public void onClickZeigeFragment1(View view) {
Button button = (Button) view; Button button = (Button) view;

View File

@ -5,7 +5,7 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="@android:color/holo_green_dark" android:background="@android:color/holo_green_dark"
android:visibility="visible" android:visibility="visible"
tools:context="de.oklein.android.ueberwachungssystem.MainActivity" tools:context="com.example.ueberwachungssystem.MainActivity"
tools:visibility="visible"> tools:visibility="visible">
<ToggleButton <ToggleButton
@ -100,7 +100,7 @@
android:id="@+id/frame" android:id="@+id/frame"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="200dp" android:layout_height="200dp"
android:layout_below="@+id/btnZwischen" android:layout_below="@+id/btnAufnahme"
android:layout_alignParentStart="true"> android:layout_alignParentStart="true">
</FrameLayout> </FrameLayout>

View File

@ -1,4 +1,4 @@
package de.oklein.android.ueberwachungssystem; package com.example.ueberwachungssystem;
import org.junit.Test; import org.junit.Test;