We are about to switch to a new forum software. Until then we have removed the registration on this forum.
Hello, When I try to load multiple videos using keyPressed, my videos start flickering. I'm not even sure if this is the right way to switch between videos, but it's working for me except for the flickering. I already have a trigger (the amount of skin colour that is in the screen) for the videos to start playing, the only thing that the keyPressed does is switch between videos. This is the part that (I think) is causing the problem:
if(animationHasBeenStarted == false)
{ {
if (keyPressed) {
if (key == '1') {
tattooImg.stop();
tattooImg = new Movie(this, "Tattoo 2.mov");
tattooImg.play();}
if (key == '2') {
tattooImg.stop();
tattooImg = new Movie(this, "Tattoo 3.mov");
tattooImg.play();}
}
tattooImg.play();
tattooImg.speed(0.2);
tattooImg.noLoop();
animationHasBeenStarted = true;
}
And this is the full code:
//docs.opencv.org/master/db/dd6/classcv_1_1RotatedRect.html#gsc.tab=0
//processing.org/reference/textureMode_.html
//processing.org/reference/vertex_.html
// rotatedRect angle calculation: stackoverflow.com/questions/24073127/opencvs-rotatedrect-angle-does-not-provide-enough-information
// A lot of native OpenCV for java code is used. Mainly because not everything is implemented in the Processing library.
boolean animationHasBeenStarted;
import gab.opencv.*;
import org.opencv.imgproc.Imgproc;
import org.opencv.core.Core;
//import org.opencv.imgproc.Moments;
import org.opencv.core.Mat;
import org.opencv.core.MatOfPoint;
import org.opencv.core.MatOfPoint2f;
import org.opencv.core.MatOfPoint2f;
import org.opencv.core.CvType;
import org.opencv.core.RotatedRect;
import java.awt.Rectangle;
import org.opencv.core.Point;
import org.opencv.core.Size;
import org.opencv.core.Scalar;
import processing.video.*;
Movie tattooImg;
//ArrayList<Contour> contours;
//ArrayList<MatOfPoint> contours;
//ArrayList<MatOfPoint2f> approximations;
//ArrayList<MatOfPoint2f> markers;
//ArrayList<PVector> hierarchyVectors;
PImage src, dst;
Mat hierarchy;
//ArrayList<Contour> polygons;
//ArrayList<Moments> mu;
MatOfPoint largestContoursMat;
//ArrayList<Contour> contours;
//ArrayList<Contour> polygons;
OpenCV opencv;
Mat workMat;
double largest_area = 0.0;
Capture video;
PImage maskImg;
RotatedRect rRect;
void setup() {
size(320, 240, P2D);
String[] cameras = Capture.list();
//video = new Capture(this, 320, 240);
video = new Capture(this, 320, 240, cameras[30]);
video.start();
opencv = new OpenCV( this, video.width, video.height);
//opencv.useColor();
maskImg = createImage(opencv.width, opencv.height, RGB);
tattooImg = new Movie(this, "Tattoo 1.mov");
}
void draw() {
background(255);
//image(tattooImg, mouseX, mouseY);
if (video.available()) {
video.read();
//markerDetector.processFrame(video, true);
//println(video.height);
//PImage test = video;
opencv.loadImage(video);
// call process function
processWithOpenCV();
}
//image(video,0,0);
//image( opencv.getOutput(), 0, 0 );
//image( maskImg,320,0);
// draw some things on top of the image
// only when we have found the largestContour.
// and when the area size is above a certain threshold
if(largestContoursMat != null && largest_area > 2500.0) {
if(animationHasBeenStarted == false)
{ {
if (keyPressed) {
if (key == '1') {
tattooImg.stop();
tattooImg = new Movie(this, "Tattoo 2.mov");
tattooImg.play();}
if (key == '2') {
tattooImg.stop();
tattooImg = new Movie(this, "Tattoo 3.mov");
tattooImg.play();}
}
tattooImg.play();
tattooImg.speed(0.2);
tattooImg.noLoop();
animationHasBeenStarted = true;
}
//strokeWeight(2);
//stroke(255,0,0);
//noFill();
noStroke();
beginShape();
//textureMode(NORMAL);
texture(tattooImg);
Point[] vertices = new Point[4];
rRect.points(vertices);
//vertices[4] = vertices[0];
//Point[] points = largestContoursMat.toArray();
//Point[] points = contoursMat.get();
//for (int j = 0; j < vertices.length; j++) {
// vertex((float)vertices[j].x, (float)vertices[j].y);
//}
vertex((float)vertices[0].x, (float)vertices[0].y, 0, 0);
vertex((float)vertices[1].x, (float)vertices[1].y, tattooImg.width, 0);
vertex((float)vertices[2].x, (float)vertices[2].y, tattooImg.width, tattooImg.height);
vertex((float)vertices[3].x, (float)vertices[3].y, 0, tattooImg.height);
endShape();
float blob_angle_deg = (float) rRect.angle;
if (rRect.size.width < rRect.size.height) {
blob_angle_deg = 90 + blob_angle_deg;
}
//text(blob_angle_deg, 10,10);
noFill();
//strokeWeight(2);
//stroke(0,0,255);
//beginShape();
//MatOfPoint c = contoursMat.get(largest_contour_index);
//Point[] points = largestContoursMat.toArray();
//Point[] points = contoursMat.get();
//for (int j = 0; j < points.length; j++) {
// vertex((float)points[j].x, (float)points[j].y);
// }
// endShape();
//pushMatrix();
// rotate(radians(blob_angle_deg));
// translate((float)vertices[0].x, (float)vertices[0].y);
// scale( (float) (rRect.size.width/tattooImg.width), (float)(rRect.size.height/tattooImg.height));
// image(tattooImg,0,0);
//popMatrix();
}
else {
animationHasBeenStarted = false;
}
}}
void movieEvent(Movie m) {
m.read();
}
void processWithOpenCV() {
// create the matrix in the size of the input image
// can this be done faster?
Mat workMat = OpenCV.imitate(opencv.getColor());
// here we put the video image in the matrix.
OpenCV.toCv(video, workMat);
// switch colors
OpenCV.ARGBtoBGRA(workMat,workMat);
// convert to YCrCb
Imgproc.cvtColor(workMat, workMat, Imgproc.COLOR_BGR2YCrCb);
// check skin range
Core.inRange(workMat, new Scalar(0, 133, 77), new Scalar(255,173,127), workMat);
// eliminate noise with erode and dilate
// http://www.tutorialspoint.com/java_dip/eroding_dilating.htm
int erosion_size = 0;
int dilation_size = 0;
Mat element = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(2*erosion_size + 1, 2*erosion_size+1));
Imgproc.erode(workMat, workMat, element);
Mat element1 = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(2*dilation_size + 1, 2*dilation_size+1));
Imgproc.dilate(workMat, workMat, element1);
// blur it a bit
Imgproc.GaussianBlur(workMat, workMat, new Size(5, 5), 0);
maskImg = opencv.getSnapshot(workMat);
//put the matrix in our opencv object, just for display
//opencv.setGray(workMat);
Mat hierarchyMat = new Mat();
ArrayList<MatOfPoint> contoursMat = new ArrayList<MatOfPoint>();
Imgproc.findContours(workMat, contoursMat, hierarchyMat, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);
// reset the global largest_area
largest_area = 0.0;
int largest_contour_index = 0;
if(contoursMat.size() > 0) {
for( int i = 0; i< contoursMat.size(); i++) {
MatOfPoint c = contoursMat.get(i);
double a = Imgproc.contourArea(c); //,false); // Find the area of contour
if(a > largest_area) {
largest_area = a;
largest_contour_index = i; //Store the index of largest contour
}
}
//println(largest_area);
//Convert contours(i) from MatOfPoint to MatOfPoint2f
MatOfPoint2f contourMMOP2f = new MatOfPoint2f();
// get the largest Contour and get the RotatedRect from it.
largestContoursMat = contoursMat.get(largest_contour_index);
contoursMat.get(largest_contour_index).convertTo(contourMMOP2f, CvType.CV_32FC2);
rRect = Imgproc.minAreaRect(contourMMOP2f);
}
}
Answers
keyPressed, the flag, is true every time it is pressed. this is being checked 60 times a second so you're probably stopping, loading and starting the video more than once,hence the flickering.
use keyReleased(), the method, which will be called once, and once only. (the keyPressed() method might repeat if you keep the key down, so use keyReleased() which won't)
also, avoid using
new Movie()
anywhere within the draw loop. load all the movies in setup() and choose the one you want in draw().ctrl-t to indent your code correctly.
Thank you, it works perfectly now!