How to do Joint tracking in Kinect with a scaled Image - scale

I trying to do some Joint Tracking with kinect (just put a ellipse inside my right hand) everything works fine for a default 640x480 Image, i based myself in this channel9 video.
My code, updated to use the new CoordinateMapper classe is here
...
CoordinateMapper cm = new CoordinateMapper(this.KinectSensorManager.KinectSensor);
ColorImagePoint handColorPoint = cm.MapSkeletonPointToColorPoint(atualSkeleton.Joints[JointType.HandRight].Position, ColorImageFormat.RgbResolution640x480Fps30);
Canvas.SetLeft(elipseHead, (handColorPoint.X) - (elipseHead.Width / 2)); // center of the ellipse in center of the joint
Canvas.SetTop(elipseHead, (handColorPoint.Y) - (elipseHead.Height / 2));
This works. The question is:
How to do joint tracking in a scaled image, 540x380 for example?

The solution for this is pretty simple, i fugured it out.
What a need to do is find some factor to apply to the position.
This factor can be found takin the atual ColorImageFormat of the Kinect and dividing by the desired size, example:
Lets say i am working with the RgbResolution640x480Fps30 format and my Image (ColorViewer) have 220x240. So, lets find the factor for X:
double factorX = (640 / 220); // the factor is 2.90909090...
And the factor for y:
double factorY = (480/ 240); // the factor is 2...
Now, i adjust the position of the ellipse using this factor.
Canvas.SetLeft(elipseHead, (handColorPoint.X / (2.909090)) - (elipseHead.Width / 2));
Canvas.SetTop(elipseHead, (handColorPoint.Y / (2)) - (elipseHead.Height / 2));

I've not used the CoordinateMapper yet, and am not in front on my Kinect at the moment, so I'll toss out this first. I'll see about an update when I get working with the Kinect again.
The Coding4Fun Kinect Toolkit has a ScaleTo extension as part of the library. This adds the ability to take a joint and scale it to any display resolution.
The scaling function looks like this:
private static float Scale(int maxPixel, float maxSkeleton, float position)
{
float value = ((((maxPixel / maxSkeleton) / 2) * position) + (maxPixel/2));
if(value > maxPixel)
return maxPixel;
if(value < 0)
return 0;
return value;
}
maxPixel = the width or height, depending on which coordinate your scaling.
maxSkeleton = set this to 1.
position = the X or Y coordinate of the joint you want to scale.
If you were to just include the above function you could call it like so:
Canvas.SetLeft(e, Scale(640, 1, joint.Position.X));
Canvas.SetTop(e, Scale(480, 1, -joint.Position.Y));
... replacing your 640 & 480 with a different scale.
If you include the Coding4Fun Kinect Toolkit, instead of re-writing code, you could just call it like so:
scaledJoin = rawJoint.ScaleTo(640, 480);
... then plug in what you need.

Related

Matter-js - How to get width and height of rectangle?

Matter-js - How to get width and height of rectangle ?
I need to know is there distance return method implemented in Matter-js .
// part.vertices[0] and part.vertices[1]
I wanna integrate tiles option.
This is how looks critical part (i use override function for Render.bodies it is most interest for me) .:
for (let x = 0; x < this.tiles; x++) {
c.drawImage(
texture,
texture.width * -part.render.sprite.xOffset * part.render.sprite.xScale,
texture.height * -part.render.sprite.yOffset * part.render.sprite.yScale,
texture.width * part.render.sprite.xScale,
texture.height * part.render.sprite.yScale);
}
const { min, max } = part.bounds
it will contain what you need in { x, y }
just substract max.x - min.x & max.y - min.y
I went with a solution very similar to the following:
var width = 30;
var height = 30;
var rect = Bodies.rectangle(150, 100, width, height, {density:0.01, className:"brick", width:width, height:height});
console.log(rect.className, rect.width); // "brick", 30
I decided to carry the original width/height information along with other custom properties such as className
The reason why is because bounds is affected by the rotation of any non perfectly-circular object eg. a rotated rectangle's bounds could be up to ~30% wider than it's actual width.
There are two solutions that I've found.
1- Create a class to wrap the matter.js body, which will also hold onto the height and width. ie:
class rectWrapper {
constructor(x, y, width, height, options){
this.width = width
this.height = height
this.body = Matter.Bodies.rectangle(x, y, width, height, options)
}
}
2- Another way is to use the magic of math to determine the distance between two coordinate points, using Body.vertices[0] and Body.vertices[1] for the width, and Body.vertices[0] and Body.vertices[3] for height. This would also account for any rotation. This link explains it clearly, for 2 and 3 dimensions:
https://sciencing.com/calculate-distance-between-two-coordinates-6390158.html
I would recommend writing your own "utility function" to do this. A heavy handed example might look like this:
function distance(x1, y1, x2, y2){
var x = Math.abs(x1-x2)
var y = Math.abs(y1-y2)
return Math.sqrt((x*x)+(y*y))
}
So a call might look like:
var rect = Matter.Bodies.rectangle(0,0,10,50)
var width = distance(rect.vertices[0].x, rect.verticies[0].y, rect.vertices[1].x, rect.vertices[1].y)
var height = distance(rect.vertices[0].x, rect.vertices[0].y, rect.vertices[3].x, rect.vertices[3].y)
Alternatively, if you happen to be using p5.js as your renderer, you can use p5.dist() which takes x1, y1, x2, y2 as arguments and returns the distance (basically the same as the function above):
https://p5js.org/reference/#/p5/dist
Note, this will only work for rectangles. If you're using different kinds of geometry, I would probably just make a wrapper class myself.

