0

私は C# プログラミングと Kinect センサー プログラミングを勉強しています (私は C# 言語と Kinect の両方の初心者です)。Microsoft Visual C# 2010 Express を使用して、Xtion Pro Live のセンサーを使用してロボットを制御するアプリケーションを作成しようとしています。私のメイン フォームには、2 つのピクチャ ボックス オブジェクト、2 つのボタン オブジェクト、3 つのラベル オブジェクト、3 つのテキスト ボックス オブジェクトがあります。2 つのピクチャ ボックス オブジェクト (pictureBox1) の 1 つは、RGB カメラを表示するためのものです。もう 1 つの pictureBox2) は、2D (x および y 座標) グラフィックスで手の位置をシミュレートするためのものです。2 つのボタンの 1 つ (button1) は、Xtion Pro Live を初期化し、picturebox1 に RGB カメラを表示し、picturebox2 で手の位置をシミュレートします。もう 1 つ (button2) は、プログラムを終了するためのものです。3 つのラベル label1、label2、label3、および 3 つのテキスト ボックス 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);
        }
    }
}

プログラムを何度もコンパイルすると、毎回異なるエラーがスローされます。クロススレッド操作が無効です: コントロール 'textBox1' は、それが作成されたスレッド以外のスレッドからアクセスされました。オブジェクトは現在別の場所で使用されています。HandPosition(start) と PicDraw(bitmap, mess) でパラメーターを渡す方法が正しかったかどうかはわかりません。HandPosition(start)を使ってロボットを制御すると何か問題が発生しますか? 誰か私の間違いを示して、プログラムを修正するのを手伝ってくれませんか?

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 に答える