I need to develop an application where a user (physiotherapist) will perform a movement in front of the Kinect, I'll write the data movement in the database and then the patient will try to imitate this motion. The system will calculate the similarity between the movement recorded and executed.
My first idea is, during recording (each 5 second, by example), to store the position (x, y, z) of the points and then compare them in the execution time(by patient).
I know that this approach is too simple, because I imagine that in people of different sizes the skeleton is recognized differently, so the comparison is not reliable.
My question is about the best way to compare a saved motion with a movement executed (on the fly).
I have done this, where a doctors frame is projected onto the patients frame, but with the whole skeleton this doesn't work so well because of different bone heights :/. The code can be found here. It is in beta 2 code, the more current version can be found here, although it is not currently working perfectly
As for comparing, do something like this
for (int i = 0; i < patientList.Count; i++)
{
int diff = (int)Math.Abs(patientList[i] - doctorList[i]);
if (diff < 100) //or whatever number you want
{
Debug.WriteLine("Good Job");
}
}
I have abandoned the idea of a whole figure because of the bone heights mentioned by Fixus, so my current program looks some thing like:
EDIT
This is the concept of camparing two movements with kinect and calculate a similarity between the two movements I explain in depth.
Suppose I have the following 2 points, point A (0, 0, 0) and point B (1, 1, 1). Now I want to find the difference from point A to B, so I would subtract all of the X, Y, and Z numbers, so the difference is 1 X 1 Y 1 Z. That is the simple stuff. Now to implement it. The code I have written above, I would implement like this.
//get patient hand coordinates
double patienthandX = Canvas.GetLeft(patienthand);
double patienthandY = Canvas.GetTop(patienthand);
//get doctor hand coordinates
double doctorhandX = Canvas.GetLeft(doctorhand);
double doctorhandY = Canvas.GetTop(doctorhand);
//compare difference for each x and y
//take Absolute value so that it is positive
double diffhandX = Math.Abs(patienthandX - doctorhandX);
double diffhandY = Math.Abs(patienthandY - doctorhandY);
Now here comes another issue. The doctor coordinates are always the same, but what if the patient isn't standing where the doctor coordinates were recorded? Now we implement more simple math. Take this simple example. suppose I want point A(8, 2) to move to point B(4, 12). You multiply the x and y's of A to get to B. So I would multiply the X by .5, and the Y by 6. So for Kinect, I would put a element on the patients hip, then compare this to the doctors hip. Then multiply all of the doctor joints by that number to achieve the doctor joints on top of the patients (more or less). For example
double whatToMultiplyX = (double) doctorhipX / patienthipX;
double whatToMultiplyY = (double) doctorhipY / patienthipY;
This is all pretty simple, but bringing it together is the harder part. So far we, 1) Scale the doctor frames on top of the patient frames, 2) Calculate the difference. 3) Compare the difference throughout the entire rep. and 4) Reset for the next rep. This seems simple but it is not. To calculate the entire difference for the rep, do something like this:
//get patient hand coordinates
double patienthandX = Canvas.GetLeft(patienthand);
double patienthandY = Canvas.GetTop(patienthand);
//get doctor hand coordinates
double doctorhandX = Canvas.GetLeft(doctorhand);
double doctorhandY = Canvas.GetTop(doctorhand);
//compare difference for each x and y
//take Absolute value so that it is positive
double diffhandX = Math.Abs(patienthandX - doctorhandX);
double diffhandY = Math.Abs(patienthandY - doctrorhandY);
//+= so that it keeps adding to it.
totaldiffhandX += diffhandX;
totaldiffhandY += diffhandY;
Now we can compare, and say:
if (totaldiffhandX < 1000 && totaldiffhandY < 1000) //keep numbers pretty high since it is an entire rep
{
//reset difference
totaldiffhandX = 0;
totaldiffhandY = 0;
//tell the patient good job
Debug.WriteLine("Good Job");
}
This is pretty easy, but keep in mind you must do this for every single joint's x and y. Otherwise it will not work. Hope this Helps.
First of all remember that people are diffrent. Every person has diffrent height, width, weight, diffrent bones length etc etc
You`re code probably will never work cause of this.
Secondly you need to think more geometrically. Don`t think about points only, think with vectors, their directions. Each movement is movent of some vectors in some directions.
Then the proportion. You need to configure application for each user.
You have some pattern. The patter is your physiotherapist. You need to remember not only his movements but also his body. Arm length, leg length, distances etc. Each user that will be using your app also need to me mesured. Having all this data you can compare movement by scaling sizes and comparing directions of movent
Of course remember that there are some very simple moves like for example. They can be recognized by simple mathematic by checking actual position of the hand and checking direction of the movement. You need for this 3 control points and you`re at home :)
Gesture recognizing isn`t a simple thing
Related
Does pinescript have any built in functions to check if a line has been crossed in the past? The line would be repainting as I am looking to check if a linear regression channel's deviation lines have been crossed previously or not, but more specifically the number of times crossed to attempt to validate it's strength.
This code will work, although the code execution time is very slow:
priceFound = 0
countAbove = 0
countBelow = 0
length = 100
slope = (y2-y1)/(x2-x1) //Calculates slope of using line coordinates
for i = 0 to length
priceFound := slope*((_y1/slope) + bar_index[i] - _x1) //Calculates price at y-coord
countAbove := high[i]>priceFound ? countAbove+1 : countAbove //Checks if above
countBelow := low[i]<priceFound ? countBelow+1 : countBelow //Checks if below
What your code is doing is checking on every single newly created bar 100 bars back if price was above/below your coordinate. Yes it's not really efficient, though I don't think simple arithmetic operations would challenge pine script. (Of course I can be wrong)
Instead you could try another direction with ta.crossunder() / ta.crossover() or ta.cross(). With these you wouldn't need slope calculation or whatsoever because you can check your plot value and the high/low real time (or rather on bar close). Of course this way you would only find out if your line did not hold and you would build up your strength tracking the opposite way.
Still, I think it's worth considering as a solution to your problem.
So, I am programming a simple Mandelbrot renderer.
My inner loop (which is executed up to ~100,000,000 times each time I draw on screen) looks like this:
Complex position = {re,im};
Complex z = {0.0, 0.0};
uint32_t it = 0;
for (; it < maxIterations; it++)
{
//Square z
double old_re = z.re;
z.re = z.re*z.re - z.im*z.im;
z.im = 2*old_re*z.im;
//Add c
z.re = z.re+position.re;
z.im = z.im+position.im;
//Exit condition (mod(z) > 5)
if (sqrt(z.re*z.re + z.im*z.im) > 5.0f)
break;
}
//Color in the pixel according to value of 'it'
Just some very simple calculations. This takes between 0.5 and a couple of seconds, depending on the zoom and so on, but i need it to be much faster, to enable (almost) smooth scrolling.
My question is: What is my best bet to achieve the maximum possible calculation speed?
OpenCl to use the GPU? Coding it in assembly? Dividing the image into small pieces and dispatch the calculation of each piece on another thread? A combination of those?
Any help is appreciated!
I have written a Mandelbrot set renderer several times... and here are the things that you should keep in mind...
The things that take the longest are the ones that never escape and take all the iterations.
a. so you can make a region in the middle out of a few rectangles and check that first.
any starting point with a real and imaginary part between -1 and 1 will never escape.
you can cache points (20, or 30) in a rolling buffer and if you ever see a point in the buffer that you just calculated means that you have a cycle and it will never escape.
You can use a more general logic that doesn't require a square root... in that if any part is less than -2 or more than 2 it will race out of control and can be considered escaped.
But you can also break this up because each point is its own thing, so you can make a separate thread or gcd dispatch or whatever for each row or quadrant... it is a very easy problem to divide up and run in parallel.
In addition to the comments by #Grady Player you could start just by optimising your code
//Add c
z.re += position.re;
z.im += position.im;
//Exit condition (mod(z) > 5)
if (z.re*z.re + z.im*z.im > 25.0f)
break;
The compiler may optimise the first, but the second will certainly help.
Why are you coding your own complex rather than using complex.h
For a program I'm writing, I need to be able to trace a virtual line (that is not straight) that an object must travel along. I was thinking to use NSBezierPath to draw the line, but I cannot find a way to get any point along the line, which I must do so I can move the object along it.
Can anyone suggest a way to find a point along an NSBezierPath? If thats not possible, can anyone suggest a method to do the above?
EDIT: The below code is still accurate, but there are much faster ways to calculate it. See Introduction to Fast Bezier and Even Faster Bezier.
There are two ways to approach this. If you just need to move something along the line, use a CAKeyframeAnimation. This is pretty straightforward and you never need to calculate the points.
If on the other hand you actually need to know the point for some reason, you have to calculate the Bézier yourself. For an example, you can pull the sample code for Chapter 18 from iOS 5 Programming Pushing the Limits. (It is written for iOS, but it applies equally to Mac.) Look in CurvyTextView.m.
Given control points P0_ through P3_, and an offset between 0 and 1 (see below), pointForOffset: will give you the point along the path:
static double Bezier(double t, double P0, double P1, double P2,
double P3) {
return
pow(1-t, 3) * P0
+ 3 * pow(1-t, 2) * t * P1
+ 3 * (1-t) * pow(t, 2) * P2
+ pow(t, 3) * P3;
}
- (CGPoint)pointForOffset:(double)t {
double x = Bezier(t, P0_.x, P1_.x, P2_.x, P3_.x);
double y = Bezier(t, P0_.y, P1_.y, P2_.y, P3_.y);
return CGPointMake(x, y);
}
NOTE: This code violates one of my cardinal rules of always using accessors rather than accessing ivars directly. It's because in it's called many thousands of times, and eliminating the method call has a significant performance impact.
"Offset" is not a trivial thing to work out. It does not proceed linearly along the curve. If you need evenly spaced points along the curve, you'll need to calculate the correct offset for each point. This is done with this routine:
// Simplistic routine to find the offset along Bezier that is
// aDistance away from aPoint. anOffset is the offset used to
// generate aPoint, and saves us the trouble of recalculating it
// This routine just walks forward until it finds a point at least
// aDistance away. Good optimizations here would reduce the number
// of guesses, but this is tricky since if we go too far out, the
// curve might loop back on leading to incorrect results. Tuning
// kStep is good start.
- (double)offsetAtDistance:(double)aDistance
fromPoint:(CGPoint)aPoint
offset:(double)anOffset {
const double kStep = 0.001; // 0.0001 - 0.001 work well
double newDistance = 0;
double newOffset = anOffset + kStep;
while (newDistance <= aDistance && newOffset < 1.0) {
newOffset += kStep;
newDistance = Distance(aPoint,
[self pointForOffset:newOffset]);
}
return newOffset;
}
I leave Distance() as an exercise for the reader, but it's in the example code of course.
The referenced code also provides BezierPrime() and angleForOffset: if you need those. Chapter 18 of iOS:PTL covers this in more detail as part of a discussion on how to draw text along an arbitrary path.
How could I, having a path defined by several points that are not in a uniform distance from each other, redefine along the same path the same number of points but with a uniform distance. I'm trying to do this in Objective-C with NSArrays of CGPoints but so far I haven't had any luck with this.
Thank you for any help.
EDIT
I was wondering if it would help to reduce the number of points, like when detecting if 3 points are collinear we could remove the middle one, but I'm not sure that would help.
EDIT
Illustrating:
Reds are the original points, blues the post processed points:
The new path defined by the blue dots does not correspond to the original one.
I don't think you can do what you state that you want to do. But that could be a misunderstanding on my part. For example, I have understood from your comment that the path is straight between successive points, not curved.
Take, for example, a simple path of 3 points (0,1,2) and 2 line segments (0-1,1-2) of different lengths. Leave points 0 and 2 where they are and introduce a new point 1' which is equidistant from points 0 and 2. If point 1' is on one of the line segments 0-1, 1-2, then one of the line segments 0-1', 1'-2 is not coincident with 0-1, 1-2. (Easier to draw this, which I suggest you do.) If point 1' is not on either of the original line segments then the entire path is new, apart from its endpoints.
So, what relationship between the new path and the old path do you want ?
EDIT: more of an extended comment really, like my 'answer' but the comment box is too small.
I'm still not clear how you want to define the new path and what relationship it has to the old path. First you wanted to keep the same number of points, but in your edit you say that this is not necessary. You agree that replacing points by new points will shift the path. Do you want, perhaps, a new path from point 0 to point N-1, defined by N points uniformly spaced on a path which minimises the area between the old and new paths when drawn on the Cartesian plane ?
Or, perhaps you could first define a polynomial (or spline or other simple curve) path through the original points, then move the points to and fro along the curve until they are uniformly spaced ?
I think the problem is simple and easily solvable actually :)
The basic idea is:
First check if the distance between your current point (P) and the end point of the line segment you are on is >= the distance between P and the next point (Q).
If it is, great, we use some simple trigonometry to figure it out.
Else, we move to the adjacent line segment (in your ordering) and deduct the distance between P and the endpoint of the line segment you are on and continue the process.
Pseudocode:
Defined previously
struct LineSegment
{
Point start,end;
int ID;
double len; // len = EuclideanDistance(start,end);
LineSegment *next_segment;
double theta; // theta = atan2(slope_of_line_segment);
}
Function [LineSegment nextseg] = FindNextLineSegment(LineSegment lineseg)
Input: LineSegment object of the current line segment
Output: LineSegment object of the adjacent line segment in your ordering.
nextseg.ID = -1 if there are no more segments
Function: Find the next point along your path
Function [Point Q, LineSegment Z] = FindNextPt(Point P, LineSegment lineseg, int dist):
Input: The current point P, the distance between this point and the next, and the LineSegment of the line segment which contains P.
Output: The next point Q, and the line segment it is on
Procedure:
distToEndpt = EuclideanDistance(P,lineseg->end);
if( distToEndpt >= d )
{
Point Q(lineseg->start.x + dist*cos(lineseg.theta), lineseg->start.y + dist*sin(lineseg.theta));
Z = lineseg;
}
else
{
nextseg = lineseg->next_segment;
if( nextseg.ID !=-1 )
{
[Q, Z] = FindNextPt(nextseg->start,nextseg->ID,dist-distToEndpt);
}
else
{
return [P,lineseg];
}
}
return [Q,Z]
Entry point
Function main()
Output: vector of points
Procedure:
vector<LineSegment> line_segments;
// Define it somehow giving it all the properties
// ....
vector<Point> equidistant_points;
const int d = DIST;
[Q Z] = FindNextPoint(line_segments[0].start,line_segments[0],DIST);
while( Z.ID != -1 )
{
equidistant_points.push_back(Q);
[Q Z] = FindNextPt(Q,Z,d);
}
My sense is that this is a very hard problem.
It basically amounts to a constrained optimization problem. The objective function measures how close the new line is from the old one. The constraints enforce that the new points are the same distance apart.
Finding a good objective function is the tricky bit, since it must be differentiable, and we don't know ahead of time on which segments each new point will lie: for instance, it's possible for two new points to lie on an extra-long old segment, and no new points lying on some extra-short old segment. If you somehow know a priori on which segments the new points will lie, you can sum the distances between points and their target segments and use that as your objective function (note that this distance function is nontrivial, since the segments are finite: it is composed of three pieces and its level-sets are "pill-shaped.")
Or you might forget about requiring the new points to lie on old segments, and just look for a new polyline that's "close" to the old one. For instance, you might try to write down an L2-like metric between polylines, and use that as your objective function. I don't expect this metric to be pleasant to write down, or differentiate.
I think a perturbative approach will work for this one.
I assume:
we know how to slide a point along the path and recalculate the distances (pretty trivial), and
the end points must remain fixed (otherwise the whole problem becomes trivial).
just iterate over the remaining (n-2) points: if point k is closer to point (k-1) than to point (k+1), move it a little forward along the path. Likewise if it's closer to point (k+1), move a little back along the path.
It's probably best to start with large step sizes (for speed) then make them smaller (for precision). Even if the points pass each other, I think this approach will sort them back into order.
This will use quite a bit of vector math but is quite simple really.
First you will need to find the total distance of the path. Depending on how the points of the path are stored is how you will do it. Here is a basic example on a 2 Dimensional Path in Pseudo-code.
// This would generally be done with vectors, however I'm not sure
// if you would like to make your own class for them as I do so I will use arrays.
// The collection of points
int Points[4][2] = { {0,0}, {1,2}, {5,4}, {6,5} };
int Points2 = Points;
// goes to 3 because there are 4 points
for(int i=0; i<3; i++) {
x = Points[i+1][0] - Points[i][0];
y = Points[i+1][1] - Points[i][1];
d += sqrt(( x * x ) + ( y * y ));
}
// divide distance by number of points to get uniform distance
dist = d/4;
// now that you have the new distance you must find the points
// on your path that are that far from your current point
// same deal here... goes to 3 because there are 4 points
for(int i=0; i<3; i++) {
// slope
m = ( Points[i+1][1] - Points[i][1] ) / ( Points[i+1][0] - Points[i][0] );
// y intercept
b = -(M * Points[i][0]) + Points[i][1];
// processor heavy which makes this problem difficult
// if some one knows a better way please say something
// check every degree grabbing the points till one matches
// if it doesn't then check next segment.
for(float j=0; j<360; j += 0.1) {
x = dist * sin(j);
y = sqrt((dist * dist) - ( x * x ));
if (y - (M * x + C)) {
// then the point is on the line so set it
Points2[i+1][0] = x;
Points2[i+1][1] = y;
}
}
}
The last step is what makes it unreasonable but this should work for you.
There may be a small math error somewhere I double checked this several times but there could be something I missed. So if anyone notices something please inform me and I will edit it.
Hope this helps,
Gale
I am currently busy on writing a small ball physics engine for my programming course in Win32 API and c++. I have finished the GDI backbuffer renderer and the whole GUI (couple of more things to adjust) but i am very near to completion. The only big obstacles that last are ball to ball collision (but i can fix this on my own) but the biggest problem of them all is the bouncing of the balls. What happens is that i throw a ball and it really falls, but once it bounces it will bounce higher than the point were i released it??? the funny thing is, it only happens if below a certain height. This part is the physics code:
(If you need any more code or explanation, please ask, but i would greatly appreciate it if you guys could have a look at my code.)
#void RunPhysics(OPTIONS &o, vector<BALL*> &b)
{
UINT simspeed = o.iSimSpeed;
DOUBLE DT; //Delta T
BOOL bounce; //for playing sound
DT= 1/o.REFRESH;
for(UINT i=0; i<b.size(); i++)
{
for(UINT k=0; k<simspeed; k++)
{
bounce=false;
//handle the X bounce
if( b.at(i)->rBall.left <= 0 && b.at(i)->dVelocityX < 0 ) //ball bounces against the left wall
{
b.at(i)->dVelocityX = b.at(i)->dVelocityX * -1 * b.at(i)->dBounceCof;
bounce=true;
}
else if( b.at(i)->rBall.right >= SCREEN_WIDTH && b.at(i)->dVelocityX > 0) //ball bounces against the right wall
{
b.at(i)->dVelocityX = b.at(i)->dVelocityX * -1 * b.at(i)->dBounceCof;
bounce=true;
}
//handle the Y bounce
if( b.at(i)->rBall.bottom >= SCREEN_HEIGHT && b.at(i)->dVelocityY > 0 ) //ball bounces against the left wall
{
//damping of the ball
if(b.at(i)->dVelocityY < 2+o.dGravity/o.REFRESH)
{
b.at(i)->dVelocityY = 0;
}
//decrease the Velocity of the ball according to the bouncecof
b.at(i)->dVelocityY = b.at(i)->dVelocityY * -1*b.at(i)->dBounceCof;
b.at(i)->dVelocityX = b.at(i)->dVelocityX * b.at(i)->dBounceCof;
bounce=true;
}
//gravity
b.at(i)->dVelocityY += (o.dGravity)/o.REFRESH;
b.at(i)->pOrigin.y += b.at(i)->dVelocityY + (1/2)*o.dGravity/o.REFRESH*DT*METER;
//METER IS DEFINED GLOBALLY AS 100 which is the amount of pixels in a meter
b.at(i)->pOrigin.x += b.at(i)->dVelocityX/o.REFRESH*METER;
b.at(i)->UpdateRect();
}
}
return;
}
You are using the Euler method of integration. It is possible that your time step (DT) is too large. Also there seems to be a mistake on the row that updates the Y coordinate:
b.at(i)->pOrigin.y += b.at(i)->dVelocityY + (1/2)*o.dGravity/o.REFRESH*DT*METER;
You have already added the gravity to the velocity, so you don't need to add it to the position and you are not multiplying the velocity by DT. It should be like this:
b.at(i)->pOrigin.y += b.at(i)->dVelocityY * DT;
Furthermore there appears to be some confusion regarding the units (the way METER is used).
Okay, a few things here.
You have differing code paths for bounce against left wall and against right wall, but the code is the same. Combine those code paths, since the code is the same.
As to your basic problem: I suspect that your problem stems from the fact that you apply the gravity after you apply any damping forces / bounce forces.
When do you call RunPhysics? In a timer loop? This code is just an approximation and no exact calculation. In the short interval of delta t, the ball has already changed his position and velocity a litte bit which isn't considered in your algorithm and produces little mistakes. You'll have to compute the time until the ball hits the ground and predict the changes.
And the gravity is already included in the velocity, so don't add it twice here:
b.at(i)->pOrigin.y += b.at(i)->dVelocityY + (1/2)*o.dGravity/o.REFRESH*DT*METER;
By the way: Save b.at(i) in a temporary variable, so you don't have to recompute it in every line.
Ball* CurrentBall = b.at(i);
ANSWER!!ANSWER!!ANSWER!! but i forgot my other account so i can't flag it :-(
Thanks for all the great replies, it really helped me alot! The answers that you gave were indeed correct, a couple of my formulas were wrong and some code optimisation could be done, but none was really a solution to the problem. So i just sat down with a piece of paper and started calculation every value i got from my program by hand, took me like two hours :O But i did find the solution to my problem:
The problem is that as i update my velocity (whith corrected code) i get a decimal value, no problem at all. Later i increase the position in Y by adding the velocity times the Delta T, which is a verry small value. The result is a verry small value that needs to be added. The problem is now that if you draw a Elipse() in Win32 the point is a LONG and so all the decimal values are lost. That means that only after a verry long period, when the values velocity starts to come out of the decimal values something happens, and that alongside with that, the higher you drop the ball the better the results (one of my symptons) The solution to this problem was really simple, ad an extra DOUBLE value to my Ball class which contained the true position (including decimals) of my ball. During the RenderFrame() you just take the floor or ceiling value of the double to draw the elipse but for all the calculations you use the Double value. Once again thanks alot for all your replies, STACKOVERFLOW PEOPLE ROCK!!!
If your dBounceCof is > 1 then, yes your ball will bounce higher.
We do not have all the values to be able to reply to your question.
I don't think your equation for position is right:
b.at(i)->dVelocityY += (o.dGravity)/o.REFRESH;
This is v=v0+gt - that seems fine, although I'd write dGravity*DT instead of dGravity/REFRESH_FREQ.
b.at(i)->pOrigin.y += b.at(i)->dVelocityY + (1/2)*o.dGravity/o.REFRESH*DT*METER;
But this seems off: It is eqivalent to p = p0+v + 1/2gt^2.
You ought to multiply velocity * time to get the units right
You are scaling the gravity term by pixels/meter, but not the velocity term. So that ought to be multiplied by METER also
You have already accounted for the effect of gravity when you updated velocity, so you don't need to add the gravity term again.
Thanks for the quick replies!!! Sorry, i should have been more clear, the RunPhysics is beiing run after a PeekMessage. I have also added a frame limiter which makes sure that no more calculations are done per second than the refresh rate of the monitor. My dleta t is therefore 1 second devided by the refresh rate. Maybe my DT is actually too small to calculate, although it's a double value??? My cof of restitution is adjustable but starts at 0.9
You need to recompute your position on bounce, to make sure you bounce from the correct place on the wall.
I.e. resolve the exact point in time when the bounce occured, and calculate new velocity/position based on that direction change (partially into a "frame" of calculation) to make sure your ball does not move "beyond" the walls, more and more on each bounce.
W.r.t. time step, you might want to check out my answer here.
In a rigid body simulation, you need to run the integration up to the instant of collision, then adjust the velocities to avoid penetration at the collision, and then resume the integration. It's sort of an instantaneous kludge to cover the fact that rigid bodies are an approximation. (A real ball deforms during a collision. That's hard to model, and it's unnecessary for most purposes.)
You're combining these two steps (integrating the forces and resolving the collisions). For a simple simulation like you've shown, it's probably enough to skip the gravity bit on any iteration where you've handled a vertical bounce.
In a more advanced simulation, you'd split any interval (dt) that contains a collision at the actual instance of collision. Integrate up to the collision, then resolve the collision (by adjusting the velocity), and then integrate for the rest of the interval. But this looks like overkill for your situation.