PdfSharp: Why do I need to multiply positions and sizes by 1.25 to get the right result?

I am evaluating PdfSharp to create PDF documents. While comparing it with MigraDoc I figured that I had to multiply each position (x, y) or size by 1.25 to get the intended result. For example if I set the page margins to 2 cm without the correction, I get margins of roughly 1.6 cm.
page.TrimMargins = new TrimMargins
{
All = XUnit.FromCentimeter(2)
};
When I multiply 2 with 1.25 I get the intended 2 cm margins:
page.TrimMargins = new TrimMargins
{
All = XUnit.FromCentimeter(2 * 1.25)
};
Same is with font sizes. I have to multiply the size by 1.25 to get the same size as MigraDoc or even Word would print.
My system does not have a custom scaling or a text size other than 100% by the way (my guess was this could be the cause).
Can someone explain what's going on here?
Edit:
With the help of TomasH I found out that when printing without auto scaling the sizing was perfect. PdfSharp obviously creates PDF documents too large. When doing the same with MigraDoc the PDF is also a bit too large as I found out, but only on a much smaller scale. The question that remains is why the document is too large and what MigraDoc does to correct the PDF size.
Here is my complete test code that only gives the correct positioning and sizing with the correction factor:
using (PdfDocument document = new PdfDocument())
{
// Create an empty page size A4 with defined margins
PdfPage page = CreatePage(document);
using (XGraphics graphics = XGraphics.FromPdfPage(page))
{
const double sizeCorrectionFactor = 1.25;
// Define the page margins. They must be multiplied by 1.25 to be correct!?
page.TrimMargins = new TrimMargins
{
All = XUnit.FromCentimeter(2 * sizeCorrectionFactor)
};
// Draw a string. The font size needs to be multiplied by 1.25 to be correct!?
double x = 0;
double y = 0;
graphics.DrawRectangle(XPens.Black, XBrushes.White, 0, 0, page.Width, page.Height);
graphics.DrawString("PdfSharp Measure Demo", new XFont("Verdana", 20 * sizeCorrectionFactor), XBrushes.Navy, x, y, XStringFormats.TopLeft);
// Draw a rectangle. Position and size must be multiplied by 1.25 to be correct!?
x = XUnit.FromCentimeter(2 * sizeCorrectionFactor);
y = XUnit.FromCentimeter(2 * sizeCorrectionFactor);
double width = XUnit.FromCentimeter(5 * sizeCorrectionFactor);
double height = XUnit.FromCentimeter(5 * sizeCorrectionFactor);
graphics.DrawRectangle(XPens.Red, XBrushes.Silver, x, y, width, height);
}
string pdfFilePath = Path.GetTempFileName() + ".pdf";
document.Save(pdfFilePath);
Process.Start(pdfFilePath);
}
I found the answer: I got the meaning of the (not well documented) TrimMargins property wrong. Setting the trim margins obviously adds the size of the margins to the width or height of the page. This means if trim margins are set, the page size is too large and usually gets scaled down when displaying or printing it. I set 2 cm for the trim margins, making the page obviously 1.25 times too large. The solution is to let all trim margins be 0 and account for any desired page margins in the printing code instead.

JavaFx can not continually zoom out

