package developer.image;
import oculusPrime.*;
import org.opencv.core.*;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.HOGDescriptor;
import org.opencv.video.BackgroundSubtractorMOG2;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.Arrays;
import java.util.List;
public class OpenCVObjectDetect {
private State state = null;
private Settings settings = null;
private Application app = null;
public volatile boolean imageupdated = false;
public volatile Mat detect = new Mat();
private final long TIMEOUT = Util.TEN_MINUTES * 3;
public static final String HUMAN = "human";
HOGDescriptor hog;
public OpenCVObjectDetect(Application a) {
app = a;
settings = Settings.getReference();
state = State.getReference();
}
public void detectGo(final String mode) {
if (state.exists(State.values.objectdetect)) {
Util.log("error, object detect already running", this);
return;
}
state.delete(State.values.streamactivity);
state.set(State.values.objectdetect, mode);
// TODO: testing only
int n=0;
if (state.exists("objectdetectcount")) {
n = state.getInteger("objectdetectcount")+1;
}
state.set("objectdetectcount", n);
Util.log("objectdetectcount: " + n, this);
// testing to see if alleviates jvm crash
// System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
new Thread(new Runnable() {
public void run() {
// try creating object within thread, to prevent seg faults after ~50 detect sessions
// tested, crashed after 69
// crash happend AFTER thread exit, BEFORE above objectdetectcount log
// (ie., during garbage collection??)
// HOGDescriptor hog = new HOGDescriptor();
hog = new HOGDescriptor();
if (mode.equals(HUMAN)) {
hog.setSVMDetector(HOGDescriptor.getDefaultPeopleDetector());
// hog.setSVMDetector(HOGDescriptor.getDaimlerPeopleDetector());
}
Mat frame = new Mat();
int trigger = 0;
long timeout = System.currentTimeMillis() + TIMEOUT;
while (state.exists(State.values.objectdetect) && System.currentTimeMillis() < timeout) {
if (!state.exists(State.values.objectdetect)) {
Util.log("error, object detect timeout", this);
return;
}
// get frame
boolean fg = app.frameGrab();
long waittime = System.currentTimeMillis() + 2000;
while (state.getBoolean(State.values.framegrabbusy) && System.currentTimeMillis() < waittime) {
Util.delay(1);
if (!state.exists(State.values.objectdetect)) return; // help reduce cpu quicker on shutdown
}
if (state.getBoolean(State.values.framegrabbusy) || !fg) {
app.driverCallServer(PlayerCommands.messageclients,
"OpenCVObjectDetect().detectGo() frame unavailable");
state.delete(State.values.objectdetect);
return;
}
BufferedImage img = ImageUtils.toBufferedImageOfType(app.processedImage, BufferedImage.TYPE_3BYTE_BGR);
frame = OpenCVUtils.bufferedImageToMat(img);
// Mat result = new Mat();
// frame.copyTo(result);
if (!state.exists(State.values.objectdetect)) break; // helps with timely exit
// process frame
MatOfRect found = new MatOfRect();
MatOfDouble weight = new MatOfDouble();
// Imgproc.cvtColor(frame, frame, Imgproc.COLOR_BGRA2GRAY);
if (mode.equals(HUMAN))
hog.detectMultiScale(frame, found, weight, 0, new Size(8, 8), new Size(32, 32), 1.05, 2, false);
Rect [] rects = found.toArray();
weight.release();
found.release();
if (rects.length > 0) { // maybe detection!
if (!state.exists(State.values.objectdetect)) break;
for (int i = 0; i < rects.length; i++) {
// most false-positives go off-frame
if (rects[i].x < 0 || rects[i].x + rects[i].width > frame.width() ||
rects[i].y<0 || rects[i].y+rects[i].height > frame.height())
continue;
if (trigger >= 2) {
Core.rectangle(frame, new Point(rects[i].x, rects[i].y),
new Point(rects[i].x + rects[i].width, rects[i].y + rects[i].height),
new Scalar(255, 0, 0, 255), 2);
Application.processedImage = OpenCVUtils.matToBufferedImage(frame);
state.set(State.values.streamactivity, mode);
if (app != null)
app.driverCallServer(PlayerCommands.messageclients, mode + " detected");
state.delete(State.values.objectdetect); // end thread
} else trigger++;
}
} else trigger = 0;
Util.delay(100); // cpu saver, maybe try increasing this if mat.release() not solution - was 50
}
frame.release(); // testing, cleanup saves JVM crash? NO
state.delete(State.values.objectdetect);
Util.log("objectdetect exit", this);
}
}).start();
}
private void humanDetectGoTest() {
new Thread(new Runnable() { public void run() {
int f = 0;
hog = new HOGDescriptor();
hog.setSVMDetector(HOGDescriptor.getDefaultPeopleDetector());
String port = "5080";
if (settings != null) {
port = settings.readRed5Setting("http.port");
}
int trigger = 0;
while (true) {
if (state != null) {
if (!state.exists(State.values.objectdetect)) 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.objectdetect);
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.objectdetect);
break;
}
if (img == null) {
Util.log("stream unavailable", this);
state.delete(State.values.objectdetect);
break;
}
f++;
if (f<=1) continue;
detect = OpenCVUtils.bufferedImageToMat(img);
MatOfRect found = new MatOfRect();
MatOfDouble weight = new MatOfDouble();
hog.detectMultiScale(detect, found, weight, 0, new Size(8, 8), new Size(32, 32), 1.05, 2, false);
Rect [] rects = found.toArray();
if (rects.length > 0) {
for (int i=0; i<rects.length; i++) {
// most false-positives go off-frame
if (rects[i].x<0 || rects[i].x+rects[i].width > detect.width() ||
rects[i].y<0 || rects[i].y+rects[i].height > detect.height())
continue;
if (trigger >= 2) {
Util.debug("human detected");
Core.rectangle(detect, new Point(rects[i].x, rects[i].y),
new Point(rects[i].x + rects[i].width, rects[i].y + rects[i].height),
new Scalar(255, 0, 0, 255), 2);
trigger = 0; // reset
} else trigger ++;
}
} else trigger = 0;
imageupdated = true;
Util.debug("human detect frame: "+f);
Util.delay(50);
}
} }).start();
}
public void detectStream(String mode) {
if (!state.get(State.values.stream).equals(Application.streamstate.camera.toString()) &&
!state.get(State.values.stream).equals(Application.streamstate.camandmic.toString()) ) {
app.message("object detect unavailable, camera not running", null, null);
return;
}
state.set(State.values.objectdetect, mode);
if (mode.equals(HUMAN)) humanDetectGoTest();
new Thread(new Runnable() {
public void run() {
try {
while(state.exists(State.values.objectdetect)) {
if (imageupdated) {
app.videoOverlayImage = OpenCVUtils.matToBufferedImage(detect);
imageupdated = false;
}
Util.delay(10);
}
} catch (Exception e) {
e.printStackTrace();
state.delete(State.values.objectdetect);
}
}
}).start();
}
}