Skip to content

Commit

Permalink
more work on #365 - simplify display of motion detection
Browse files Browse the repository at this point in the history
- we are creating too many in memory bitmaps just for fancy UI that isn't that usable
- this now displays a simple "motion detected" string instead of the change detection overlay
  • Loading branch information
n8fr8 committed Feb 8, 2019
1 parent 06c4a8c commit e8f3774
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 102 deletions.
45 changes: 18 additions & 27 deletions src/main/java/org/havenapp/main/sensors/motion/MotionDetector.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ public class MotionDetector {
// Input data

private List<MotionListener> listeners = new ArrayList<>();
private Handler handler;
private int motionSensitivity;
// Output data

Expand All @@ -58,14 +57,13 @@ public void addListener(MotionListener listener) {
}

public MotionDetector(

Handler updateHandler,
int motionSensitivity) {
// this.renderScript = renderScript;
this.handler = updateHandler;
this.motionSensitivity = motionSensitivity;
detector = new LuminanceMotionDetector();



}

public void setDetectColor (int detectColor)
Expand All @@ -87,19 +85,19 @@ public void detect(byte[] rawOldPic,
boolean facingFront) {

int[] newPicLuma = ImageCodec.N21toLuma(rawNewPic, width, height);
if (rawOldPic != null) {

if (rawOldPic != null) {

detector.setThreshold(motionSensitivity);
List<Integer> changedPixels =
detector.detectMotion(ImageCodec.N21toLuma(rawOldPic, width, height), newPicLuma, width, height);

if (changedPixels != null) {

/*
int[] newPic = ImageCodec.lumaToGreyscale(newPicLuma, width, height);
newPicLuma = null;

System.gc();
for (int i = 0; i < newPic.length; i++)
Expand All @@ -109,8 +107,6 @@ public void detect(byte[] rawOldPic,
newPic[changedPixel] = detectColor;
}


Matrix mtx = new Matrix();
if (facingFront) {
Expand All @@ -124,31 +120,26 @@ public void detect(byte[] rawOldPic,
= Bitmap.createBitmap(Bitmap.createBitmap(newPic, width, height, Bitmap.Config.ARGB_4444), 0, 0, width, height, mtx, true);
newPic = null;
*/

Bitmap rawBitmap = convertImage(rawNewPic,width,height);

handler.post(() -> {
for (MotionListener listener : listeners) {
listener.onProcess(
newBitmap,
rawBitmap,
true);
}

});
for (MotionListener listener : listeners) {
listener.onProcess(
null,
rawBitmap,
true);
}
}
else
{
//nothing changed
handler.post(() -> {
for (MotionListener listener : listeners) {
listener.onProcess(
null,
null,
false);
}

});
for (MotionListener listener : listeners) {
listener.onProcess(
null,
null,
false);
}

}

}
Expand Down
55 changes: 43 additions & 12 deletions src/main/java/org/havenapp/main/ui/CameraFragment.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@
*/
package org.havenapp.main.ui;

import android.graphics.Bitmap;
import android.hardware.SensorEvent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
Expand All @@ -30,6 +33,41 @@ public final class CameraFragment extends Fragment {
private ImageView newImage;
private PreferenceManager prefs;
private TextView txtCameraStatus;
private Bitmap lastBitmap;

/**
* Handler used to update back the UI after motion detection
*/
private final Handler handler = new Handler()
{
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);

if (!isDetached()) {
if (txtCameraStatus != null) {

if (msg.what == 0) {
// newImage.setImageResource(R.drawable.blankimage);
txtCameraStatus.setText("");

} else if (msg.what == 1) {
// newImage.setImageBitmap(lastBitmap);
txtCameraStatus.setText(getString(R.string.motion_detected));

}


/**
if (cameraViewHolder.doingVideoProcessing()) {
txtCameraStatus.setText("Recording...");
} else {
txtCameraStatus.setText("");
}**/
}
}
}
};

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Expand Down Expand Up @@ -98,18 +136,11 @@ public void initCamera ()
cameraViewHolder = new CameraViewHolder(getActivity(), cameraView);

cameraViewHolder.addListener((newBitmap, rawBitmap, motionDetected) -> {
if (motionDetected)
newImage.setImageBitmap(newBitmap);
else
newImage.setImageResource(R.drawable.blankimage);

if (txtCameraStatus != null) {
if (cameraViewHolder.doingVideoProcessing()) {
txtCameraStatus.setText("Recording...");
} else {
txtCameraStatus.setText("");
}
}

lastBitmap = rawBitmap;

handler.sendEmptyMessage(motionDetected?1:0);


});
}
Expand Down
135 changes: 73 additions & 62 deletions src/main/java/org/havenapp/main/ui/CameraViewHolder.java
Original file line number Diff line number Diff line change
Expand Up @@ -134,59 +134,60 @@ public CameraViewHolder(Activity context, CameraView cameraView) {
prefs = new PreferenceManager(context);

task = new MotionDetector(
updateHandler,
motionSensitivity);

task.addListener((detectedImage, rawBitmap, motionDetected) -> {

for (MotionDetector.MotionListener listener : listeners)
listener.onProcess(detectedImage,rawBitmap,motionDetected);

if (motionDetected) {
if (motionDetected)
mEncodeVideoThreadPool.execute(() -> saveDetectedImage(rawBitmap));

if (serviceMessenger != null) {
Message message = new Message();
message.what = EventTrigger.CAMERA;
});
/*
* We bind to the alert service
*/
this.context.bindService(new Intent(context,
MonitorService.class), mConnection, Context.BIND_ABOVE_CLIENT);
}

try {
private void saveDetectedImage (Bitmap rawBitmap)
{
if (serviceMessenger != null) {
Message message = new Message();
message.what = EventTrigger.CAMERA;

File fileImageDir = new File(Environment.getExternalStorageDirectory(), prefs.getDefaultMediaStoragePath());
fileImageDir.mkdirs();
try {

String ts = new SimpleDateFormat(Utils.DATE_TIME_PATTERN,
Locale.getDefault()).format(new Date());
File fileImageDir = new File(Environment.getExternalStorageDirectory(), prefs.getDefaultMediaStoragePath());
fileImageDir.mkdirs();

File fileImage = new File(fileImageDir, ts.concat(".detected.original.jpg"));
FileOutputStream stream = new FileOutputStream(fileImage);
rawBitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
String ts = new SimpleDateFormat(Utils.DATE_TIME_PATTERN,
Locale.getDefault()).format(new Date());

stream.flush();
stream.close();
message.getData().putString("path", fileImage.getAbsolutePath());
File fileImage = new File(fileImageDir, ts.concat(".detected.original.jpg"));
FileOutputStream stream = new FileOutputStream(fileImage);
rawBitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);

//store the still match frame, even if doing video
serviceMessenger.send(message);
stream.flush();
stream.close();
message.getData().putString("path", fileImage.getAbsolutePath());

if (prefs.getVideoMonitoringActive() && (!doingVideoProcessing)) {
recordVideo();
//store the still match frame, even if doing video
serviceMessenger.send(message);

}
if (prefs.getVideoMonitoringActive() && (!doingVideoProcessing)) {
recordVideo();

} catch (Exception e) {
// Cannot happen
Log.e("CameraViewHolder", "error creating image", e);
}
}
}


});
/*
* We bind to the alert service
*/
this.context.bindService(new Intent(context,
MonitorService.class), mConnection, Context.BIND_ABOVE_CLIENT);
}
} catch (Exception e) {
// Cannot happen
Log.e("CameraViewHolder", "error creating image", e);
}
}
}