I encountered some strange problem with JavaFX.
The use case is: I want to zoom out a swatch.
I implemented a Scroll event handler, like this:
private void handleSwatchScrollAction(ScrollEvent se){
if(se.getEventType().equals(ScrollEvent.SCROLL)){
System.out.println("Enter into handleSwatchScrollAction ");
//The following two lines just want to calculate a ration to scale
double diff = (se.getDeltaY() / 40) * 2;
double diffFactor = diff / 2 / this.fxDial.getRadius() + 1;
System.out.println("diffFactor is: " + diffFactor);
//The following lines is to set scale
this.fxSwatch.setScaleX(diffFactor);
this.fxSwatch.setScaleY(diffFactor);
}
System.out.println("finish handleDialScrollAction");
}
Problem is, when I use scroll to zoom out, the first time zoom out operation works well.
But from the second time, from the view there is no change.
The log looks right, but just no change to display, everything the same as before.
for example, the log is always like this when I continually do zoom out operation(scroll up), no matter the first time or after that:
Enter into handleSwatchScrollAction
(deltaX, deltaY) = (0.0, 40.0)
diffFactor is: 1.005
finish handleSwatchScrollAction
So, why from the view there is no change from the second time to do zoom out(scroll up) operation?
Thank you so much in advance!
You are just setting the scale values to the same value (1.005) every time you scroll. The first time, you will see a zoom of 0.5% or so; but on subsequent scroll events you are not changing the value.
You need something like:
double diffFactor = ... // as before
double scale = this.fxSwatch.getScaleX() * diffFactor ;
this.fxSwatch.setScaleX(scale);
this.fxSwatch.setScaleY(scale);

how to generate a map based on a given scale [Bing Map]?

I recently started working with [Bing Api] in my webService [wcf] in c #.
I would like to recover a satellite image of a given scale with Bing!
for example
Scale 1:200 (1 centimeter on the map equal 200 centimeters on the world)
Of course I found this function that explains how to calculate the image resolution satellite bing but this is not what I'm looking for ..
Map resolution = 156543.04 meters/pixel * cos(latitude) / (2 ^ zoomlevel)
Here is my function used to generate my bing map, but I do not know what to send parameter to retrieve an image scale of 1:200.
I need :
Scale = 1:200
I search :
int mapSizeHeight = ?
int mapSizeWidth = ?
int zoomLevel = ?
public string GetImageMap(double latitude,double longitude,int mapSizeHeight, int mapSizeWidth, int zoomLevel)
{
string key = "ddsaAaasm5vwsdfsfd2ySYBxfEFsdfsdfcFh6iUO5GI4v";
MapUriRequest mapUriRequest = new MapUriRequest();
// Set credentials using a valid Bing Maps key
mapUriRequest.Credentials = new ImageryService.Credentials();
mapUriRequest.Credentials.ApplicationId = key;
// Set the location of the requested image
mapUriRequest.Center = new ImageryService.Location();
mapUriRequest.Center.Latitude = latitude;
mapUriRequest.Center.Longitude = longitude;
// Set the map style and zoom level
MapUriOptions mapUriOptions = new MapUriOptions();
mapUriOptions.Style = MapStyle.Aerial;
mapUriOptions.ZoomLevel = zoomLevel;
mapUriOptions.PreventIconCollision = true;
// Set the size of the requested image in pixels
mapUriOptions.ImageSize = new ImageryService.SizeOfint();
mapUriOptions.ImageSize.Height = mapSizeHeight;
mapUriOptions.ImageSize.Width = mapSizeWidth;
mapUriRequest.Options = mapUriOptions;
//Make the request and return the URI
ImageryServiceClient imageryService = new ImageryServiceClient();
MapUriResponse mapUriResponse = imageryService.GetMapUri(mapUriRequest);
return mapUriResponse.Uri;
}
If you haven't already, you might want to check out this article on the Bing Maps tile system calculations, within you will find a section discussing ground resolution and map scale. From that article:
map scale = 1 : ground resolution * screen dpi / 0.0254 meters/inch
Depending on which implementation of Bing Maps you use, specifying the view via a precise map scale might not be possible. I think this is due to the fact that you don't have precise control over the zoom level. For example, in the javascript ajax version, you can only specify zoom levels in integer values, so the ground resolution part of the above equation will jump in discreet steps. At the equator, using a zoom level of 21 will give you a scale of 1: 282, and a zoom level of 22 will give you 1:141. Since you can't specify a decimal value for zoom level, it is not possible to get an exact 1:200 scale using the ajax control. I don't have extensive experience with the .net Bing Maps control, so you might want to investigate that API to see if you can specify an arbitrary zoom level.
If you can precisely control the zoom level and know the dpi value, then the 1:200 scale is achievable using the equation described in the above linked article.

How do I get the visual width and height of a rotated component?

