@@ -101,12 +101,19 @@ public class VideodetectionAndAccelerometerActivity extends AppCompatActivity im | |||
@Override | |||
public void onChanged(Boolean aBoolean) { | |||
if (aBoolean) { | |||
mVideodetectionAndAccelerometerViewModel.updateDevice(mVideodetectionAndAccelerometerViewModel.getLocalDeviceUUID(), mVideodetectionAndAccelerometerViewModel.getSystemTimeStamp(), true, "Accelerometer", 10); | |||
if (mVideodetectionAndAccelerometerViewModel.getAccelerometerAlarmDetected() && !mVideodetectionAndAccelerometerViewModel.getVideoAlarmDetected()) { | |||
mVideodetectionAndAccelerometerViewModel.updateDevice(mVideodetectionAndAccelerometerViewModel.getLocalDeviceUUID(), mVideodetectionAndAccelerometerViewModel.getSystemTimeStamp(), true, "Accelerometer", 10); | |||
} | |||
else if (mVideodetectionAndAccelerometerViewModel.getVideoAlarmDetected() && !mVideodetectionAndAccelerometerViewModel.getAccelerometerAlarmDetected()) { | |||
mVideodetectionAndAccelerometerViewModel.updateDevice(mVideodetectionAndAccelerometerViewModel.getLocalDeviceUUID(), mVideodetectionAndAccelerometerViewModel.getSystemTimeStamp(), true, "Video", 10); | |||
} | |||
else if (mVideodetectionAndAccelerometerViewModel.getAccelerometerAlarmDetected() && mVideodetectionAndAccelerometerViewModel.getVideoAlarmDetected()) { | |||
mVideodetectionAndAccelerometerViewModel.updateDevice(mVideodetectionAndAccelerometerViewModel.getLocalDeviceUUID(), mVideodetectionAndAccelerometerViewModel.getSystemTimeStamp(), true, "2VideoAndAccelerometer", 10); | |||
} | |||
} | |||
else { | |||
mVideodetectionAndAccelerometerViewModel.updateDevice(mVideodetectionAndAccelerometerViewModel.getLocalDeviceUUID(), mVideodetectionAndAccelerometerViewModel.getSystemTimeStamp(), false, "Accelerometer", 0); | |||
mVideodetectionAndAccelerometerViewModel.updateDevice(mVideodetectionAndAccelerometerViewModel.getLocalDeviceUUID(), mVideodetectionAndAccelerometerViewModel.getSystemTimeStamp(), false, "VideoAndAccelerometer", 0); | |||
} | |||
} | |||
}); | |||
@@ -3,6 +3,7 @@ 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; | |||
@@ -18,9 +19,18 @@ 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; | |||
@@ -59,7 +69,7 @@ public class CameraSensor { | |||
if (previousHeight != 0) { | |||
assert currentImage != null; | |||
videoAlarmDetected = compareFrames(currentImage); | |||
isMotionDetected = compareFrames(currentImage); | |||
} | |||
assert currentImage != null; | |||
@@ -72,6 +82,18 @@ public class CameraSensor { | |||
currentImage.close(); | |||
if (isMotionDetected) { | |||
videoAlarmDetected = true; | |||
if(alarmResetRunnable != null) { | |||
alarmResetHandler.removeCallbacks(alarmResetRunnable); | |||
} | |||
alarmResetRunnable = this::resetAlarmStatus; | |||
alarmResetHandler.postDelayed(alarmResetRunnable, ALARM_RESET_DELAY); | |||
} | |||
checkAlarmCondition(); | |||
} | |||
@@ -85,36 +107,76 @@ public class CameraSensor { | |||
} | |||
private boolean compareFrames(Image currentImage) { | |||
ByteBuffer currentBuffer = currentImage.getPlanes()[0].getBuffer(); | |||
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; | |||
} | |||
for (int row = 0; row < previousHeight; row++) { | |||
for (int col = 0; col < previousWidth; col++) { | |||
int blockSize = kleinstesQuadrat(previousHeight, previousWidth) / 8; | |||
int numBlocksX = currentWidth / blockSize; | |||
int numBlocksY = currentHeight / blockSize; | |||
int previousIndex = row * previousWidth + col; | |||
int currentIndex = row * currentWidth + col; | |||
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; | |||
int previousPixel = previousBuffer.get(previousIndex) & 0xFF; | |||
int currentPixel = currentBuffer.get(currentIndex) & 0xFF; | |||
float currentLuminance = berechneMittlereLuminanz(currentBuffer, yRowStride, yPixelStride); | |||
float previousLuminance = berechneMittlereLuminanz(previousBuffer, yRowStride, yPixelStride); | |||
int pixelDifference = Math.abs(previousPixel - currentPixel); | |||
int threshold = 120; | |||
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(); |
@@ -26,7 +26,9 @@ public class VideodetectionAndAccelerometerViewModel extends ViewModel implement | |||
private AccelerometerSensor mAccelerometerSensor; | |||
private CameraSensor mCameraSensor; | |||
private DeviceRepository mDeviceRepository; | |||
private boolean VideodetectionAndAccelerometerAlarmDetected; | |||
private boolean videoAlarmDetected; | |||
private boolean accelerometerAlarmDetected; | |||
private boolean videodetectionAndAccelerometerAlarmDetected; | |||
@Override | |||
public void init() { | |||
@@ -54,7 +56,9 @@ public class VideodetectionAndAccelerometerViewModel extends ViewModel implement | |||
if (mVideoAlarmDetected == null) { | |||
mVideoAlarmDetected = mCameraSensor.getVideoAlarmDetectedValue(); | |||
} | |||
VideodetectionAndAccelerometerAlarmDetected = false; | |||
videodetectionAndAccelerometerAlarmDetected = false; | |||
videoAlarmDetected = false; | |||
accelerometerAlarmDetected = false; | |||
registerAlarmObserver(); | |||
} | |||
@@ -84,19 +88,37 @@ public class VideodetectionAndAccelerometerViewModel extends ViewModel implement | |||
} | |||
private void setMutableLiveDataVideodetectionAndAccelerometerAlarmDetected() { | |||
mVideodetectionAndAccelerometerAlarmDetected.setValue(VideodetectionAndAccelerometerAlarmDetected); | |||
mVideodetectionAndAccelerometerAlarmDetected.setValue(videodetectionAndAccelerometerAlarmDetected); | |||
} | |||
private void setAccelerometerAlarmDetected(boolean accelerometerAlarmDetected) { | |||
this.accelerometerAlarmDetected = accelerometerAlarmDetected; | |||
} | |||
public boolean getAccelerometerAlarmDetected() { | |||
return accelerometerAlarmDetected; | |||
} | |||
private void setVideoAlarmDetected(boolean videoAlarmDetected) { | |||
this.videoAlarmDetected = videoAlarmDetected; | |||
} | |||
public boolean getVideoAlarmDetected() { | |||
return videoAlarmDetected; | |||
} | |||
Observer<Boolean> observer = new Observer<Boolean>() { | |||
@Override | |||
public void onChanged(Boolean aBoolean) { | |||
if (mVideoAlarmDetected.getValue() || mAccelerometerAlarmDetected.getValue() && !VideodetectionAndAccelerometerAlarmDetected) { | |||
VideodetectionAndAccelerometerAlarmDetected = true; | |||
setAccelerometerAlarmDetected(mAccelerometerAlarmDetected.getValue()); | |||
setVideoAlarmDetected(mVideoAlarmDetected.getValue()); | |||
if (videoAlarmDetected || accelerometerAlarmDetected && !videodetectionAndAccelerometerAlarmDetected) { | |||
videodetectionAndAccelerometerAlarmDetected = true; | |||
setMutableLiveDataVideodetectionAndAccelerometerAlarmDetected(); | |||
} | |||
else if (!mVideoAlarmDetected.getValue() && !mAccelerometerAlarmDetected.getValue() && VideodetectionAndAccelerometerAlarmDetected) { | |||
VideodetectionAndAccelerometerAlarmDetected = false; | |||
else if (!videoAlarmDetected && !accelerometerAlarmDetected && videodetectionAndAccelerometerAlarmDetected) { | |||
videodetectionAndAccelerometerAlarmDetected = false; | |||
setMutableLiveDataVideodetectionAndAccelerometerAlarmDetected(); | |||
} | |||
} |