123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
- package com.example.greenwatch.sensors;
-
- import android.content.Context;
- import android.graphics.ImageFormat;
- import android.media.Image;
- import android.os.Handler;
- import android.util.Size;
-
- import androidx.camera.core.CameraSelector;
- import androidx.camera.core.ImageAnalysis;
- import androidx.camera.lifecycle.ProcessCameraProvider;
- import androidx.core.content.ContextCompat;
- import androidx.lifecycle.LifecycleOwner;
- import androidx.lifecycle.MutableLiveData;
-
- import java.nio.ByteBuffer;
-
- public class CameraSensor {
- private final MutableLiveData<Boolean> mVideoAlarmDetected = new MutableLiveData<>();
- private static CameraSensor cameraSensorInstance;
- private boolean videoAlarmDetected;
- private boolean isMotionDetected;
- private ByteBuffer previousBuffer;
- private int previousWidth;
- private int previousHeight;
- private final int threshold = 50;
- private int startX;
- private int startY;
- private int endX;
- private int endY;
- private static final long ALARM_RESET_DELAY = 5000;
- private Runnable alarmResetRunnable;
- private final Handler alarmResetHandler = new Handler();
-
- private CameraSensor() {
- videoAlarmDetected = false;
- }
-
- public static synchronized CameraSensor getInstance() {
- if (cameraSensorInstance == null){
- cameraSensorInstance = new CameraSensor();
- }
- return cameraSensorInstance;
- }
-
- public MutableLiveData<Boolean> getVideoAlarmDetectedValue() {
- setMutableLiveDataVideoAlarmDetected();
- return mVideoAlarmDetected;
- }
-
- private void setMutableLiveDataVideoAlarmDetected() {
- mVideoAlarmDetected.setValue(videoAlarmDetected);
- }
-
- public void bindImageAnalysis(ProcessCameraProvider cameraProvider, LifecycleOwner lifecycleOwner, Context context) {
- ImageAnalysis.Builder builder = new ImageAnalysis.Builder();
- builder.setTargetResolution(new Size(640, 480));
- builder.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST);
- ImageAnalysis imageAnalysis = builder.build();
- imageAnalysis.setAnalyzer(
- ContextCompat.getMainExecutor(context),
- imageProxy -> {
-
- int imageFormat = imageProxy.getFormat();
-
- if (imageFormat == ImageFormat.YUV_420_888) {
-
- Image currentImage = imageProxy.getImage();
-
- if (previousHeight != 0) {
- assert currentImage != null;
- isMotionDetected = compareFrames(currentImage);
- }
-
- assert currentImage != null;
- Image.Plane[] planes = currentImage.getPlanes();
- ByteBuffer buffer = planes[0].getBuffer().duplicate();
- previousBuffer = ByteBuffer.allocateDirect(buffer.remaining());
- previousBuffer.put(buffer);
- previousWidth = currentImage.getWidth();
- previousHeight = currentImage.getHeight();
-
- currentImage.close();
-
- if (isMotionDetected) {
-
- videoAlarmDetected = true;
-
- if(alarmResetRunnable != null) {
- alarmResetHandler.removeCallbacks(alarmResetRunnable);
- }
-
- alarmResetRunnable = this::resetAlarmStatus;
- alarmResetHandler.postDelayed(alarmResetRunnable, ALARM_RESET_DELAY);
- }
-
- checkAlarmCondition();
-
- }
-
- imageProxy.close();
- });
-
- CameraSelector cameraSelector = new CameraSelector.Builder().requireLensFacing(CameraSelector.LENS_FACING_BACK).build();
-
- cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, imageAnalysis);
- }
-
- private boolean compareFrames(Image currentImage) {
- Image.Plane[] planes = currentImage.getPlanes();
- ByteBuffer currentBuffer = planes[0].getBuffer();
- int currentWidth = currentImage.getWidth();
- int currentHeight = currentImage.getHeight();
- int yRowStride = planes[0].getRowStride();
- int yPixelStride = planes[0].getPixelStride();
-
- if (previousWidth != currentWidth || previousHeight != currentHeight) {
- return false;
- }
-
- int blockSize = kleinstesQuadrat(previousHeight, previousWidth) / 8;
-
- int numBlocksX = currentWidth / blockSize;
- int numBlocksY = currentHeight / blockSize;
-
- for (int blockY = 0; blockY < numBlocksY; blockY++) {
- for (int blockX = 0; blockX < numBlocksX; blockX++) {
- startX = blockX * blockSize;
- startY = blockY * blockSize;
- endX = startX + blockSize;
- endY = startY + blockSize;
-
- float currentLuminance = berechneMittlereLuminanz(currentBuffer, yRowStride, yPixelStride);
- float previousLuminance = berechneMittlereLuminanz(previousBuffer, yRowStride, yPixelStride);
-
- int pixelDifference = Math.abs((int) previousLuminance - (int) currentLuminance);
-
- if (pixelDifference > threshold) {
- System.out.println(pixelDifference);
- return true;
- }
- }
- }
-
- return false;
- }
-
- private float berechneMittlereLuminanz(ByteBuffer buffer, int rowStride, int pixelStride) {
- int sumLuminance = 0;
- int countPixels = 0;
-
- for (int row = startY; row < endY; row++) {
- for (int col = startX; col < endX; col++) {
- int bufferIndex = row * rowStride + col * pixelStride;
- int currentPixel = buffer.get(bufferIndex) & 0xFF;
-
- sumLuminance += currentPixel;
- countPixels++;
- }
- }
-
- return (float) sumLuminance / countPixels;
- }
-
- private int kleinstesQuadrat(int height, int width) {
- if (height == width) {
- return height;
- } else if (height > width) {
- return kleinstesQuadrat(height - width, width);
- } else {
- return kleinstesQuadrat(height, width - height);
- }
- }
-
- private void resetAlarmStatus() {
- videoAlarmDetected = false;
- alarmResetRunnable = null;
- }
-
- public void checkAlarmCondition() {
- if (videoAlarmDetected && !mVideoAlarmDetected.getValue()) {
- setMutableLiveDataVideoAlarmDetected();
- }
- else if (!videoAlarmDetected && mVideoAlarmDetected.getValue()){
- setMutableLiveDataVideoAlarmDetected();
- }
- }
- }
|