public void setMotionSensitivity (int
motionSensitivity )
Expand Down Expand Up @@ -242,16 +243,10 @@ public void process(@NonNull Frame frame) {

if (frame.getData() != null && frame.getSize() != null) {

byte[] data = frame.getData();
Size size = frame.getSize();
int width = size.getWidth();
int height = size.getHeight();
int rot = getCorrectCameraOrientation(cameraView.getFacing(),frame.getRotation());

if (!doingVideoProcessing) {
mDecodeThreadPool.execute(() -> processNewFrame(data, width, height, rot));
mDecodeThreadPool.execute(() -> processNewFrame(frame));
} else {
mEncodeVideoThreadPool.execute(() -> recordNewFrame(data, width, height, rot));
mEncodeVideoThreadPool.execute(() -> recordNewFrame(frame));
}
}
}
Expand Down Expand Up @@ -300,25 +295,32 @@ public void updateCamera ()

private Matrix mtxVideoRotate;

private void recordNewFrame (byte[] data, int width, int height, int rotationDegrees)
private void recordNewFrame (Frame frame)
{

Bitmap bitmap = MotionDetector.convertImage(data, width, height);
//Nv21Image.nv21ToBitmap(renderScript, data, width, height);
byte[] data = frame.getData();
Size size = frame.getSize();

bitmap = Bitmap.createBitmap(bitmap,0,0,width,height,mtxVideoRotate,true);
if (data != null && size != null) {
int width = size.getWidth();
int height = size.getHeight();
int rotationDegrees = getCorrectCameraOrientation(cameraView.getFacing(), frame.getRotation());

try {
if (encoder != null)
encoder.encodeImage(bitmap);
Bitmap bitmap = MotionDetector.convertImage(data, width, height);

bitmap.recycle();
bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, mtxVideoRotate, true);

} catch (Exception e) {
e.printStackTrace();
}
try {
if (encoder != null)
encoder.encodeImage(bitmap);

bitmap.recycle();

} catch (Exception e) {
e.printStackTrace();
}

}

}

Expand All @@ -343,18 +345,27 @@ private void finishVideoEncoding ()

}

private synchronized void processNewFrame (byte[] data, int width, int height, int rotationDegrees)
private void processNewFrame (Frame frame)
{
task.detect(
lastPic,
data,
width,
height,
rotationDegrees,
cameraView.getFacing()==Facing.FRONT);

lastPic = data;
byte[] data = frame.getData();
Size size = frame.getSize();

if (data != null && size != null) {
int width = size.getWidth();
int height = size.getHeight();
int rotationDegrees = getCorrectCameraOrientation(cameraView.getFacing(), frame.getRotation());

task.detect(
lastPic,
data,
width,
height,
rotationDegrees,
cameraView.getFacing() == Facing.FRONT);

lastPic = data;
}
}


Expand Down
2 changes: 1 addition & 1 deletion src/main/res/layout/camera_fragment.xml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
android:layout_height="wrap_content"
android:gravity="center"
android:text=""
android:textColor="@color/DarkRed"
android:textColor="@color/Yellow"
android:textSize="28sp"
android:textStyle="bold"
android:layout_gravity="center_horizontal|center_vertical"
Expand Down
1 change: 1 addition & 0 deletions src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -165,5 +165,6 @@
<!-- accepted digits for directory name - may vary for locale/platform/etc.
Skipping periods, spaces, and other special characters to keep it simple -->
<string name="path_chars">0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_/</string>
<string name="motion_detected">MOTION DETECTED</string>

</resources>

0 comments on commit e8f3774

Please sign in to comment.