Click here to Skip to main content
15,867,308 members
Articles / Mobile Apps / Android

Motion Detection in Android - Howto

Rate me:
Please Sign up or sign in to vote.
4.60/5 (16 votes)
29 Jun 2014CPOL1 min read 63.3K   48   7
Using OpenCV4Android in Android App

Introduction

This article describes how OpenCV4Android is being used in one of my recently developed Android app to detect motion and face in the captured camera images.

Background

While developing my Android app, I have been researching for a simple way of performing image processing and motion detection. OpenCV, being an open source computer vision and machine learning software library, fits my need as it has been ported into Android environment.

Using the code

For development on Android using OpenCV4Android, there is a good introduction here. I will not go into details in this article but rather focus on how I use the library.

OpenCV4Android has an interface to the built-in phone camera to capture the camera frame for further processing. You can refer to the samples on how the code is being used.

In my app, I capture the input frame and then use the motion detection algorithms provided by the library.

Java
    @Override
    public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
        if (isNotRealTimeProcessing()) {
            // Check if needs to do real-time motion detection
            try {
                streamingLock.lock();
                capturedFrame = inputFrame.rgba();
            } finally {
                streamingLock.unlock();
            }
            if (!frameProcessing && !isUploadInProgress) {
                frameProcessing = true;
                capturedFrame.copyTo(processingFrame);
                fireProcessingAction(ProcessingAction.PROCESS_FRAME);
            }
            return capturedFrame;
        } else {
            return processFrame(inputFrame.rgba());
        }
    }

There are few ways to detect the motions, the simplest one is to convert the frame into gray scale and get the differences between the frames.

Java
public final class BasicDetector extends BaseDetector implements IDetector {

	private static final String TAG = AppConfig.LOG_TAG_APP + ":BasicDetector";

	// number of cyclic frame buffer used for motion detection
	// (should, probably, depend on FPS)
	public static final int N = 4;

	// ring image buffer
	private Mat[] buf = null;
	private int last = 0;

	private List<matofpoint> contours = new ArrayList<matofpoint>();
	private int threshold;
	private Mat hierarchy = new Mat();
	
	public BasicDetector(int threshold) {
		this.threshold = threshold;
	}

	@Override
	public Mat detect(Mat source) {
		Size size = source.size(); // get current frame size
		int i, idx1 = last, idx2;
		Mat silh;

		// allocate images at the beginning or
		// reallocate them if the frame size is changed
		if (buf == null || buf[0].width() != size.width || buf[0].height() != size.height) {
			if (buf == null) {
				buf = new Mat[N];
			} 

			for (i = 0; i < N; i++) {
				if (buf[i] != null) {
					buf[i].release();
					buf[i] = null;
				}
				buf[i] = new Mat(size, CvType.CV_8UC1);
				buf[i] = Mat.zeros(size, CvType.CV_8UC1);
			}
		}
		// convert frame to gray scale
		Imgproc.cvtColor(source, buf[last], Imgproc.COLOR_BGR2GRAY);

		// index of (last - (N-1))th frame
		idx2 = (last + 1) % N;
		last = idx2;

		silh = buf[idx2];

		// get difference between frames
		Core.absdiff(buf[idx1], buf[idx2], silh);

		// and threshold it
		Imgproc.threshold(silh, silh, threshold, 255, Imgproc.THRESH_BINARY);
		
		// Log.i(TAG, "Computed threshold - " + computedThreshold);
		contours.clear();
		Imgproc.findContours(silh, contours, hierarchy, Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);
		Imgproc.drawContours(source, contours, -1, contourColor, contourThickness);
		if (contours.size() > 0) {
			targetDetected = true;
		} else {
			targetDetected = false;
		}
		return source;
	}

}

</matofpoint></matofpoint>

Alternatively you can use background subtractor technique to detect the motion

Java
public final class BackgroundSubtractorDetector extends BaseDetector implements IDetector {

	private static final double LEARNING_RATE = 0.1 ;

	private static final int MIXTURES = 4;
	
	private static final int HISTORY = 3;
	
	private static final double BACKGROUND_RATIO = 0.8;

	// ring image buffer
	private Mat buf = null;
	private BackgroundSubtractorMOG bg;
	private Mat fgMask = new Mat();
	private List<matofpoint> contours = new ArrayList<matofpoint>();
	private Mat hierarchy = new Mat();
	
	public BackgroundSubtractorDetector() {
		bg = new BackgroundSubtractorMOG(HISTORY, MIXTURES, BACKGROUND_RATIO);
	}
	
	public BackgroundSubtractorDetector(int backgroundRatio){
		bg = new BackgroundSubtractorMOG(HISTORY, MIXTURES, (backgroundRatio / 100.0));
	}

	@Override
	public Mat detect(Mat source) {

		// get current frame size
		Size size = source.size(); 
		
		// allocate images at the beginning or
		// reallocate them if the frame size is changed
		if (buf == null || buf.width() != size.width || buf.height() != size.height) {
			if (buf == null) {
				buf = new Mat(size, CvType.CV_8UC1);
				buf = Mat.zeros(size, CvType.CV_8UC1);
			}
		}
		
		// convert frame to gray scale
		Imgproc.cvtColor(source, buf, Imgproc.COLOR_RGBA2RGB);
		
		bg.apply(buf, fgMask, LEARNING_RATE); //apply() exports a gray image by definition
		
		//Imgproc.erode(fgMask, fgMask, new Mat());
		//Imgproc.dilate(fgMask, fgMask, new Mat());
		
	    //Imgproc.cvtColor(fgMask, silh, Imgproc.COLOR_GRAY2RGBA);
		
		contours.clear();
		Imgproc.findContours(fgMask, contours, hierarchy, Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);
		Imgproc.drawContours(source, contours, -1, contourColor, contourThickness);
		if (contours.size() > 0) {
			targetDetected = true;
		} else {
			targetDetected = false;
		}
		return source;
	}

}


</matofpoint></matofpoint>

You can find the source code for these algorithms here.

Few screenshorts using the above algorithms in my Android app.

Motion detection using background subtraction technique

Using background subtraction technique,

Motion detection using background subtraction technique

Points of Interest

Besides motion and face detection, there are definitely a lot more functions that OpenCV4Android can provide. In my next articles I will describe how I use this library for image processing in my Android app.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Malaysia Malaysia
A programmer for a long time, and still learning everyday.

A supporter for open source solutions, and have written quite a few open source software both in .NET and Java.

https://mengwangk.github.io/

Comments and Discussions

 
QuestionError in integration of demo Pin
Member 133416862-Aug-17 3:35
Member 133416862-Aug-17 3:35 
QuestionRequest for the source code Pin
Member 1285410516-Nov-16 5:07
Member 1285410516-Nov-16 5:07 
Praisethanks Pin
Beginner Luck14-Aug-16 19:37
professionalBeginner Luck14-Aug-16 19:37 
Questionthanks Pin
stackprogramer1-Jun-16 21:18
stackprogramer1-Jun-16 21:18 
QuestionSomething have been wrong Pin
Member 1252988717-May-16 16:09
Member 1252988717-May-16 16:09 
QuestionHow to see this software work in android studio? Pin
patangerahul24-Oct-15 23:58
patangerahul24-Oct-15 23:58 
GeneralMy vote of 5 Pin
Ștefan-Mihai MOGA20-Jul-14 4:38
professionalȘtefan-Mihai MOGA20-Jul-14 4:38 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.