使用Xtion pro live模拟手部位置

时间:2013-02-01 22:56:34

标签: c#

我正在学习C#编程和Kinect传感器编程(我很喜欢 C#语言和Kinect中的新手。我正在尝试使用Microsoft Visual C#2010 Express使用Xtion Pro Live传感器编写应用程序来控制机器人。在我的主窗体中,有2个picturebox对象,2个按钮对象,3个标签和3个文本框对象。两个图片框对象之一(pictureBox1)用于显示RGB摄像头。另一个pictureBox2)用于模拟2D(x和y坐标)图形中的手部位置。两个按钮之一(button1)用于初始化Xtion Pro Live并在picturebox1上显示RGB相机,并模拟picturebox2上的手部位置。另一个(button2)是退出程序。三个标签,label1,label2,label3和三个文本框,textbox1,textbox2,textbox3用于显示手的3个坐标。

这是我在Form1.cs中的代码:

using OpenNI;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace HandTracking
{
    public partial class Form1 : Form
    {
        public const string path = @"C:/Vu/Kinect/Data/SamplesConfig.xml";
        public bool run;
        public Thread thread;
        public Bitmap bitmap;
        public Context context;
        public ScriptNode node;
        public ImageGenerator image;
        public DepthGenerator depth;
        public GestureGenerator gesture;
        public HandsGenerator hand;
        public Queue<Point3D> handpoint = new Queue<Point3D>();
        public const int maxpoint = 30;
        enum GestureStatus
        {
            Unrecognized, Progress, Recognized
        }
        private GestureStatus gesstatus = GestureStatus.Unrecognized;
        enum HandsStatus
        {
            Untracked, Create, Update
        }
        private HandsStatus handstatus = HandsStatus.Untracked;
        public Pen pen = new Pen(Color.Red, 5);
        public Brush brush = new SolidBrush(Color.Magenta);
        public Font font = new Font("Times New Roman", 20);
        public PointF point = new PointF(0, 0);

        public Form1()
        {
            InitializeComponent();
            this.pictureBox1.BackColor = Color.Black;
            this.pictureBox2.BackColor = Color.White;
            this.button1.Enabled = true;
        }

        public void button1_Click(object sender, EventArgs e)
        {
            this.button1.Enabled = false;
            try
            {
                context = Context.CreateFromXmlFile(path, out node);
                image = context.FindExistingNode(NodeType.Image) as ImageGenerator;
                if (image == null)
                    throw new Exception(context.GlobalErrorState);
                depth = context.FindExistingNode(NodeType.Depth) as DepthGenerator;
                if (depth == null)
                    throw new Exception(context.GlobalErrorState);
                depth.AlternativeViewpointCapability.SetViewpoint(image);
                    gesture = context.FindExistingNode(NodeType.Gesture) as     GestureGenerator;
                if (gesture == null)
                   throw new Exception(context.GlobalErrorState);
                gesture.AddGesture("RaiseHand");
                gesture.GestureRecognized += new     EventHandler<GestureRecognizedEventArgs>(GestureRecognized);
                gesture.GestureProgress += new EventHandler<GestureProgressEventArgs>    (GestureProgress);
                hand = context.FindExistingNode(NodeType.Hands) as HandsGenerator;
                if (hand == null)
                    throw new Exception(context.GlobalErrorState);
                hand.HandCreate += new EventHandler<HandCreateEventArgs>(HandCreate);
                hand.HandUpdate += new EventHandler<HandUpdateEventArgs>(HandUpdate);
                context.StartGeneratingAll();
                MapOutputMode map = image.MapOutputMode;
                bitmap = new Bitmap((int)map.XRes, (int)map.YRes,     System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                run = true;
                thread = new Thread(CallThread);
                thread.Start();
            }
            catch (Exception error)
            {
                MessageBox.Show(error.Message);
            }
        }

        public void GestureRecognized(object sender, GestureRecognizedEventArgs e)
        {
            gesstatus = GestureStatus.Recognized;
            hand.StartTracking(e.EndPosition);
        }

        public void GestureProgress(object sender, GestureProgressEventArgs e)
        {
            gesstatus = GestureStatus.Progress;
        }

        public void HandCreate(object sender, HandCreateEventArgs e)
        {
            handstatus = HandsStatus.Create;
        }

        public void HandUpdate(object sender, HandUpdateEventArgs e)
        {
            handstatus = HandsStatus.Update;
            handpoint.Enqueue(e.Position);
        }
        public void button2_Click(object sender, EventArgs e)
        {
            DialogResult result = MessageBox.Show("Do you want to quit?", "Confirm",     MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
            if (result == DialogResult.OK)
            {
                try
                {
                    run = false;
                    if (thread != null)
                        thread.Join();
                    this.Close();
                }
                catch (Exception error)
                {
                    MessageBox.Show(error.Message);
                 }
            }
        }

        public void CallThread()
        {
            try
            {
                while (run)
                {
                    Data();
                    pictureBox1.Invalidate();
                    pictureBox2.Invalidate();

                }
            }
            catch (Exception error)
            {
                MessageBox.Show(error.Message);
            }
        }

        public unsafe void Data()
        {
            context.WaitAndUpdateAll();
            ImageMetaData imd = image.GetMetaData();
            lock (this)
            {
                Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
                BitmapData data = bitmap.LockBits(rect, ImageLockMode.WriteOnly,     System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                byte* dstp = (byte*)data.Scan0.ToPointer();
                byte* imstp = (byte*)image.ImageMapPtr.ToPointer();
                for (int i = 0; i < imd.DataSize; i += 3, dstp += 3, imstp += 3)
                {
                    dstp[0] = imstp[2];
                    dstp[1] = imstp[1];
                    dstp[2] = imstp[0];
                }
                bitmap.UnlockBits(data);
                if (handpoint.Count != 0)
                {
                    Point3D start =     depth.ConvertRealWorldToProjective(handpoint.Peek());
                    foreach (Point3D hpoint in handpoint)
                    {
                        Point3D pt = depth.ConvertRealWorldToProjective(hpoint);
                        HandPosition(start);
                        start = pt;
                    }
                }
                string mess = "Gesture: RaiseHand" + " ,Status:" + gesstatus.ToString()     + "\n" + "Hand: " + handstatus.ToString();
                PicDraw(bitmap, mess);
            }
        }

        public void HandPosition(Point3D pt)
        {
            try
            {
                float a,b,c;
                string handx, handy, handz;
                a=pt.X;
                b=pt.Y;
                c=pt.Z;
                handx = a.ToString();
                handy = b.ToString();
                handz = c.ToString();
                Graphics g = pictureBox2.CreateGraphics();
                g.FillEllipse(brush, a - 5, b - 5, 20, 20);
                textBox1.Text = handx;
                textBox2.Text = handy;
                textBox3.Text = handz;
                g.Dispose();
            }
            catch (Exception error)
            {
                MessageBox.Show(error.Message);
            }
        }

        public void PicDraw(Bitmap bmap, string me)
        {
            try
            {
                Graphics g;
                pictureBox1.Image = bmap;
                g = Graphics.FromImage(pictureBox1.Image);
                g.DrawString(me, font, brush, point);
                g.Dispose();
            }
            catch (Exception error)
            {
                MessageBox.Show(error.Message);
            }
        }
    }
}

这是我在Program.cs中的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;

namespace HandTracking
{
    static class Program
    {
        ........
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Form1 f1 = new Form1();
            f1.Text = "Hand Tracking";
            f1.StartPosition = FormStartPosition.CenterScreen;
            Application.Run(f1);
        }
    }
}

当我多次编译程序时,每次抛出不同的错误:未处理InvalidOperationException;跨线程操作无效:控制'textBox1'从其创建的线程以外的线程访问;对象目前在其他地方使用。   我不知道我传递参数的方式是:HandPosition(start)和PicDraw(bitmap,mess)是否正确。如果我使用HandPosition(开始)来控制机器人,会出现任何问题吗?任何人都可以告诉我我的错误并帮助我纠正程序吗?

1 个答案:

答案 0 :(得分:0)

问题是您正在尝试在UI线程以外的线程上访问WinForms控件。它是使用Thread.Start创建的主题完成的。

更好的Windows Forms技术是使用BackgroundWorker方法(如果您使用的是.NET 4,则任务并行库非常好)。使用BackgroundWorker,您可以发送线程来完成一些工作,它会提供UI线程更新,并发回您选择的任何对象。由于您是C#的新手,因此BackgroundWorker是正确的选择,因为它易于使用,如果您遇到困难,还有大量的文档。

在UI线程上,您只需获取这些更新,然后从UI线程更新WinForms控件。问题已解决。

要了解有关BackgroundWorker,Google的更多信息,或者您可以从这里开始:

http://www.codeproject.com/Articles/99143/BackgroundWorker-Class-Sample-for-Beginners