We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpSyntax Questions › event triggered after time passed...
Page Index Toggle Pages: 1
event triggered after time passed... (Read 931 times)
event triggered after time passed...
Dec 11th, 2009, 1:56am
 
Hi there

My scenario is like this: A person enter af zone, a webcam detects this and Processing shall when a certain amount of movement has occurred over time play an audio file.

For the part of detecting movement I use the Frame Differencing example by Golan Levi and a simple audioplayer - these two parts are working together, but when I try to implement a timer/delay on the player.play(); event I don't get it...

Code:

/**
* Frame Differencing
* by Golan Levin.
*
* Quantify the amount of movement in the video frame using frame-differencing.
*/


import processing.video.*;
import ddf.minim.*;

AudioPlayer player;
Minim minim;

float mills,interval;

int numPixels;
int[] previousFrame;
Capture video;

void setup() {
 size(640, 480); // Change size to 320 x 240 if too slow at 640 x 480
 // Uses the default video input, see the reference if this causes an error
 
 video = new Capture(this, width, height, 24);
 numPixels = video.width * video.height;
 // Create an array to store the previously captured frame
 previousFrame = new int[numPixels];
 loadPixels();
 
 minim = new Minim(this);
 player = minim.loadFile("groove.mp3", 2048);
 
 mills = millis();
 interval=5000;

}

void draw() {
 if (video.available()) {
   // When using video to manipulate the screen, use video.available() and
   // video.read() inside the draw() method so that it's safe to draw to the screen
   video.read(); // Read the new frame from the camera
   video.loadPixels(); // Make its pixels[] array available
   
   int movementSum = 0; // Amount of movement in the frame
   for (int i = 0; i < numPixels; i++) { // For each pixel in the video frame...
     color currColor = video.pixels[i];
     color prevColor = previousFrame[i];
     // Extract the red, green, and blue components from current pixel
     int currR = (currColor >> 16) & 0xFF; // Like red(), but faster
     int currG = (currColor >> 8) & 0xFF;
     int currB = currColor & 0xFF;
     // Extract red, green, and blue components from previous pixel
     int prevR = (prevColor >> 16) & 0xFF;
     int prevG = (prevColor >> 8) & 0xFF;
     int prevB = prevColor & 0xFF;
     // Compute the difference of the red, green, and blue values
     int diffR = abs(currR - prevR);
     int diffG = abs(currG - prevG);
     int diffB = abs(currB - prevB);
     // Add these differences to the running tally
     movementSum += diffR + diffG + diffB;
     // Render the difference image to the screen
     pixels[i] = color(diffR, diffG, diffB);
     // The following line is much faster, but more confusing to read
     //pixels[i] = 0xff000000 | (diffR << 16) | (diffG << 8) | diffB;
     // Save the current color into the 'previous' buffer
     previousFrame[i] = currColor;
   }
   // To prevent flicker from frames that are all black (no movement),
   // only update the screen if the image has changed.
   
   if (movementSum > 0) {
     updatePixels();
   
     println(movementSum); // Print the total amount of movement to the console
   }
   
if (movementSum > 7000000) {
   if (millis()-mills > interval){
     
  player.play();
   
     }
  }
     
}
}

 
public void stop() {
 player.close();
 minim.stop();
 video.stop();
   super.stop();
}


...any suggestions?

Cheers,
Adam
Re: event triggered after time passed...
Reply #1 - Dec 11th, 2009, 3:48am
 
I tend to use the following code for timing, but yours looks fine too...

Code:
if(millis() > startMillis + interval) {
 // do something
}


Perhaps the problem is with the enclosing condition?  Unless there's a good reason for it I'd restructure it so the timing isn't dependent on the condition:

Code:
if (millis()-mills > interval){
 if (movementSum > 7000000) {
   player.play();
   println("play!"); // just to double check that it's not a problem with play()
 }
}
Re: event triggered after time passed...
Reply #2 - Dec 11th, 2009, 4:43am
 
When I try out your code (not in my code.bit)

Code:

if(millis() > startMillis + interval) {
 // do something
}




it works...  Smiley

but when I put it in the code I'm using  - it's not working...

Also I have tried this:

Code:

if (movementSum > 7000000 && millis() > mills + interval )


which still has no effect...

//Adam
Re: event triggered after time passed...
Reply #3 - Dec 11th, 2009, 5:10am
 
Maybe movementSum never reaches this value?
Try and print the value after computation to check that.
Re: event triggered after time passed...
Reply #4 - Dec 11th, 2009, 5:36am
 
The MovementSum reaches the value... It does start to play the audio.file but without the delay...

There must be a way to make a delay (?)

//Adam


Re: event triggered after time passed...
Reply #5 - Dec 11th, 2009, 6:19am
 
Are you setting startMillis to the current millis at the point from which you want to create the delay?  Currently you set it in setup() so in theory the test should return true 5 seconds after launching your sketch.  You may need to add a boolean variable to do that at the appropriate point (untested - but I can dig out tested code if necessary):

Code:
// An event changes 'setTimer' to true
// (if event and setting of startMillis is external to draw (e.g. in mousePressed) this condition probably won't be necessary)
if(setTimer) {
startMillis = millis();
setTimer = false; // so startMillis won't be updated again until necessary
}


So maybe what you really want to be doing is setting startMillis to millis when movementSum > 7000000?
Re: event triggered after time passed...
Reply #6 - Dec 11th, 2009, 8:09am
 
aj.linux wrote on Dec 11th, 2009, 5:36am:
It does start to play the audio.file but without the delay...

You mean a delay after the movementSum has reached the limit
Indeed, as blindfish points out, you have to set mills at this point, not when program starts.
It might be complicated if you abandon the delay if there is no more movement before the interval...

Let see. We set a global boolean variable named bMovementDetected.
Also int msLimit = 7000000;
We can have:
Code:
if (bMovementDetected)
{
if (movementSum > msLimit)
{
// Still detecting activity
if (millis() - startMillis > interval)
{
// Persistent moves
player.play();
}
}
else
{
// No more activity before end of delay, reset detection and delay
bMovementDetected = false;
}
}
else // Nothing detected yet
{
if (movementSum > msLimit)
{
bMovementDetected = true; // Aha, something moved!
startMillis = millis();
}
}

Untested, so I hope I haven't made logic errors...
Page Index Toggle Pages: 1