Skip to content

Commit

Permalink
Merge pull request #350 from tm1990/master
Browse files Browse the repository at this point in the history
Added support for multiple points for source of motion
  • Loading branch information
sarxos committed Jun 2, 2015
2 parents 9827348 + 41bce6b commit 1a8501f
Show file tree
Hide file tree
Showing 5 changed files with 326 additions and 9 deletions.
142 changes: 142 additions & 0 deletions webcam-capture/src/example/java/MultipointMotionDetectionExample.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
package com.github.sarxos.webcam;

import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

public class MultipointMotionDetectionExample implements WebcamMotionListener, WebcamPanel.Painter {

public static void main(String[] args) throws InterruptedException {
new MultipointMotionDetectionExample();
}

private static final int INTERVAL = 100; // ms

public static Webcam webcam;
public static WebcamPanel.Painter painter = null;

public MultipointMotionDetectionExample(){
webcam = Webcam.getDefault();
webcam.setViewSize(WebcamResolution.VGA.getSize());

WebcamPanel panel = new WebcamPanel(webcam);
panel.setPreferredSize(WebcamResolution.VGA.getSize());
panel.setPainter(this);
panel.setFPSDisplayed(true);
panel.setFPSLimited(true);
panel.setFPSLimit(20);
panel.setPainter(this);
panel.start();

painter = panel.getDefaultPainter();

JFrame window = new JFrame("Multipoint-motion detection");
window.add(panel);
window.setResizable(true);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.pack();
window.setVisible(true);


WebcamMotionDetector detector = new WebcamMotionDetector(webcam);

//Sets the max amount of motion points to 300 and the minimum range between them to 40
detector.setMaxMotionPoints(300);
detector.setPointRange(40);

detector.setInterval(INTERVAL);
detector.addMotionListener(this);

detector.start();
}


//A HashMap to store all the current points and the current amount of times it has been rendered
//Time rendered is used to remove the point after a certain amount of time
public static HashMap<Point, Integer> motionPoints = new HashMap<Point, Integer>();

//Gets the motion points from the motion detector and adds it to the HashMap
@Override
public void motionDetected(WebcamMotionEvent wme) {
for(Point p : wme.getPoints()){
motionPoints.put(p, 0);
}
}

@Override
public void paintPanel(WebcamPanel panel, Graphics2D g2) {
if (painter != null) {
painter.paintPanel(panel, g2);
}
}


//Used to render the effect for the motion points
private static final Stroke STROKE = new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 1.0f, new float[] { 1.0f }, 0.0f);

//The amount of time each point should be rendered for before being removed
public static final int renderTime = 3;

//The actual size of the rendered effect for each point
public static final int renderSize = 20;

