I'm trying to compute the x-, y- and z-Coordinate of a point selected by the user.
My program shows the Color Stream Image and the depth stream image and the user is able to select two points of interest. My program then should calculate the distance beteween the two point. That for I need the coordinates of the point in mm. So my plan was to map the frame to a SkeletonPoint Structure so I can just read the informations, provided by the kinect sensor.
My Question now is, if I'm doing right or if I'm missing something in my code.
The problem is that I sometimes get negativ coordinates for some point in x and y axis, so I'm not sure if I'm missing something.
SkeletonPoint[] mySkeletonArray;
private void SensorDepthFrameReady(object sender, DepthImageFrameReadyEventArgs e)
{
using (DepthImageFrame dFrame = e.OpenDepthImageFrame())
{
if (dFrame != null)
{
dFrame.CopyDepthImagePixelDataTo(myDepthArray);
mySensor.CoordinateMapper.MapDepthFrameToSkeletonFrame(DepthImageFormat.Resolution640x480Fps30, myDepthArray, mySkeletonArray);
this.myDepthBitmap.WritePixels(
new Int32Rect(0, 0, this.myDepthBitmap.PixelWidth, this.myDepthBitmap.PixelHeight),
this.colorPixels,
this.myDepthBitmap.PixelWidth * sizeof(int),
0);
}
}
}
private void Mouse_ClickTest(object sender, System.Windows.Input.MouseEventArgs e)
{
System.Windows.Point myMousePosition = e.GetPosition(DepthImage);
double xpixel = myMousePosition.X;
double ypixel = myMousePosition.Y;
int xpos = (int)xpixel;
int ypos = (int)ypixel;
int depthWidth = mySensor.DepthStream.FrameWidth;
int depthIndex = xpos + (ypos * depthWidth);
SkeletonPoint mySkeletonArray = this.mySkeletonArray[depthIndex];
float zpos = mySkeletonArray.Z;
float xp = mySkeletonArray.X;
float yp = mySkeletonArray.Y;
}
Related
Solved
I am trying to simulate a planet rotating a star. I am currently aware of the syntax to move the picture box
(I have this in a timer so it is repeated)
private void rotate_timer(object sender, EventArgs e) {
picturebox1.location = new point (picturebox1.location.x + 1,
picturebox1.location.y + 1);
}
But I don't know where to start so that it rotates around a specific point.
How would I go about rotating it around (0,0)?
This may help:
float angle = 0;
float rotSpeed = 1;
Point origin = new Point(222, 222); // your origin
int distance = 100; // your distance
private void timer1_Tick(object sender, EventArgs e)
{
angle += rotSpeed;
int x = (int)(origin.X + distance * Math.Sin(angle *Math.PI / 180f));
int y = (int)(origin.Y + distance * Math.Cos(angle *Math.PI / 180f));
yourControl.Location = new Point(x, y);
}
Pick your timer Interval and don't be disappointed that it will look a little uneven. Winforms is really bad at animation..
If you want the image to rotate as well you can find an example here.
I am using visual studio c# windows form, I need help to draw a circle using the Mouse click.. first click will give me the center of the circle equal to the cursor position and the second click will give me a point on the border of the circle equal to the second position of the cursor, the distance between the to points will give me the radius..now I have radius and point ..I can draw a circle ..The code doesn't work because I only can get one position of the cursor no matter how many times I click the mouse
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
int lastX = Cursor.Position.X;//the first click x cursor position
int lastY = Cursor.Position.Y;//the first click y cursor position,
//is there any way to reuse the Cursor.Position for different point ??
int x = Cursor.Position.X;//the second click x cursor position
int y = Cursor.Position.Y;//the second click y cursor position
Graphics g;
double oradius=Math.Sqrt(((lastX-x)^2) +((lastY-y)^2));
//double newy = Math.Sqrt(lastY);
// int newxv = Convert.ToInt32(newx);
int radius= Convert.ToInt32(oradius);
g = this.CreateGraphics();
Rectangle rectangle = new Rectangle();
PaintEventArgs arg = new PaintEventArgs(g, rectangle);
DrawCircle(arg, x, y,radius,radius);
}
private void DrawCircle(PaintEventArgs e, int x, int y, int width, int height)
{
System.Drawing.Pen pen = new System.Drawing.Pen(System.Drawing.Color.Red, 3);
e.Graphics.DrawEllipse(pen, x - width / 2, y - height / 2, width, height);
}
}
You need to store the first click as well before you start doing the calculations. One way to do this is to create a class that simply throws an event every second time you pass it x and y coordinates like this:
public class CircleDrawer
{
private int _firstX;
private int _firstY;
private int _secondX;
private int _secondY;
private bool _isSecondClick;
private event EventHandler OnSecondClick;
public void RegisterClick(int x, int y)
{
if(_isSecondClick)
{
_secondX = x;
_secondY = y;
if(OnSecondClick != null)
OnSecondClick(this, null);
}
else
{
_firstX = x;
_firstY = y;
_isSecondClick = true;
}
}
}
You can then in your code simply call your methods:
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
int lastX = Cursor.Position.X;//the first click x cursor position
int lastY = Cursor.Position.Y;//the first click y cursor position,
_circleDrawer.RegisterClick(lastX, lastY);
}
And in your constuctor:
public MyForm()
{
_circleDrawer = new CircleDrawer();
_circleDrawer.OnSecondClick += DrawCircle();
}
public void DrawCircle()
{
// Your drawing code
}
Your lastX and lastY are local variables, and you initialize them in the beginning of the MouseDown event handler. They should be class level variables and should be populated at the end of the MouseDown event handler.
Also, you should test if they already have a value, and only if they have value then draw the circle and then clear them (so that the next circle will have it's own center).
Here is an improvement of your code. Note I've used the using keyword with the graphics object and with the pen - get used to use it every time you are using an instance of anything that's implementing the IDisposable interface.
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
if (_lastPosition != Point.Empty)
{
var currentPosition = Cursor.Position;
var oradius = Math.Sqrt(((_lastPosition.X - currentPosition.X) ^ 2) + ((_lastPosition.Y - currentPosition.Y) ^ 2));
var radius = Convert.ToInt32(oradius);
using (var g = this.CreateGraphics())
{
var arg = new PaintEventArgs(g, new Rectangle());
DrawCircle(arg, currentPosition, radius, radius);
}
_lastPosition = Point.Empty;
}
else
{
_lastPosition = Cursor.Position;
}
}
private void DrawCircle(PaintEventArgs e, Point position, int width, int height)
{
using (var pen = new System.Drawing.Pen(System.Drawing.Color.Red, 3))
{
e.Graphics.DrawEllipse(pen, position.X - width / 2, position.Y - height / 2, width, height);
}
}
Note: This code can be improved even further.
There are many things fundamentally wrong with this code, here is a complete, working example.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private Point clickCurrent = Point.Empty;
private Point clickPrev = Point.Empty;
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
clickPrev = clickCurrent;
clickCurrent = this.PointToClient(Cursor.Position);
if (clickPrev == Point.Empty) return;
Graphics g;
double oradius = Math.Sqrt((Math.Pow(clickPrev.X - clickCurrent.X, 2)) + (Math.Pow(clickPrev.Y - clickCurrent.Y, 2)));
int radius = Convert.ToInt32(oradius);
g = this.CreateGraphics();
Rectangle rectangle = new Rectangle();
PaintEventArgs arg = new PaintEventArgs(g, rectangle);
DrawCircle(arg, clickPrev.X, clickPrev.Y, radius * 2, radius * 2);
clickCurrent = Point.Empty;
}
private void DrawCircle(PaintEventArgs e, int x, int y, int width, int height)
{
System.Drawing.Pen pen = new System.Drawing.Pen(System.Drawing.Color.Red, 3);
e.Graphics.DrawEllipse(pen, x - width / 2, y - height / 2, width, height);
}
}
private int _firstX;
private int _firstY;
private int _secondX;
private int _secondY;
private bool _isSecondClick;
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
if (_isSecondClick)
{
_secondX = Cursor.Position.X;
_secondY = Cursor.Position.Y;
var radious1 = Math.Pow(_firstX - _secondX, 2);
var radious2 = Math.Pow(_firstY - _secondY, 2);
var radious = Math.Sqrt(radious1 + radious2);
Graphics g = this.CreateGraphics();
Rectangle rectangle = new Rectangle();
PaintEventArgs arg = new PaintEventArgs(g, rectangle);
DrawCircle(arg, _secondX, _secondY, radious, radious);
}
else
{
_firstX = Cursor.Position.X;
_firstY = Cursor.Position.Y;
_isSecondClick = true;
}
}
private void DrawCircle(PaintEventArgs arg, int x, int y, double width, double height)
{
System.Drawing.Pen pen = new System.Drawing.Pen(System.Drawing.Color.Red, 3);
var xL = Convert.ToInt32(x - width / 2);
var yL = Convert.ToInt32(y - height / 2);
var hL = Convert.ToInt32(height);
var wL = Convert.ToInt32(width);
arg.Graphics.DrawEllipse(pen, xL, yL, wL, hL);
}
I wrote a program which displays the color and the depth stream of a kinect sensor. In the depth image it's possible for the user to select two points and the program displays the coordinates of the points. Now I want to improve my program. So I added a new window called Disatance.xaml. This window is opened when the user checks a Check-box. In this window I want to show the coordinates, rather then in the MainWindow. So I need to pass the integer variables of the x- and y-Coordinates. My problem now is that I'm really new to C# and I don't know a way to pass integers from one window to an other window. I really how somebody can help me.
The main code is executed in the main window. In that I open the second window, by clicking on a button. My code looks like this:
private void CmdDistance_Click(object senderr, RoutedEventArgs e)
{
Distance distance = new Distance();
distance.Show();
}
The coordinates are currently calculatet and displayed by my function void Mouse_ClickTest:
private void Mouse_ClickTest(object sender, System.Windows.Input.MouseEventArgs e)
{
if (ChkDistance.IsChecked == true)
{
System.Windows.Point myMousePosition = e.GetPosition(DepthImage);
double xpixel = myMousePosition.X;
double ypixel = myMousePosition.Y;
int xpos = (int)xpixel;
int ypos = (int)ypixel;
if ((xpos > 0 || ypos > 0) && (xpos <= 640 || ypos <= 480))
{
int depthWidth = mySensor.DepthStream.FrameWidth;
int depthIndex = xpos + (ypos * depthWidth);
if (depthIndex < 307840)
{
SkeletonPoint mySkeletonArray = this.mySkeletonArray[depthIndex];
float zpos = mySkeletonArray.Z;
zpos = zpos * 1000;
int z = (int)zpos;
float xp = mySkeletonArray.X;
xp = xp * 1000;
int x = (int)xp;
float yp = mySkeletonArray.Y;
yp = yp * 1000;
int y = (int)yp;
if (e.LeftButton == MouseButtonState.Pressed)
{
if (i == false)
{
TxtCoordX.Text = string.Format("X: {0}", x);
TxtCoordY.Text = string.Format("Y: {0}", y);
TxtCoordZ.Text = string.Format("Z: {0}", z);
i = true;
}
else
{
TxtCoordX2.Text = string.Format("X: {0}", x);
TxtCoordY2.Text = string.Format("Y: {0}", y);
TxtCoordZ2.Text = string.Format("Z: {0}", z);
i = true;
}
}
}
else
{
return;
}
}
else
{
return;
}
}
}
Now I want to pass the integer variable x, y and z to the window Distance
Declare your Distance class higher in scope in your MainWindow class. The way you have it right now, it's created and goes out of scope once the Click handler completes execution.
The quickest and dirtiest way to do what you're asking is to create a method in the code-behind of your Distance form. It could be something like:
public void SetCoordinates(float x, float y, float z)
{
//Set properties here
}
Then you can make TextBlocks or TextBoxes to those properties.
You can also initialize the x,y,z to a value by passing them in the constructor:
Instead of:
new Distance();
Do:
new Distance(float x, float y, float z);
Then you can make TextBlocks or TextBoxes to those properties.
I am working with the XBox-Kinect (Beta SDK).
I try to direct a robot to grab an object from a box that contains many objects (bachelorthesis), for that I need to find the closest point of the nearest object to the kinect. Than i can localize the complete object by region growing and find out the grabbing point for the robot.
Now I have two question for that topic:
How can I find out the x and y coordinate of this point? ( I have the distance already)
How can I access the private byte[] FindMinimum(ImageFrame imageFrame)
by button click to find the closest distance?
Here is my code:
void nui_DepthFrameReady(object sender, ImageFrameReadyEventArgs e)
{
image1.Source = e.ImageFrame.ToBitmapSource();
byte[] Minumum = FindMinimum(e.ImageFrame);
}
private void button1_Click(object sender, RoutedEventArgs e)
{
FindMinimum();
}
private byte[] FindMinimum(ImageFrame imageFrame)
{
int height = imageFrame.Image.Height;
int width = imageFrame.Image.Width;
Byte[] depthData = imageFrame.Image.Bits;
Byte[] colorFrame = new byte[imageFrame.Image.Height * imageFrame.Image.Width * 4];
int min = int.MaxValue, max = int.MinValue;
for (int i = 0; i < depthData.Length; i += 2)
{
int dist = GetDistance(depthData[i], depthData[i + 1]);
if (dist < min && dist > 0) min = dist;
if (dist > max) max = dist;
}
textBox1.Text = Convert.ToString(min);
return colorFrame;
}
private int GetDistance(byte firstFrame, byte secondFrame)
{
int distance = (int)(firstFrame | secondFrame << 8);
return distance;
}
private void Window_Closed(object sender, EventArgs e)
{
nui.Uninitialize();
}
}
}
I have a program that prints the cube and which can be rotated. Here's the code.
public partial class ProjectorForm : Form
{
Projector projector;
Cube cube;
float deltaRot;
public ProjectorForm()
{
InitializeComponent();
}
private void ProjectorForm_Load(object sender, EventArgs e)
{
deltaRot = 0.01f;
projector = new Projector();
cube = new Cube(Vector3.UnitZ * 20*10, 10*10, 10*10, 15*10);
updateTimer.Start();
}
private void updateTimer_Tick(object sender, EventArgs e)
{
if (rotXBox.Checked)
cube.RotateX(deltaRot);
if (rotYBox.Checked)
cube.RotateY(deltaRot);
if (rotZBox.Checked)
cube.RotateZ(deltaRot);
doubleBufferedPanel1.Invalidate();
}
private void doubleBufferedPanel1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.Clear(Color.White);
cube.Draw(projector, Color.Black, doubleBufferedPanel1.ClientSize.Width, doubleBufferedPanel1.ClientSize.Height, e.Graphics);
}
private void button1_Click(object sender, EventArgs e)
{
deltaRot = float.Parse(deltaRotBox.Text);
}
}
class Projector
{
public Vector3 cameraPosition;
public float planeDistance;
ProjectorForm n = new ProjectorForm();
public Projector()
{
cameraPosition = Vector3.Zero;
planeDistance = 256; //Here, multiply by 2 and the scaled cube, how to make that scale when you press the button.
}
public PointF Project(Vector3 point, float width, float height)
{
float x = cameraPosition.X + ((cameraPosition.Z + planeDistance) / (point.Z - cameraPosition.Z)) * (point.X - cameraPosition.X) + width / 2;
float y = cameraPosition.Y + ((cameraPosition.Z + planeDistance) / (point.Z - cameraPosition.Z)) * (point.Y - cameraPosition.Y) + height / 2;
return new PointF(x, y);
}
public void DrawLine(Color color, Vector3 p1, Vector3 p2, float width, float height, Graphics g)
{
g.DrawLine(new Pen(color), Project(p1, width, height), Project(p2, width, height));
}
public void FillPolygon(Color color, Vector3[] vertices, float width, float height, Graphics g)
{
PointF[] points = new PointF[vertices.Length];
for (int i = 0; i < points.Length; i++)
points[i] = Project(vertices[i], width, height);
g.FillPolygon(new SolidBrush(color), points);
}
}
How to make a cube can be scaled by pressing a button. I found the variable planeDistance in the class Projector, when it increased by 2 times the cube is scaled, but I do not know how it can be increased by means of a button.
The field planeDistance is public, so you can change it from outside the class. i.e. just add something like the following to the event handler of a button:
projector.planeDistance += 10; // Change 10 as appropriate
It's worth noting that this doesn't change the size of the cube, it changes how far away the camera is from it. So, while the cube appears to be changing in size, that's just because the camera is moving closer / further away.
To actually change the size of the cube you would have to change fields in the cube class.
Since the size is defined by the vectors created in the constructor you don't really have an easy way of changing them once the cube is created.
You could create a new cube whenever you want to change the size (keep track of the size in another variable on the form).
You could add a method to the cube class that creates new vectors that define the new size (it would look a bit like the constructor, only populating the arrays, not creating them).
You could add a size field to your cube, always create a unit cube (1, 1, 1) then when rendering multiply each vector by your size.