Storing a one snapshot of value within a draw loop?

Hi I am exploring Ml5js posenet model to get the 2D keypoints. I am using these keypoints to calculate the angle around a joint area , for example shoulder joint. I am looking for a way to store the x and y co .ordinates of associated key points when it full fills a certain condition.

For example in the following pseudo code if the angle range is between 85-95 degrees it should store
the first value of the shoulder co ordinates for example

let shoulderX,shoulderY  // Global variables

draw()
{

 if (angle >= 85  || angle <+ 95)
  {
   shoulderX = poses.keypoints[shoulder].x;
   shoulderY = poses.keypoints[shoulder].y ;

}

}

With such a logic I do get a range of shoulderX , shoulderY values but I am looking to save only a snapshot of the value, that is the first value when the condition is fulfilled. Is there a way to achieve that ?

You can use a boolean variable firstTime set to true before setup ()

Set it to false within {…} of the if

and in the if-clause say && firstTime == false

1 Like

You have the || operator there, which means or, rather than and

 if (angle >= 85  || angle <+ 95)

Be sure to use:

 if (angle >= 85 && angle <= 95)

… and add && firstTime == false to the conditional expression if you are following @Chrisir’s pattern.

1 Like

Try the following p5.js code as a possible pattern:

let shoulderX, shoulderY, angle, firstTime;
function setup() {
  createCanvas(377, 144);
  firstTime = false; // shoulder joint event has not yet occurred
  background(244, 244, 216);
  fill(255, 0, 0);
  noStroke();
  // draw the red area that triggers the event
  rect(3 * width / 7, 0, width / 7, height); 
}
function draw() {
  // check for shoulder joint angle event
  if (red(get(mouseX, mouseY)) == 255 && !firstTime) {
    // mouse entered the red area --> shoulder joint angle within range
    // simulate the angle within the range based on mouseY
    angle = map(mouseY, 0, height, 85, 95); 
    if (angle >= 85 && angle <= 95 && !firstTime) {
      // get snapshot
      snapshot();
    }
  }
}

function snapshot() {
  // get and display a snapshot of variables
  firstTime = true;
  shoulderX = mouseX;
  shoulderY = mouseY;
  fill(0, 0, 127);
  textSize(20);
  text("(" + shoulderX + ", " + shoulderY + ") " + Math.round(angle) + "°", 12, height / 2);
  noLoop();
}

Move the mouse into the red area to simulate occurrence of a shoulder joint angle event.

Image capture:

EDITED 2x on November 14, 2021 to revise the code.

Thanks for the tips. I might be wrong in approaching the problem here. What i wanted initially was that when the angle was between a certain angle , i should get a snapshot of the keypoints. I tried method mentioned above but , i get the values undefined. Also , I am not using noLoop() because , I want to the rendering to continue after the snap shot. So I have defined the code as follows. I tried also with other keypoints just to double check if perhaps due to invisibility the joints are not detected .

The idea of snapshot is that , iget initial co-ordinates or vertex through which I can continue drawing independently. I used the even mouseePressed() to get such vertexes but for a hands free approach i thought of taking the angle. Any ways of overcoming this problem . Adding some snippets. I am also console logging the angle so as to check if the angle measured is correct.

let firstTime,angle,rightshoulderX,rightshoulderY
async function setup() {
  createCanvas(640, 480);
  angleMode(DEGREES);
  await init();
video = createCapture(VIDEO, videoReady);
video.hide();
firstTime = false; // shoulder joint event has not yet occurred  
}

for (let i = 0; i < poses[0].keypoints.length; i++) {
          const { x, y, score } = poses[0].keypoints[i];
          // console.log(kp);
          if (score > ScoreThreshold) {
            
            
              /*Right Side  */  
            v1Left = createVector(poses[0].keypoints[8].x -poses[0].keypoints[6].x, poses[0].keypoints[8].y -poses[0].keypoints[6].y);
            
         
            v2Left = createVector(poses[0].keypoints[4].x -poses[0].keypoints[6].x, poses[0].keypoints[4].y -poses[0].keypoints[6].y);
            
            
            
            
            
            // Angle calculations
         
            angle = (Math.round(v1Left.angleBetween(v2Left)));
            console.log(angle)
            if (angle >=120 && angle <= 180  && !firstTime) {
              // get snapshot
              snapshot();
              console.log(angle);
              line(0, 0, 400, 400);
              
              
            }       
            
          }
        }
      }
    }
   console.log("snapshot");
  console.log(rightShoulderX);
console.log(angle);

 
 
}


