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();
}
}
}
Related
I have some picture boxes (billiard balls) in a Windows Forms and I want to make them collide. In the initial condition they are at rest and I want to apply an impulse to one of them. The way I was thinking this problems was like this:
I have two events:
Form1_MouseDown => (here I click on a ball and I want to check that click is on it, I start a timer, and I want to get the initial mouse coordinates)
Form1_MouseUp => (here I want to stop the timer, in order to measure time interval, also I want to get the final mouse coordinates).
Having in mind, the time interval, the initial and the final point of the mouse position (the distance between these two), I can mathematically express the click impulse on a ball.
public partial class Form1 : Form
{
public Ball b1;
public Ball b2;
public Ball b3;
public Ball b4;
public Ball b5;
public Ball b6;
public Ball[] list;
double time;
ushort first_ball;
bool started = false;
Point Start;
Point End;
public Form1()
{
InitializeComponent();
b1 = new Ball(ref p1, 0, 0);
b2 = new Ball(ref p2, 0, 0);
b3 = new Ball(ref p3, 0, 0);
b4 = new Ball(ref p4, 0, 0);
b5 = new Ball(ref p5, 0, 0);
b6 = new Ball(ref p6, 0, 0);
list = new Ball[] { b1, b2, b3, b4, b5, b6 };
}
private void Form1_Load(object sender, EventArgs e)
{
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
foreach (var z in list)
Ball.Move(z, this);
for(ushort i=0; i < list.Length; i++)
for(ushort j=i; j< list.Length; j++)
{
if (i != j)
{
if (Ball.distance(list[i].Center, list[j].Center) < (list[i].ball.Width / 2 + list[j].ball.Width / 2))
{
list[i].vx *= -1;
list[i].vy *= -1;
list[j].vx *= -1;
list[j].vy *= -1;
}
}
}
}
// here starts the problematic part
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
Start.X = MousePosition.X;
Start.Y = MousePosition.Y;
for (ushort i = 0; i < list.Length; i++)
{
if(Start.X < list[i].ball.Left + list[i].ball.Width && Start.X > list[i].ball.Left && Start.Y < list[i].ball.Top + list[i].ball.Height && Start.Y > list[i].ball.Top)
{
timer2.Start();
started = true;
first_ball = i;
}
}
}
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
timer2.Stop();
if (started)
{
End.X = MousePosition.X;
End.Y = MousePosition.Y;
/*
here I want to get the distance between Start point and End point
here I want to get the time interval
*/
}
}
//here ends the problematic part
}
public class Ball
{
public PictureBox ball;
public int vx, vy;
public static UInt16 friction_coef;
public Point Center;
public Ball(ref PictureBox p, int x = 0, int y = 0)
{
this.vx = x;
this.vy = y;
this.ball = p;
this.Center = new Point(p.Left + p.Width / 2, p.Top + p.Height / 2);
}
public static void Move(Ball b, in Form f)
{
if (b.ball.Top < 0 || b.ball.Top + b.ball.Height > f.ClientSize.Height)
{
b.vx *= -1;
}
if (b.ball.Left < 0 || b.ball.Left + b.ball.Width > f.ClientSize.Width)
{
b.vy *= -1;
}
b.ball.Top += b.vx;
b.ball.Left += b.vy;
b.Center.X = b.ball.Left + b.ball.Width / 2;
b.Center.Y = b.ball.Top + b.ball.Height / 2;
}
public static double distance(Point P1, Point P2)
{
return Math.Sqrt((P1.X - P2.X) * (P1.X - P2.X) + (P1.Y - P2.Y) * (P1.Y - P2.Y));
}
}
The problem is that Form1_MouseDown is not triggered by a click on ball, which is obvious, but I want to make the transition from a ball click to Form1_MouseUp (which is outside the ball), without losing the state started on a ball click.
After testing this code it may be that my idea is wrong and I ran out of ideas regarding the implementation.
This must be a very noobie question so please don't judge me too hard!
In Windows Form Applications something like this would easily get the bound of a progressbar:
progressBar1.Bounds.X(or)Y
How can I get the same in WPF? I can't find anything on this on internet.
This is my progressbar OnClick method for the windows form app:
private void progressBar1_MouseClick(object sender, MouseEventArgs e)
{
float absoluteMouse = (PointToClient(MousePosition).X - progressBar1.Bounds.X);
float calcFactor = progressBar1.Width / (float)100;
float relativeMouse = absoluteMouse / calcFactor;
double maxlength = BASS_ChannelBytes2Seconds(BassHandle, (ulong)PlayBackLength);
double percents = (maxlength * relativeMouse) / 100;
UInt64 pos = BASS_ChannelSeconds2Bytes(BassHandle, percents);
BASS_ChannelSetPosition(BassHandle, pos, 0);
progressBar1.Value = Convert.ToInt32(relativeMouse);
int current = BASS_ChannelGetPosition(BassHandle, 0);
TimeLabel.Text = FormatTime(BASS_ChannelBytes2Seconds(BassHandle, (uint)current)) + "/" + FormatTime(BASS_ChannelBytes2Seconds(BassHandle, (uint)PlayBackLength));
}
This is my attempt on it's WPF version
private void progressBar1_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
double absoluteMouse = (PointFromScreen(GetMousePosition()).X - progressBar1.?);
double calcFactor = progressBar1.Width / (float)100;
double relativeMouse = absoluteMouse / calcFactor;
double maxlength = Imports.BASS_ChannelBytes2Seconds(GlobalVariables.BassHandle, (ulong)GlobalVariables.PlayBackLength);
double percents = (maxlength * relativeMouse) / 100;
UInt64 pos = Imports.BASS_ChannelSeconds2Bytes(GlobalVariables.BassHandle, percents);
Imports.BASS_ChannelSetPosition(GlobalVariables.BassHandle, pos, 0);
progressBar1.Value = Convert.ToInt32(relativeMouse);
int current = Imports.BASS_ChannelGetPosition(GlobalVariables.BassHandle, 0);
TimeLabel.Text = FormatTime(Imports.BASS_ChannelBytes2Seconds(GlobalVariables.BassHandle, (uint)current)) + "/" + FormatTime(Imports.BASS_ChannelBytes2Seconds(GlobalVariables.BassHandle, (uint)GlobalVariables.PlayBackLength));
}
You may use progressBar1.Margin.Left - for X, progressBar1.Margin.Top - for Y.
But there will be value relative to Container where ProgressBar is placed.
Please help me with this problem :(
This is what i'm trying to do:
Because QuickFont use different coordinate system with my ortho so i have to calculate coordinate for my text and it's ok.
The problem is when i resized the form, the text's coordiantes become wrong.
Here is my code:
public static void DrawOxy(float lO, float rO, float tO, float bO, int controlW, int controlH)
{
GL.Color3(Color.Blue);
GL.Begin(BeginMode.Lines);
GL.Vertex2(lO, 0);
GL.Vertex2(rO, 0);
GL.Vertex2(0, tO);
GL.Vertex2(0, bO);
for (float i = lO; i < rO; i+=2)
{
GL.Vertex2(i, 0.5);
GL.Vertex2(i, -0.5);
}
for (float j = bO; j < tO; j+=2)
{
GL.Vertex2(0.2, j);
GL.Vertex2(-0.2, j);
}
GL.End();
QFont font = new QFont(new Font(FontFamily.GenericSansSerif, 15));
GL.PushAttrib(AttribMask.ColorBufferBit);
font.Options.Colour = Color.Red;
QFont.Begin();
float horStep = ((float)controlW / rO);
font.Print(horStep.ToString(), new Vector2(0, 0));
float beginX = 0;
for (float i = lO; i < rO; i += 2)
{
font.Print(i.ToString(), new Vector2(beginX, (((float)controlH / 2))));
beginX += horStep;
}
QFont.End();
GL.PopAttrib();
}
private void SetupViewport()
{
int w = glControl1.Width;
int h = glControl1.Height;
int left = -(w / 2);
int right = w / 2;
int top = h / 2;
int bottom = -(h / 2);
GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();
GL.Ortho(leftOr, rightOr, bottomOr, topOr, -1, 1); // Bottom-left corner pixel has coordinate (0, 0)
GL.Viewport(0, 0, w, h); // Use all of the glControl painting area
}
private void glControl1_Load(object sender, EventArgs e)
{
loaded = true;
GL.ClearColor(Color.White);
SetupViewport();
}
private void glControl1_Paint(object sender, PaintEventArgs e)
{
if (!loaded) // Play nice
return;
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.LineWidth(2);
DrawingObjects.DrawOxy(leftOr, rightOr, topOr, bottomOr, glControl1.Width, glControl1.Height);
glControl1.SwapBuffers();
}
private void glControl1_Resize(object sender, EventArgs e)
{
if (!loaded)
{
return;
}
SetupViewport();
}
Sorry about my english :)
You need to recreate the projection matrix. Based on your code above, this should do it:
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
SetupViewport();
}
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;
}
I'm creating graphic at picturebox from left to right side, by adding single pixel columns, with predetermined time intervals(300ms). When subsequent pixel columns exceed the picturebox width, I can't see more of them.
How to make moving picturebox window, which would allow to see the current pixel column all the time?
I'm using BASS library, code is below.
private void timer1_Tick_1(object sender, EventArgs e)
{
graphic = pictureBox1.CreateGraphics();
bool spectrum3DVoicePrint = visuals.CreateSpectrum3DVoicePrint(rHandle, graphic, pictureBox1.Bounds, Color.Navy, Color.Navy, pos, false, true);`
graphic.Dispose();
pos = ++;
}
you need to store each position in array.
Here is my simple code for demonstrate to draw line and move after reaches at width of picturebox. Make sure any mistake of any value of pixel,x,y,etc.. leads to wrong output.
int x = -1;
int y = 50;
Random rnd = new Random();
bool check = true;
int[,] pos;
int index = -1;
private void Form1_Load(object sender, EventArgs e)
{
//Initalize array
pos = new int[pictureBox1.Width + 2, 2];
}
private void timer1_Tick(object sender, EventArgs e)
{
Graphics graphic = pictureBox1.CreateGraphics();
if (x < pictureBox1.Width)
{
index++;
x++;
}
else
{
graphic.Clear(Color.Black);
for (int i = 0; i < pictureBox1.Width; i++)
{
pos[i, 1] = pos[i + 1, 1];
graphic.DrawRectangle(System.Drawing.Pens.Lime, pos[i, 0], pos[i, 1], 1, 1);
}
}
graphic.DrawRectangle(System.Drawing.Pens.Lime, x, y, 1, 1);
pos[index, 0] = x;
pos[index, 1] = y;
graphic.Dispose();
//for random dots
//y = rnd.Next(5, 95);
//for line
if (check)
y++;
else
y--;
if (y == 100)
check = false;
if (y == 5)
check = true;
}