package developer.image;
import oculusPrime.*;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.imgproc.Imgproc;
import org.opencv.video.BackgroundSubtractorMOG2;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.Arrays;
import java.util.List;
public class OpenCVMotionDetect {
// OpenCVUtils cv = new OpenCVUtils();;
private Mat fore = new Mat();
protected Mat detect = new Mat();
private State state = null;
private Settings settings = null;
private Application app = null;
private final long TIMEOUT = Util.ONE_HOUR;
public volatile boolean imageupdated = false;
// constructor
public OpenCVMotionDetect() {
}
public OpenCVMotionDetect(Application a) {
this();
app = a;
settings = Settings.getReference();
state = State.getReference();
}
public void motionDetectGo() {
if (state.getBoolean(State.values.motiondetect)) {
Util.log("error, motion detect already running", this);
return;
}
state.delete(State.values.streamactivity);
state.set(State.values.motiondetect, true);
new Thread(new Runnable() {
public void run() {
BackgroundSubtractorMOG2 mog = new BackgroundSubtractorMOG2(0, 512, false);
// frame = cv.bufferedImageToMat(ImageUtils.getImageFromStream());
Mat frame = new Mat();
Mat gr = null;
Mat bl = null;
Mat m = new Mat();
long timeout = System.currentTimeMillis() + TIMEOUT;
int f = 0;
int trigger = 0;
while (state.getBoolean(State.values.motiondetect) && System.currentTimeMillis() < timeout) {
if (!state.getBoolean(State.values.motiondetect)) {
Util.log("error, motion detect timeout", this);
return;
}
// BufferedImage img = null;
//
// try {
// img = ImageIO.read(new URL("http://127.0.0.1:" +
// settings.readRed5Setting("http.port") + "/oculusPrime/frameGrabHTTP"));
// } catch (IOException e) {
// e.printStackTrace();
// }
double threshold = settings.getDouble(ManualSettings.motionthreshold.toString());
//
// if (img == null) {
// Util.log("stream unavailable", this);
// break;
// }
boolean fg = app.frameGrab();
long waittime = System.currentTimeMillis() + 5000;
while (state.getBoolean(State.values.framegrabbusy) && System.currentTimeMillis() < waittime) {
Util.delay(1);
if (!state.getBoolean(State.values.motiondetect)) return; // help reduce cpu quicker on shutdown
}
if (state.getBoolean(State.values.framegrabbusy) || !fg) {
app.driverCallServer(PlayerCommands.messageclients,
"OpenCVMotionDetect().motionDetectGo() frame unavailable");
return;
}
BufferedImage img = ImageUtils.toBufferedImageOfType(app.processedImage, BufferedImage.TYPE_3BYTE_BGR);
frame = OpenCVUtils.bufferedImageToMat(img);
mog.apply(frame, fore, 0);
// mog.apply(frame, fore);
Imgproc.erode(fore, fore, new Mat());
Imgproc.dilate(fore, fore, new Mat());
double movingpixels = Core.countNonZero(fore);
double activity = movingpixels / (fore.width()*fore.height());
if ( activity > threshold && f>1) { // motion detected
if (trigger >=3) {
// System.out.println(movingpixels);
if (!state.getBoolean(State.values.motiondetect)) break;
fore.copyTo(m);
if (gr == null) gr = new Mat().zeros(frame.height(), frame.width(), CvType.CV_8U);
if (bl == null) bl = new Mat().zeros(frame.height(), frame.width(), CvType.CV_8U);
List<Mat> listMat = Arrays.asList(bl, gr, m);
Core.merge(listMat, m);
Core.addWeighted(m, 0.50, frame, 1.0, 1.0, detect);
// Imgproc.cvtColor(m, m, Imgproc.COLOR_GRAY2BGR);
// Core.addWeighted(m, 0.5, frame, 1.0, 1.0, detect);
Application.processedImage = OpenCVUtils.matToBufferedImage(detect);
imageupdated = true;
state.set(State.values.streamactivity, "video " + activity);
if (app != null)
app.driverCallServer(PlayerCommands.messageclients, "motion detected " + activity);
break;
}
else trigger ++;
} else trigger = 0;
f ++;
Util.delay(150); // cpu saver
}
detect.release();
frame.release();
if (gr != null) gr.release();
if (bl != null) bl.release();
m.release();
state.set(State.values.motiondetect, false);
}
}).start();
}
public void motionDetectGoTest() {
new Thread(new Runnable() { public void run() {
double threshold= 0.00001;
int f = 0;
BackgroundSubtractorMOG2 mog = new BackgroundSubtractorMOG2(0, 16, false);
Mat frame;
Mat gr = null;
Mat bl = null;
Mat m = new Mat();
String port = "5080";
if (settings != null) {
port = settings.readRed5Setting("http.port");
}
while (true) {
if (state != null) {
if (!state.getBoolean(State.values.motiondetect)) break;
if (!state.get(State.values.stream).equals(Application.streamstate.camera.toString()) &&
!state.get(State.values.stream).equals(Application.streamstate.camandmic.toString()) ) {
state.delete(State.values.motiondetect);
break;
}
}
BufferedImage img = null;
try {
img = ImageIO.read(new URL("http://127.0.0.1:" + port + "/oculusPrime/frameGrabHTTP"));
} catch (IOException e) {
e.printStackTrace();
state.delete(State.values.motiondetect);
break;
}
if (img == null) {
Util.log("stream unavailable", this);
state.delete(State.values.motiondetect);
break;
}
frame = OpenCVUtils.bufferedImageToMat(img);
// frame = cv.bufferedImageToMat(ImageUtils.getImageFromStream());
mog.apply(frame, fore, 0.01);
// mog.apply(frame, fore);
Imgproc.erode(fore, fore, new Mat());
Imgproc.dilate(fore, fore, new Mat());
double movingpixels = Core.countNonZero(fore);
double activity = movingpixels / (fore.width() * fore.height());
if (activity > threshold && f > 1) { // motion detected
// System.out.println(movingpixels);
fore.copyTo(m);
if (gr == null) gr = new Mat().zeros(frame.height(), frame.width(), CvType.CV_8U);
if (bl == null) bl = new Mat().zeros(frame.height(), frame.width(), CvType.CV_8U);
List<Mat> listMat = Arrays.asList(bl, gr, m);
Core.merge(listMat, m);
Core.addWeighted(m, 1.0, frame, 1.0, 1.0, detect);
// Imgproc.cvtColor(m, m, Imgproc.COLOR_GRAY2BGR);
// Core.addWeighted(m, 0.5, frame, 1.0, 1.0, detect);
}
else {
frame.copyTo(detect);
}
imageupdated = true;
f++;
Util.delay(50);
}
} }).start();
}
public void motionDetectStream() {
if (!state.get(State.values.stream).equals(Application.streamstate.camera.toString()) &&
!state.get(State.values.stream).equals(Application.streamstate.camandmic.toString()) ) {
app.message("motion detect unavailable, camera not running", null, null);
return;
}
state.set(State.values.motiondetect, true);
motionDetectGoTest();
new Thread(new Runnable() {
public void run() {
try {
while(state.getBoolean(State.values.motiondetect)) {
if (imageupdated) {
app.videoOverlayImage = OpenCVUtils.matToBufferedImage(detect);
imageupdated = false;
}
Util.delay(10);
}
} catch (Exception e) {
e.printStackTrace();
state.delete(State.values.motiondetect);
}
}
}).start();
}
}