I'm playing around with code like this:
<s:Button id="test" label="test" transformX="{Math.floor(test.width/2)}" rotationY="20" x="20" y="20" />
The button is rotated on the Y axis and the rotate pivot is in the middle of the button.
This will create a button that looks something like this:
(source: jeffryhouser.com)
The rotated button is, visually, filling a different space than the x, y, height, and width values would you have believe.
The "A" value in my image is the height of the button. But, what I want to use for calculation and placement purposes is the B value.
Additionally, I'd like to perform similar calculations with the width; getting the width from the top right corner to the bottom left corner.
How do I do this?
I put together a sample to show off the various approaches for calculating this that people are suggesting. The source code is also available. Nothing is quite working like I'd expect. For example, turn the rotationSlider to 85. The button is effectively invisible, yet all approaches are still giving it height and width.
My math may be a bit rusty, but this is how I would find the answer :
You would extend a right-triangle from the right edge of the button to the bottom-most point of the diagram you have (A-B). You can then use the Law of Sines to get three angles : 90', 20' and 70' (90 will always be there, and then your variable - 180 for the third angle).
You can then use the following formula to find your answer :
B = ((button.width * sin(button.rotationY)) / (sin(90 -button.rotationY)) + (button.height)
getBounds(..) and getRect(..) are supposed to be the methods for getting the width and height of transformed objects.
Not tried them in Flex 4 yet, but they always worked for me in Flex 3.
The answer was in one of the comments from James Ward on this question and is located at this blog post.
The one thing the blog post doesn't say is that in many cases, the perspectiveProjection property of the transform property on the class in question will be null. The linked to example took care of this by setting the maintainProjectionCenter property to true. But, you could also create a new perspectiveProjection object like this:
object.transform.perspectiveProjection = new PerspectiveProjection();
I wrapped up the function from evtimmy into a class:
/**
* DotComIt/Flextras
* Utils3D.as
* Utils3D
* jhouser
* Aug 5, 2010
*/
package com.flextras.coverflow
{
import flash.geom.Matrix3D;
import flash.geom.PerspectiveProjection;
import flash.geom.Rectangle;
import flash.geom.Utils3D;
import flash.geom.Vector3D;
public class TransformUtilities
{
public function TransformUtilities()
{
}
//--------------------------------------------------------------------------
//
// Methods
//
//--------------------------------------------------------------------------
//----------------------------------
// projectBounds
//----------------------------------
// info from
// http://evtimmy.com/2009/12/calculating-the-projected-bounds-using-utils3dprojectvector/
/**
* Method retrieved from
* http://evtimmy.com/2009/12/calculating-the-projected-bounds-using-utils3dprojectvector/
*
* #param bounds: The rectangle that makes up the object
* #param matrix The 3D Matrix of the item
* #param the projection of the item's parent.
*/
public static function projectBounds(bounds:Rectangle,
matrix:Matrix3D,
projection:PerspectiveProjection):Rectangle
{
// Setup the matrix
var centerX:Number = projection.projectionCenter.x;
var centerY:Number = projection.projectionCenter.y;
matrix.appendTranslation(-centerX, -centerY, projection.focalLength);
matrix.append(projection.toMatrix3D());
// Project the corner points
var pt1:Vector3D = new Vector3D(bounds.left, bounds.top, 0);
var pt2:Vector3D = new Vector3D(bounds.right, bounds.top, 0)
var pt3:Vector3D = new Vector3D(bounds.left, bounds.bottom, 0);
var pt4:Vector3D = new Vector3D(bounds.right, bounds.bottom, 0);
pt1 = Utils3D.projectVector(matrix, pt1);
pt2 = Utils3D.projectVector(matrix, pt2);
pt3 = Utils3D.projectVector(matrix, pt3);
pt4 = Utils3D.projectVector(matrix, pt4);
// Find the bounding box in 2D
var maxX:Number = Math.max(Math.max(pt1.x, pt2.x), Math.max(pt3.x, pt4.x));
var minX:Number = Math.min(Math.min(pt1.x, pt2.x), Math.min(pt3.x, pt4.x));
var maxY:Number = Math.max(Math.max(pt1.y, pt2.y), Math.max(pt3.y, pt4.y));
var minY:Number = Math.min(Math.min(pt1.y, pt2.y), Math.min(pt3.y, pt4.y));
// Add back the projection center
bounds.x = minX + centerX;
bounds.y = minY + centerY;
bounds.width = maxX - minX;
bounds.height = maxY - minY;
return bounds;
}
}
}
Although that is the answer to my question, I'm not sure if it was the solution to my problem. Thanks everyone!

Resources