function snapshot() {
  // get and display a snapshot of variables
  firstTime = true;
  rightshoulderX = poses[0].keypoints[4].x;  //save the value and continue 
  rightshoulderY = poses[0].keypoints[4].y; 
}

I didn’t encounter that issue, but it is possible that it may occur on some systems because mouseX and mouseY are checked several times during a draw() cycle, and things could get out of sync as the mouse continues to move. The solution could be to create two global variables, x, and y, and assign the values of mouseX and mouseY to them at the beginning of each draw() cycle. Then we can use x and y instead of checking mouseX and mouseY again during the same cycle.

In any case, it appears that you have moved on to a different solution.

Have you gotten it working as you had hoped?

Hello actually not , i could not manage it to work . Kind of strange . I still used your logic but instead of MouseX and MouseY , I automatically wanted to get the end co/ordinates. So instead of the click ( mouse X and Mouse Y) in the sketch sample, I was hoping it would triigger the same behaiviour when the angle is between a certain range. In theory it should right ??

You can use any condition you choose to trigger a snapshot. Just make sure that when that condition occurs, you save all the data that you need into variables immediately for eventual output, especially if the numbers are changing continually.

I cannot run your code, partly because it throws the following error on line 42:

Uncaught SyntaxError: Unexpected token '}' 

There were too many closing curly braces when compared to the fewer number of code blocks that were still open.

@basicvisual, below is a revised model for the sketch. The various tasks have been delegated to functions for improved organization. Most of it is arbitrary, and you can modify it as appropriate. See the comments within the code.

// globals
let first_occ;
let joint_ang;
let joint_data;
let data_at_critical_angle;

function setup() {
  // setup
  createCanvas(400, 100);
  first_occ = false;
  joint_ang = null;
  joint_data = [];
  data_at_critical_angle = [];
  textSize(24);
  textAlign(CENTER, CENTER);
}

function draw() {
  // draw cycle
  joint_ang = get_joint_angle();
  joint_data.push(joint_ang);
  if (is_angle_critical(joint_ang) && !first_occ) {
    data_at_critical_angle.push(get_time());
    data_at_critical_angle.push(joint_ang);
    first_occ = true;
    fill(255, 0, 0);
    background(255, 255, 231);
    text(
      "Time: " + get_time() + " Angle: " + Math.round(joint_ang) + "°",
      width / 2,
      height / 2
    );
  }

  if (is_run_complete()) {
    dump_data_and_stop();
  }
}

function get_joint_angle() {
  // number: proxy for joint angle
  return random(200);
}

function is_run_complete() {
  // boolean: proxy for answer to question: is the run complete?
  return frameCount == 256;
}

function is_angle_critical(ang) {
  // boolean: is the angle critcal?
  return ang >= 85 && ang <= 95;
}

function dump_data() {
  // dump all the data
  for (let i = 0; i < joint_data.length; i++) {
    print(joint_data[i]);
  }
  print(
    "Critical data: " +
      data_at_critical_angle[0] +
      " " +
      data_at_critical_angle[1]
  );
}

function dump_data_and_stop() {
  // dump data to console and stop
  dump_data();
  noLoop();
}

function get_time() {
  // number: proxy for gettimg the time since start of run
  return frameCount;
}

Image:

1 Like

@javagar
Thanks I will try it and update you , on my observations .

1 Like

You are welcome. If additional suggestions are needed, we will be happy to provide them.

1 Like

@javagar thank you. I think your logic worked really well. I had made a mistake in the function and i did not understood it correctly. I have one question though.some what related to drawing of an arc at the joints. since i have only a joint angle I dont have a start angle and stop angle

arc(x, y, w, h, start, stop, [mode], [detail])

Is it possible to draw dynamic arc from the angle calculated above ?

  v1Left = createVector(poses[0].keypoints[8].x -poses[0].keypoints[6].x, poses[0].keypoints[8].y -poses[0].keypoints[6].y);
            
         
            v2Left = createVector(poses[0].keypoints[4].x -poses[0].keypoints[6].x, poses[0].keypoints[4].y -poses[0].keypoints[6].y);
            // Angle calculations
         
            angle = (Math.round(v1Left.angleBetween(v2Left)));

Do you wish to draw an arc that connects smoothly to two lines, either drawn or implied, that correspond in their orientations to the orientations of the two vectors?

EDIT (December 11, 2021):

Since the issue of drawing an arc differs from the topic that initiated this discussion, it should be addressed in a new discussion with a title directly related to it. That would get the attention of users who feel that they can offer effective advice for this issue.