Related
I am working with a pose estimator that is giving me (x, y, z) for each joint. I am attempting to calculate angles based on these and running into some issues.
const find_angle = (Ax,Ay,Az,Bx,By,Bz,Cx,Cy,Cz) =>
{
var AB = Math.sqrt(Math.pow(Bx-Ax,2) + Math.pow(By-Ay,2) + Math.pow(Bz-Az,2));
var CB = Math.sqrt(Math.pow(Bx-Cx,2) + Math.pow(By-Cy,2) + Math.pow(Bz-Cz,2));
var AC = Math.sqrt(Math.pow(Cx-Ax,2) + Math.pow(Cy-Ay,2) + Math.pow(Cz-Az,2));
const radians = Math.acos((CB*CB+AB*AB-AC*AC) / (2*CB*AB));
const angle = (Math.abs(radians*180.0/Math.PI))
console.log(angle)
}
// Knee
find_angle(101, 166, 409, 107, 209, 790, 115, 248, 9564)
// Ankle
find_angle(100, 259, 1549, 97, 299, 9471, 95, 315, 1575)
Ouput:
The Knee output looks correct to me but Ankle does not. I was expecting an angle in the range of 70-90. I'm wondering if this function is too simple for what I am trying to do or what improvements could be made to make it consistent across all joints. User is facing the camera while pose is being estimated.
I am trying to find the best way to generate an array that has the following output:
[135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 275, 276, 277 , 278, 279, 280, 281, 282, 283, 284, 285, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 675, 676, 677, 678, 679, 700, 701, 702, 703, 704, 705 ...
As you can see it has a set of limits from 140 - 280 - 420 - 560 - 700 ( adds 148 to each value)
and then there's an interval with minus 5 and plus 5 for each value.
I already tried this approach
scrollFrom = Array.from(Array(bytesIndexTo).keys()).map(i => 140 + i * 140);
That returns me:
[140, 280, 420, 560, 700, ...
However I also need the plus and minus 5 values intervals...
I also noticed it uses to much resources.
const prev = [
[135,136,137,138,139],
[275,276,277,278,279],
];
const after = [
[141,142,143,144,145],
[281,282,283,284,285],
];
for (let i = 0; i < scrollFrom.length; i++) {
scrollFrom.push( scrollFrom[i] );
}
The purpose of this array is to have a set of values that will help me to identify a certain scroll position in order to execute a function, the addition of this intervals will help me to figure the scroll position even if the user scrolls fast.
Maybe I could load the values inside a .json and load them ?
What do you think ? thanks in advance
Once you create an array of central values (eg [140, 280, 420, 560, 700]), you can use flatMap to iterate over each item and construct another array of the 5 values below and above it:
const bytesIndexTo = 4;
const result = Array.from(
{ length: bytesIndexTo },
(_, i) => (i + 1) * 140
)
.flatMap(num => Array.from(
{ length: 11 },
(_, j) => num - 5 + j
));
console.log(result);
So, if you all you really want to do is to be able to test if a number is within 5 of a sentinel multiple, then I don't think you really want to be generating a giant array and using .includes(). That would be slow. If you were going to pre-generate values, you should use a Set and then use .has() which should be a lot faster than .includes() for a large set of data.
But, it seems to be that you can just calculate a lot faster without doing any pre-generation at all.
In the code below, we divide by the multiple (140) and then look at the remainder. If the remainder is <=5 or >= 135, then it's within 5 of the multiple, otherwise not. It's really that simple. Since it appears you don't want the numbers 0-5 (around the zero multiple) to be counted as true, we add a special case for those.
// tests to see if a value is within 5 of a multiple of 140
const multiple = 140;
const over = 5;
const below = multiple - over;
function testValue(val) {
if (val < below) return false;
const delta = val % multiple; // divide by multiple, get remainder
return (delta <= over || delta >= below); // see if remainder in right range
}
// run some tests on numbers at edges of the interval ranges
[
0, 1,
134, 135, 140, 144, 145, 146, // around 140
274, 275, 280, 284, 285, 286, // around 280
414, 415, 420, 424, 425, 426, // around 420
554, 555, 560, 564, 565, 566 // around 560
].forEach(num => {
console.log(`${num}: ${testValue(num)}`);
});
I'm trying to find the technique of Normalising (not sure if that is the right word) a range of numbers.
Say I have an array:
[0, 1, 2, 3, 4, 70, 80, 900]
I want to flatten or average out the range curve, so it's more like:
[10, 11, 12, 13, 14, 50, 100, 300]. // not a real calculation
So increasing the smaller numbers in relation to reducing the larger numbers.
What is this technique called? Normalised scale? I wish to implement this in some Javascript.
UPDATE: Here is hopefully a better description of what I'm trying to do:
I have an original array of numbers:
[0, 10, 15, 50, 70, 100]
When processed through a function averageOutAllNumbers(array, slider) will produce and array that when slider is set to 100% looks like:
[0, 20, 40, 60, 80, 100] // the curve has been flattened
when slider is set to 0%, it will return the original array. If slider is set to 50%, the returned array will look something like:
[0, 12, 19, 52, 88, 100] // the curve is less steep [do not take these number literally, I'm guess what the output would be based on the slider].
the array.max() will alway be 100.
Thanks for the comments so far, they did point me closer to the solution.
No thanks to the trolls who down-voted; if you can't fix it no one can—right!
When I updated my question I realised that "increasing the smaller numbers in relation to reducing the larger numbers" would eventually lead to an evenly distributed set of numbers, e.g. [20, 20, 20, 20, 20]. However I did actually want something like I stated in the question: [0, 20, 40, 60, 80, 100] // the curve has been flattened. I did some more searching for things like:
Evenly space an array of oddly spaced numbers
Making a list of evenly spaced numbers in a certain range
Return evenly spaced numbers over a specified interval
Find what percent X is between two numbers
Amongst the list of search result I saw the answer to my original question: "What is this technique called?" Linear Interpolation
Based on that I was able to create the following:
var orig = [3, 11, 54, 72, 100];
function lerp(n, x0, x1) {
// returns a position: x that is n percent between y0 and y1
// As numbers in array are x only, y values are fixed to 0(start) - 1(end)
const y0 = 0;
const y1 = 1;
const x = ((y1 - n)*x0 + (n - y0)*x1) / (y1 - y0);
return x;
}
var flattenedEven = orig.map((value, index, arr) => {
return lerp(1, value, (Math.max(...arr)/arr.length) * (index + 1));
});
//=> [20, 40, 60, 80, 100]
var flattenedCurve = orig.map((value, index, arr) => {
return lerp(.7, value, (Math.max(...arr)/arr.length) * (index + 1));
});
//=> [14.9, 31.3, 58.2, 77.6, 100]
Im working my way through the Khanacademy site and a a bit confused on how to make randomly sized(within certain parameters), and colored fish after mouseClick. I cant even get mouseClick working.
background(89, 216, 255);
var mouseClicked = function(drawFish){
};
^^^^^^^^^^^^^^^ What am I missing here? ^^^^^^^^^^
var drawFish = function(centerX, centerY, bodyLength, bodyHeight, bodyColor, tailWidth,
tailHeight, eyeColor,tailColor, eyeWidth, eyeHeight){
noStroke();
fill(bodyColor);
// body
ellipse(centerX, centerY, bodyLength, bodyHeight);
// tail
fill(tailColor);
triangle(centerX-bodyLength/2, centerY,
centerX-bodyLength/2-tailWidth, centerY-tailHeight,
centerX-bodyLength/2-tailWidth, centerY+tailHeight);
// eye
fill(eyeColor);
ellipse(centerX+bodyLength/3, centerY, eyeWidth, eyeHeight);
};
drawFish(296, 281, -57,52, color(245, 227, 30),-15, 60,color(13, 12, 12),color(66, 58, 58),4,4); // yellowFish
drawFish(290, 80, 180, 140, color(255, 0, 0), 57, 45,color(46, 66, 194), color(255, 204, 0),32,8); // redFish
drawFish(146,233, 218, 141, color(62, 110, 67), 30, 10, color(245, 240, 245), color(0, 51, 255),12,48); // greenFish
drawFish(233, 370, 322, 36, color(133, 34, 199), 61,15, color(255, 0, 0), color(34, 255, 0),67,20); // purpFish
Any other pointers or recommendations would be greatly appreciated.
Thanks guys!
Cool fishes! I'm learning Processing too. I ran your code and came up with this function for having random fishes appear when you click.
void mouseReleased() {
var c1 = color(random(0,255),random(0,255),random(0,255),random(0,255))
var c2 = color(random(0,255),random(0,255),random(0,255),random(0,255))
var c3 = color(random(0,255),random(0,255),random(0,255),random(0,255))
var s1 = random(10,100)
var s2 = random(10,100)
var s3 = random(10,100)
var s4 = random(10,100)
var s5 = random(5,s1)
var s6 = random(5,s2)
drawFish(mouseX, mouseY, s1, s2, c2, s3,s4, c2, c3,s5,s6); //randFish
}
To make an animation, I think you will want to use the draw() function, use variables for the x,y locations and redraw the background each time. This example has the red fish follow the mouse around.
void draw(){
background(89, 216, 255);
drawFish(mouseX, mouseY, 180, 140, color(255, 0, 0), 57, 45,color(46, 66, 194), color(255, 204, 0),32,8); // redFish
}
I hope your aquarium comes out really great!
stage.addChild(background);
stage.addChild(container);
createjs.Ticker.addEventListener("tick", handleTick);
function handleTick(event) {
background.x-=1;
container.x-=2;
stage.update();
}
background and container contains large images more than the width of canvas so that it gives a parallax effect for the game.
If you want to be able to move them with w a s d or arrow keys or whatever you want, there's this file I like to use. (I recommend saving it in another document)
var Key = {
_pressed: {},
preventedDefaults:[32, 37, 38, 39, 40, 16, 90, 81, 68, 83, 87, 65],
Z: 90,
Q: 81,
D: 68,
S: 83,
W: 87,
A: 65,
SPACE: 32,
LEFT: 37,
UP : 38,
RIGHT: 39,
DOWN: 40,
SHIFT: 16,
isDown: function(keyCode){
return this._pressed[keyCode];
},
onKeyDown: function(e){
this._pressed[e.keyCode] = true;
if(this.preventedDefaults.indexOf(e.keyCode) > -1){
e.preventDefault();
}
},
onKeyUp: function(e){
delete this._pressed[e.keyCode];
}
}
window.addEventListener('keyup', function(e){Key.onKeyUp(e);}, false);
window.addEventListener('keydown', function(e){Key.onKeyDown(e);}, false);
So as you can see the numbers in the array preventedDefaults are the numbers of the keys on your keyboard which you can look up on google if you need other key codes.
To use it, you do it with a simple if statement like so:
if(Key.isDown(Key.DOWN) || Key.isDown(Key.S)){
move down or whatever
};
(make an if statement for each direction you want to be able to go)
As you can see you can use multiple keys for the same movement , so you can use the arrow keys and w a s d for example.
I hope this was clear enough. If not, ask away.