@Override | @Override | ||||
public void onChanged(Boolean aBoolean) { | public void onChanged(Boolean aBoolean) { | ||||
if (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 { | else { | ||||
mVideodetectionAndAccelerometerViewModel.updateDevice(mVideodetectionAndAccelerometerViewModel.getLocalDeviceUUID(), mVideodetectionAndAccelerometerViewModel.getSystemTimeStamp(), false, "Accelerometer", 0); | |||||
mVideodetectionAndAccelerometerViewModel.updateDevice(mVideodetectionAndAccelerometerViewModel.getLocalDeviceUUID(), mVideodetectionAndAccelerometerViewModel.getSystemTimeStamp(), false, "VideoAndAccelerometer", 0); | |||||
} | } | ||||
} | } | ||||
}); | }); | ||||
import android.content.Context; | import android.content.Context; | ||||
import android.graphics.ImageFormat; | import android.graphics.ImageFormat; | ||||
import android.media.Image; | import android.media.Image; | ||||
import android.os.Handler; | |||||
import android.util.Size; | import android.util.Size; | ||||
import androidx.camera.core.CameraSelector; | import androidx.camera.core.CameraSelector; | ||||
private final MutableLiveData<Boolean> mVideoAlarmDetected = new MutableLiveData<>(); | private final MutableLiveData<Boolean> mVideoAlarmDetected = new MutableLiveData<>(); | ||||
private static CameraSensor cameraSensorInstance; | private static CameraSensor cameraSensorInstance; | ||||
private boolean videoAlarmDetected; | private boolean videoAlarmDetected; | ||||
private boolean isMotionDetected; | |||||
private ByteBuffer previousBuffer; | private ByteBuffer previousBuffer; | ||||
private int previousWidth; | private int previousWidth; | ||||
private int previousHeight; | 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() { | private CameraSensor() { | ||||
videoAlarmDetected = false; | videoAlarmDetected = false; | ||||
if (previousHeight != 0) { | if (previousHeight != 0) { | ||||
assert currentImage != null; | assert currentImage != null; | ||||
videoAlarmDetected = compareFrames(currentImage); | |||||
isMotionDetected = compareFrames(currentImage); | |||||
} | } | ||||
assert currentImage != null; | assert currentImage != null; | ||||
currentImage.close(); | currentImage.close(); | ||||
if (isMotionDetected) { | |||||
videoAlarmDetected = true; | |||||
if(alarmResetRunnable != null) { | |||||
alarmResetHandler.removeCallbacks(alarmResetRunnable); | |||||
} | |||||
alarmResetRunnable = this::resetAlarmStatus; | |||||
alarmResetHandler.postDelayed(alarmResetRunnable, ALARM_RESET_DELAY); | |||||
} | |||||
checkAlarmCondition(); | checkAlarmCondition(); | ||||
} | } | ||||
} | } | ||||
private boolean compareFrames(Image currentImage) { | 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 currentWidth = currentImage.getWidth(); | ||||
int currentHeight = currentImage.getHeight(); | int currentHeight = currentImage.getHeight(); | ||||
int yRowStride = planes[0].getRowStride(); | |||||
int yPixelStride = planes[0].getPixelStride(); | |||||
if (previousWidth != currentWidth || previousHeight != currentHeight) { | if (previousWidth != currentWidth || previousHeight != currentHeight) { | ||||
return false; | 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) { | if (pixelDifference > threshold) { | ||||
System.out.println(pixelDifference); | |||||
return true; | return true; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
return false; | 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() { | public void checkAlarmCondition() { | ||||
if (videoAlarmDetected && !mVideoAlarmDetected.getValue()) { | if (videoAlarmDetected && !mVideoAlarmDetected.getValue()) { | ||||
setMutableLiveDataVideoAlarmDetected(); | setMutableLiveDataVideoAlarmDetected(); |
private AccelerometerSensor mAccelerometerSensor; | private AccelerometerSensor mAccelerometerSensor; | ||||
private CameraSensor mCameraSensor; | private CameraSensor mCameraSensor; | ||||
private DeviceRepository mDeviceRepository; | private DeviceRepository mDeviceRepository; | ||||
private boolean VideodetectionAndAccelerometerAlarmDetected; | |||||
private boolean videoAlarmDetected; | |||||
private boolean accelerometerAlarmDetected; | |||||
private boolean videodetectionAndAccelerometerAlarmDetected; | |||||
@Override | @Override | ||||
public void init() { | public void init() { | ||||
if (mVideoAlarmDetected == null) { | if (mVideoAlarmDetected == null) { | ||||
mVideoAlarmDetected = mCameraSensor.getVideoAlarmDetectedValue(); | mVideoAlarmDetected = mCameraSensor.getVideoAlarmDetectedValue(); | ||||
} | } | ||||
VideodetectionAndAccelerometerAlarmDetected = false; | |||||
videodetectionAndAccelerometerAlarmDetected = false; | |||||
videoAlarmDetected = false; | |||||
accelerometerAlarmDetected = false; | |||||
registerAlarmObserver(); | registerAlarmObserver(); | ||||
} | } | ||||
} | } | ||||
private void setMutableLiveDataVideodetectionAndAccelerometerAlarmDetected() { | 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>() { | Observer<Boolean> observer = new Observer<Boolean>() { | ||||
@Override | @Override | ||||
public void onChanged(Boolean aBoolean) { | 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(); | setMutableLiveDataVideodetectionAndAccelerometerAlarmDetected(); | ||||
} | } | ||||
else if (!mVideoAlarmDetected.getValue() && !mAccelerometerAlarmDetected.getValue() && VideodetectionAndAccelerometerAlarmDetected) { | |||||
VideodetectionAndAccelerometerAlarmDetected = false; | |||||
else if (!videoAlarmDetected && !accelerometerAlarmDetected && videodetectionAndAccelerometerAlarmDetected) { | |||||
videodetectionAndAccelerometerAlarmDetected = false; | |||||
setMutableLiveDataVideodetectionAndAccelerometerAlarmDetected(); | setMutableLiveDataVideodetectionAndAccelerometerAlarmDetected(); | ||||
} | } | ||||
} | } |