We are about to switch to a new forum software. Until then we have removed the registration on this forum.
The following code results in a stutter type effect on the live video. If I take the 'scaler' var off (ie, make the Capture video and OpenCV instances the same dimensions) it works (but slower). It seems to be the temp = video.get(); that is throwing it. Any ideas? Here is a video of it in action if that helps.
import gab.opencv.*;
import processing.video.*;
import java.awt.*;
// for movie input
Movie myMovie;
// for live input
Capture video;
PImage temp; // temporary pimage to copy video capture and resize
boolean live = true; // are we using live vid or a pre-rendered?
// performing computer vision
OpenCV opencv;
// arraylist of trackbox instances
ArrayList<Trackbox> trackers = new ArrayList<Trackbox>();
int sloganID; // which slogan gets printed below face
int scaler = 2; // ratio of video to CV
int camW = 640;
int camH = 480;
void setup() {
size(camW, camH, OPENGL);
//smooth();
frameRate(30);
// for live video capture...
if (live) {
String[] cameras = Capture.list();
if (cameras.length == 0) {
println("There are no cameras available for capture.");
exit();
} else {
println("Available cameras:");
for (int i = 0; i < cameras.length; i++) {
println(cameras[i]);
}
}
video = new Capture(this, camW, camH);
video.start();
}
opencv = new OpenCV(this, camW / scaler, camH / scaler);
temp = new PImage(camW, camH);
opencv.loadCascade(OpenCV.CASCADE_FRONTALFACE);
if (!live) {
// load in an video
myMovie = new Movie(this, "train.mov");
myMovie.play();
}
}
void draw() {
//scale(2);
if (live) {
temp = video.get();
image(video, 0, 0 );
} else {
temp = myMovie.get();
image(myMovie, 0, 0 );
}
temp.resize(opencv.width, opencv.height);
opencv.loadImage(temp);
// create array of rectangles around faces in video
Rectangle[] faces = opencv.detect();
// see if we need to add or subract trackers
if (faces.length > trackers.size()) {
// more faces needed
for (int i = trackers.size(); i < faces.length; i++) {
trackers.add(new Trackbox(faces[i].x, faces[i].y, faces[i].width, faces[i].height));
}
}
if (faces.length < trackers.size()) {
// fewer faces needed
for (int i = trackers.size(); i > faces.length; i--) {
trackers.remove(i - 1);
}
}
for (int i = 0; i < trackers.size(); i++) {
Trackbox t = trackers.get(i);
t.update(faces[i].x, faces[i].y, faces[i].width, faces[i].height);
}
}
void captureEvent(Capture c) {
c.read();
}
Answers
redraw = true
inside captureEvent().http://forum.processing.org/two/discussion/10541/problems-with-video
This is great, thank you!
I use the get() function so that I can shrink the temp PImage and have OpenCV do analysis on that instance rather than the full frame. Is there a better function than get?
This is great, thank you! One major problem though is that when I add the Thread stuff I get this error:
Also, if I want to record the non-live movie with all my overlayed effects, is there a better way to do that than to just frameOut every draw loop and recombine JPGs?
As mentioned, I don't have the hardware! So anything I do is just an educated guess.
If you say that thread() here:
if (!isBusy) thread("frameDetection");
is buggy, you can try w/o it:
if (!isBusy) frameDetection();
By using thread(), we've gotta make sure not to modify sketch's canvas while in it.
Either you've included such code there or library OpenCV did it! :|
P.S.: Maybe the problem lies in class Trackbox.
Since you haven't posted its implementation, it's a mystery whether it modifies sketch's canvas or not! :-\"
it does indeed modify the canvas,
float lerpSpeed = .5; // how quick the box is. lower number is smoother but slower
It works well enough, though. I think I'm more concerned now with capturing it as a video to playback later. Any thoughts on that? Also thanks so much for your hep so far :))
This is fantastic! Thank you so much for your help. I do have a final question of course ;-)
When the input is not live, the goal is to output a movie file. I'm comfortable using saveFrames() and rebuilding with another program, but I'd love if there was a way to advance only a single frame at a time in the video so that the resulting video isn't effected by the system lag incurred from CV! Any ideas?
Perusing its reference: https://processing.org/reference/libraries/video/index.html
I've found out speed(): https://processing.org/reference/libraries/video/Movie_speed_.html
Check it out my latest v2.3 template above... B-)
static final int INTERVAL = 2 * 1000;
along w/delay(INTERVAL)
would ease the sketch's burden for 2 whole seconds! \m/speed(SPD)
too. :DAh okay, I was thrown off by speed() not effecting the sound. This is great, thanks so much! In the spirit of continuing our little processing class here ... ;-)
I'm getting this error only when it's in LIVE mode, any thoughts?
code:
synchronized ()
: http://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.htmlThanks! sorry, I edited my post but it appears to have reverted.
You are very right, it would seem. It's my trackers.remove() that it's not diggin...
I tried editing that portion at the bottom where it removes a tracker to
but it still throws a concurrent modification exception. Is there some way to just catch this exception so the program won't stop at least?
It seems to throw more exceptions when I have some modes enabled that use get(), like:
Concurrency is a very advanced subject in Java, unfortunately... ~O)
Since the used loop type there is the regular
for ( ; ; )
, and not thefor ( : )
type, and therefore it's not based on a "fail-fast" Iterator, it can't by itselfthrow
any ConcurrentModificationException. :-BHowever, since it uses remove(), it surely can cause such in some other
for ( : )
loop happening in another Thread! :-SBut be aware that remove() can also
throw
IndexOutOfBoundsException. :(|)For a solution, I dunno how much you figured out about how to use
synchronized ()
.In my own example I did it in order to protect draw()'s
for ( : )
loop against the "offender"for ( ; ; )
loops from frameDetection()'s Thread.B/c they were changing tracker's size() via add() & remove(). And that will surely cause ConcurrentModificationException! 8-X
I'm not sure whether get() can be problematic when called outside "Animation"'s Thread.
However, image() certainly is, b/c it alters sketch's canvas! #-o
Either use them exclusively when running under "Animation"'s Thread...
Or use PGraphics in another Thread.
And later stamp them into canvas via image() when it's under "Animation"'s Thread. *-:)
Thank you! Initial tests seem to indicate that putting the synchronize armor around some of the for loops fixed it. I didn't realize add() could also cause these exceptions! GoToLoop, you are the best.