0

I am studying C# Programming and Kinect sensors programming (I am quite a newbie in both C# language and Kinect). I am trying to use Microsoft Visual C# 2010 Express to write applications using sensors of Xtion Pro Live to control robots. In my main form, there are 2 picturebox objects, 2 button object, 3 label and 3 textbox objects. One of the two picturebox objects (pictureBox1) is to display the RGB camera. The other one pictureBox2) is to simulate the hand positions in 2D (x and y coordinates) graphics. One of the two buttons (button1) is to initialize Xtion Pro Live and to show RGB camera on picturebox1, and to simulate hand positions on picturebox2. The other one (button2) is to exit the program. The three labels, label1, label2, label3, and the three textboxes, textbox1, textbox2, textbox3 are used to show 3 coordinates of the hand.

This is my code in 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);
            }
        }
    }
}

And this is my code in 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);
        }
    }
}

When I compile the program many times, each time different errors are thrown: InvalidOperationException not handled; Cross-thread operation not valid: Control 'textBox1' accessed from a thread other than the thread it was created on; Object is currently in use elsewhere. I don't know whether the way I pass parameters at: HandPosition(start) and PicDraw(bitmap, mess) were correct. Any problem will come out if I use HandPosition(start) to control a robot? Can anybody show me my mistakes and help me correct the progam?

4

1 回答 1

0

问题是您试图在 UI 线程以外的线程上访问 WinForms 控件。它是从您正在创建的线程中完成的Thread.Start

对于 Windows 窗体,一种更好的技术是使用 BackgroundWorker 方法(如果您使用的是 .NET 4,Task Parallel Library 非常好)。使用 BackgroundWorker,您可以发送线程去做一些工作,它会更新 UI 线程,发送回您选择的任何对象。由于您是 C# 的新手,BackgroundWorker 是正确的选择,因为它易于使用,并且如果您遇到困难,它上面有大量的文档。

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

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

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

于 2013-02-01T23:17:53.643 回答