@Override
public void paintImage(WebcamPanel panel, BufferedImage image, Graphics2D g2) {


if (painter != null) {
painter.paintImage(panel, image, g2);
}

//Gets all the points and updates the amount of time they have been rendered for
//And removes the ones that exceed the renderTime variable

ArrayList<Point> rem = new ArrayList<Point>();

for (Map.Entry<Point, Integer> ent : motionPoints.entrySet()) {
Point p = ent.getKey();

if (ent.getValue() != null) {
int tt = ent.getValue();
if (tt >= renderTime) {
rem.add(ent.getKey());

} else {
int temp = ent.getValue() + 1;
motionPoints.put(p, temp);
}

}
}

for(Point p : rem){
motionPoints.remove(p);
}


//Gets all the remaining points after removing the exceeded ones and then renders the current ones as a red square
for(Map.Entry<Point, Integer> ent : motionPoints.entrySet()){
Point p = ent.getKey();

int xx = p.x - (renderSize / 2), yy = p.y - (renderSize / 2);

Rectangle bounds = new Rectangle(xx, yy, renderSize, renderSize);

int dx = (int) (0.1 * bounds.width);
int dy = (int) (0.2 * bounds.height);
int x = (int) bounds.x - dx;
int y = (int) bounds.y - dy;
int w = (int) bounds.width + 2 * dx;
int h = (int) bounds.height + dy;

g2.setStroke(STROKE);
g2.setColor(Color.RED);
g2.drawRect(x, y, w, h);

}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ protected void detect() {
* @param image with the motion detected
*/
private void notifyMotionListeners(BufferedImage currentOriginal) {
WebcamMotionEvent wme = new WebcamMotionEvent(this, previousOriginal, currentOriginal, detectorAlgorithm.getArea(), detectorAlgorithm.getCog());
WebcamMotionEvent wme = new WebcamMotionEvent(this, previousOriginal, currentOriginal, detectorAlgorithm.getArea(), detectorAlgorithm.getCog(), detectorAlgorithm.getPoints());
for (WebcamMotionListener l : listeners) {
try {
l.motionDetected(wme);
Expand Down Expand Up @@ -437,4 +437,22 @@ public WebcamMotionDetectorAlgorithm getDetectorAlgorithm() {
return detectorAlgorithm;
}


public void setMaxMotionPoints(int i){
detectorAlgorithm.setMaxPoints(i);
}

public int getMaxMotionPoints(){
return detectorAlgorithm.getMaxPoints();
}


public void setPointRange(int i){
detectorAlgorithm.setPointRange(i);
}

public int getPointRange(){
return detectorAlgorithm.getPointRange();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.awt.Point;
import java.awt.image.BufferedImage;
import java.util.ArrayList;


/**
Expand Down Expand Up @@ -50,4 +51,36 @@ public interface WebcamMotionDetectorAlgorithm {
* @return Return percentage image fraction covered by motion
*/
double getArea();

/**
* Set the minimum range between each point detected
* @param i the range to set
*/
void setPointRange(int i);

/**
* Set the max amount of points that can be detected at one time
* @param i The amount of points that can be detected
*/
void setMaxPoints(int i);


/**
* Get the current minimum range between each point
* @return The current range
*/
int getPointRange();

/**
* Get the current max amount of points that can be detected at one time
* @return
*/
int getMaxPoints();


/**
* Returns the currently stored points that have been detected
* @return The current points
*/
ArrayList<Point> getPoints();
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package com.github.sarxos.webcam;

import java.awt.Point;
import java.awt.image.BufferedImage;

import com.github.sarxos.webcam.util.jh.JHBlurFilter;
import com.github.sarxos.webcam.util.jh.JHGrayFilter;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.ArrayList;

/**
* Default motion detector algorithm.
*/
Expand Down Expand Up @@ -71,6 +72,7 @@ public BufferedImage prepareImage(BufferedImage original) {

@Override
public boolean detect(BufferedImage previousModified, BufferedImage currentModified) {
points.clear();
int p = 0;

int cogX = 0;
Expand All @@ -79,6 +81,7 @@ public boolean detect(BufferedImage previousModified, BufferedImage currentModif
int w = currentModified.getWidth();
int h = currentModified.getHeight();

int j = 0;
if (previousModified != null) {
for (int x = 0; x < w; x++) {
for (int y = 0; y < h; y++) {
Expand All @@ -88,10 +91,29 @@ public boolean detect(BufferedImage previousModified, BufferedImage currentModif
int pid = combinePixels(cpx, ppx) & 0x000000ff;

if (pid >= pixelThreshold) {
cogX += x;
cogY += y;
p += 1;
}
Point pp = new Point(x, y);
boolean keep = j < maxPoints;

if (keep) {
for (Point g : points) {
if (g.x != pp.x || g.y != pp.y) {
if (pp.distance(g) <= range) {
keep = false;
break;
}
}
}
}

if (keep) {
points.add(new Point(x, y));
j += 1;
}

cogX += x;
cogY += y;
p += 1;
}
}
}
}
Expand Down Expand Up @@ -198,5 +220,73 @@ private static int clamp(int c) {
return 255;
}
return c;
}
}


/**
* ArrayList to store the points for a detected motion
*/
ArrayList<Point> points = new ArrayList<Point>();

/**
* The default minimum range between each point where motion has been detected
*/
public static final int DEFAULT_RANGE = 50;

/**
* The default for the max amount of points that can be detected at one time
*/
public static final int DEFAULT_MAX_POINTS = 100;

/**
* The current minimum range between points
*/
private int range = DEFAULT_RANGE;

/**
* The current max amount of points
*/
private int maxPoints = DEFAULT_MAX_POINTS;

/**
* Set the minimum range between each point detected
* @param i the range to set
*/
public void setPointRange(int i){
range = i;
}

/**
* Get the current minimum range between each point
* @return The current range
*/
public int getPointRange(){
return range;
}


/**
* Set the max amount of points that can be detected at one time
* @param i The amount of points that can be detected
*/
public void setMaxPoints(int i){
maxPoints = i;
}


/**
* Get the current max amount of points that can be detected at one time
* @return
*/
public int getMaxPoints(){
return maxPoints;
}

/**
* Returns the currently stored points that have been detected
* @return The current points
*/
public ArrayList<Point> getPoints(){
return points;
}
}
Loading

0 comments on commit 1a8501f

Please sign in to comment.