Display 2 succesive images

Thanks for your answer !!
However if my draw() loop is already full, I means I aim to use it into this code :

  for (int i=0;i<tuioObjectList.size();i++) {
    TuioObject num = tuioObjectList.get(i);
    int ID = num.getSymbolID();
    stroke(0);
    
      if (ID>=0 & ID<=2){
        fill(#FDCA00); 
        rect(0,0,width,height); //not shown
        fill(255);
        text(""+ID,width/2,height/2); // not shown
        myDelay(500);
        background(0);
        if (ID==0){ID0=loadImage("image.png");}
        if (ID==1){ID0=loadImage("image1.png");}
        if (ID==2){ID0=loadImage("image2.png");}
        image(ID0,0,0,width,height); // shown
      }

how can I don’t use a for loop ?
sorry, I don’t know if that’s clear…:roll_eyes:

1 Like

I don’t know.

I don’t know tuio

Sorry!

1 Like

draw() loop full? How so?
If you want it really to be done in setup, you can, but I don’t know if it’s a good idea.

void setup() {
  // load your images
  // set first image
  int start_time = millis();
  int my_time_interval = 2000;  // milli seconds
  while (millis()-start_time < my_time_interval) {}
  // set second image
}

Then again it could be done with delay();

Sorry it wasn’t clear. I want to use TUIO (ReactiVision) to display two images (one by one) when the webcam recognizes the correct symbol. However in my draw() loop I’m kind of stuck in a for() loop to obtain the TUIO symbol ID.
Then I’ve tried to use a delay but it still don’t work and show me only the 2nd image (because we are in a for() loop ? is there is another way to proceed ?). :confounded:

I want to clarify that I’m a beginner on processing and that there probably is an easier way to achieve my goals. Then here is the entire code :

import TUIO.*;

TuioProcessing tuioClient;

PImage map,conti;
PImage ID0,ID1;

void setup()
{
  noCursor();
  fullScreen();
  noStroke();
  fill(0);
  background(255);
  map=loadImage("WorldMap3.png");
  conti=loadImage("LOCALISATION 0 - Vierge.png");

  tuioClient  = new TuioProcessing(this);
  
}
 
 
void draw()
{
  background(255);
  image(map,0,0,width,height);
  textSize(70);
  ArrayList<TuioObject> tuioObjectList = tuioClient.getTuioObjectList();
  
  for (int i=0;i<tuioObjectList.size();i++) {    // for() loop to obtain the TUIO symbol ID
    TuioObject num = tuioObjectList.get(i);
    int ID = num.getSymbolID();
    stroke(0);
    
      if (ID>=0 & ID<=2){
        
        image(conti,0,0,width,height); // set first image
        myDelay(500);    // same delay as yours
        background(0);
        if (ID==0){ID0=loadImage("image.png");}
        if (ID==1){ID0=loadImage("image1.png");}
        if (ID==2){ID0=loadImage("image3.png");}
        image(ID0,0,0,width,height); // set second image
      }

      if (ID>=3 & ID<=5){
        image(conti,0,0,width,height); // set first image
        myDelay(500);    // same delay as yours
        background(0);
        if (ID==0){ID0=loadImage("image.png");}
        if (ID==1){ID0=loadImage("image1.png");}
        if (ID==2){ID0=loadImage("image3.png");}
        image(ID0,0,0,width,height); // set second image
      }
      
      if (ID==6){
        fill(#CC7991);} 
      
      if (ID==7){
        fill(#E94B50);}
      
      if (ID==8){
        fill(#FE9755);} 
      
      if (ID==9){
        fill(#00A8D3);} 
            
      if (ID==10){
        fill(#065BA6);} 
        
      if (ID>10){
        return;}
      
      
  if (looping)  noLoop();
  }
}

void keyPressed() {
  if (keyPressed == true){
    loop();}
}

void myDelay(int ms){
  int time = millis();
  while(millis()-time < ms);
}

Why don’t you use if(i < tuioObjectList.size()) ){code}
i++;

1 Like

it sounded like a very good idea but unfortunately it didn’t solve the problem :pleading_face: … thanks anyway! :kissing_heart:

Did it give any error?

Actually it get worse. The first image do not appear and moreover the TUIO recognition system don’t work either when the draw() loop restart.

Where is the boolean looping set?
Edit, I tested it. It actually works. Didn’t know that.
But within draw if you use if(looping) noLoop(); It will just run one draw() frame isn’t it?

Yeah but I’ve added a keyPressed() condition that restart the loop() when you press your keyboard. It’s the only solution I’ve found to prevent the draw() loop to restart automatically when I hide the ID symbol from the camera.

Just googling before F 1 starts😊.
Likewise chrisir I don’t know tuio.
Did you get it here?

I actually get it here , download the two files highlight below

(reactiVision has to be running behind to use TUIO in processing)

At the moment I just have a tablet. So I can’t download the file. But the impression I have, is that the code first must run until the object’s list size.is reached, and only than you can check the ID’s and load images.

Honestly I don’t know. I’ve difficulties to really understanding how the TUIO librarie works.
However if you figure this out, I’ll stay tune ! :brown_heart:

Well, a compatriot of mine did some tests with this lib.
In the video below he modified the example and created a sketch with a jpg background and two images wich are shown on the screen depending the marker exhibited in the webcam
That was seven years ago so I don’t know if you have to modify for the recent version.
Here is the code:

----------------------------------------------------------------------------------------
/*
    TUIO processing demo - part of the reacTIVision project
    http://reactivision.sourceforge.net/

Modifiied by Miklos em 13/03/2011 
*/

// we need to import the TUIO library
// and declare a TuioProcessing client variable
import TUIO.*;
TuioProcessing tuioClient;

// these are some helper variables which are used
// to create scalable graphical feedback
float cursor_size = 15;
float object_size = 120;
float table_size = 760;
float scale_factor = 1;
PFont font;
PImage bg;
PImage p0;
PImage p1;

void setup()
{
  
  size(800,600);
  bg = loadImage("background_test.gif");
  p0 = loadImage("quad_teste.gif");
  p1 = loadImage("circ_teste.gif");
  
  //size(screen.width,screen.height);
 // size(640,480);
 // noStroke();
 // fill(0);
  
  loop();
  frameRate(30);
  //noLoop();
  
  hint(ENABLE_NATIVE_FONTS);
  font = createFont("Arial", 18);
  scale_factor = height/table_size;
  
  // we create an instance of the TuioProcessing client
  // since we add "this" class as an argument the TuioProcessing class expects
  // an implementation of the TUIO callback methods (see below)
  tuioClient  = new TuioProcessing(this);
}

// within the draw method we retrieve a Vector (List) of TuioObject and TuioCursor (polling)
// from the TuioProcessing client and then loop over both lists to draw the graphical feedback.
void draw()
{
  //background(255);
  background(bg);
  textFont(font,18*scale_factor);
  float obj_size = object_size*scale_factor; 
  float cur_size = cursor_size*scale_factor; 
   
  Vector tuioObjectList = tuioClient.getTuioObjects();
  for (int i=0;isize();i++) {
     TuioObject tobj = (TuioObject)tuioObjectList.elementAt(i);
      String simb = "" + tobj.getSymbolID();
     if( simb.equals("1") ){
     stroke(0);
     fill(0);
     pushMatrix();
     translate(tobj.getScreenX(width),tobj.getScreenY(height));
     rotate(tobj.getAngle());
    // rect(-obj_size/2,-obj_size/2,obj_size,obj_size);
     image(p0,-obj_size/2,-obj_size/2,obj_size,obj_size);
     popMatrix();
     fill(255);
     text(""+tobj.getSymbolID(), tobj.getScreenX(width), tobj.getScreenY(height));
     }
     if( simb.equals("2") ){
     stroke(0);
     fill(0);
     pushMatrix();
     translate(tobj.getScreenX(width),tobj.getScreenY(height));
     rotate(tobj.getAngle());
    // rect(-obj_size/2,-obj_size/2,obj_size,obj_size);
     image(p1,-obj_size/2,-obj_size/2,obj_size,obj_size);
     popMatrix();
     fill(255);
     text(""+tobj.getSymbolID(), tobj.getScreenX(width), tobj.getScreenY(height));
        } 
   }
/*  
   Vector tuioCursorList = tuioClient.getTuioCursors();
   for (int a=0;a
      TuioCursor tcur = (TuioCursor)tuioCursorList.elementAt(a);
      Vector pointList = tcur.getPath();
      
      if (pointList.size()>0) {
        stroke(0,0,255);
        TuioPoint start_point = (TuioPoint)pointList.firstElement();;
        for (int j=0;j
           TuioPoint end_point = (TuioPoint)pointList.elementAt(j);
           line(start_point.getScreenX(width),start_point.getScreenY(height),end_point.getScreenX(width),end_point.getScreenY(height));
           start_point = end_point;
        }
        
        stroke(192,192,192);
        fill(192,192,192);
        ellipse( tcur.getScreenX(width), tcur.getScreenY(height),cur_size,cur_size);
        fill(0);
        text(""+ tcur.getCursorID(),  tcur.getScreenX(width)-5,  tcur.getScreenY(height)+5);
      }
   }*/
   
}

// these callback methods are called whenever a TUIO event occurs

// called when an object is added to the scene
void addTuioObject(TuioObject tobj) {
  println("add object "+tobj.getSymbolID()+" ("+tobj.getSessionID()+") "+tobj.getX()+" "+tobj.getY()+" "+tobj.getAngle());
}

// called when an object is removed from the scene
void removeTuioObject(TuioObject tobj) {
  println("remove object "+tobj.getSymbolID()+" ("+tobj.getSessionID()+")");
}

// called when an object is moved
void updateTuioObject (TuioObject tobj) {
  println("update object "+tobj.getSymbolID()+" ("+tobj.getSessionID()+") "+tobj.getX()+" "+tobj.getY()+" "+tobj.getAngle()
          +" "+tobj.getMotionSpeed()+" "+tobj.getRotationSpeed()+" "+tobj.getMotionAccel()+" "+tobj.getRotationAccel());
}

// called when a cursor is added to the scene
void addTuioCursor(TuioCursor tcur) {
  println("add cursor "+tcur.getCursorID()+" ("+tcur.getSessionID()+ ") " +tcur.getX()+" "+tcur.getY());
}

// called when a cursor is moved
void updateTuioCursor (TuioCursor tcur) {
  println("update cursor "+tcur.getCursorID()+" ("+tcur.getSessionID()+ ") " +tcur.getX()+" "+tcur.getY()
          +" "+tcur.getMotionSpeed()+" "+tcur.getMotionAccel());
}

// called when a cursor is removed from the scene
void removeTuioCursor(TuioCursor tcur) {
  println("remove cursor "+tcur.getCursorID()+" ("+tcur.getSessionID()+")");
}

// called after each message bundle
// representing the end of an image frame
void refresh(TuioTime bundleTime) { 
  redraw();
}

As for what is in your code; are you sure you want a bitwise AND with if (ID>=0 & ID<=2)? Wouldn’t it be logical &&?
And what are you filling?

1 Like

Thank you I didn’t know that the “&” and “&&” has different signification and indeed the logical && would be more suitable for my use.

Regarding the video and the code you presented to me, his use of the library is very different from mine. Indeed he don’t put two images but an image on a background … However it could be a solution to my problem: display my first image as background and then display the second as an image? I have to try it…

Until now I don’t kow what your end goal is. Your code looks weird to me, and I can’t test this lib on my tablet. But then I remembered a great series of videos about Computer Vision by Daniel Shifman There he teaches how to write your own code for blob detections and others video related things. He is the best teacher I know of. Fun, detailed, objective, understandable etc, etc. As you see I am really a fan. Here is the link to the videos.
Today I tested his motion detection code, but I had to adapt it for Android with the Ketai library. Below as you see, the result on my tablet.

1 Like

Although there are cases where && and & would produce diff. decisions, in your particular case there’s no diff. choosing 1 over the other:

if (ID >= 0 & ID <= 2) { has the same effect as if (ID >= 0 && ID <= 2) {.

That is, the short-circuit behavior of && won’t make any diff. in the case above.

1 Like

Could you please elaborate on that a little?
I mean, I thought that logical operators work on boolean expressions and return boolean values , whereas bitwise operators work on binary digits of integer values and return an integer.

In Java, when both operands are of type boolean, the bitwise operators &, | and ^ are overloaded to act as logical operators too.

However in such case both sides are always eagerly evaluated.

While the logical operators && and || are short-circuit evaluated:

1 Like