我正在學習C#編程和Kinect傳感器編程(我在C#語言和Kinect中都是新手)。我正嘗試使用Microsoft Visual C#2010 Express編寫使用Xtion Pro Live的傳感器控制機器人的應用程序。在我的主要形式中,有2個圖片框對象,2個按鈕對象,3個標籤和3個文本框對象。兩個圖片框對象(pictureBox1)之一是顯示RGB相機。另一個pictureBox2)將模擬2D(x和y座標)圖形中的手位置。兩個按鈕(按鈕1)之一是初始化Xtion Pro Live,並在picturebox1上顯示RGB攝像頭,並在picturebox2上模擬手部位置。另一個(按鈕2)是退出程序。三個標籤label1,label2,label3和三個文本框,textbox1,textbox2,textbox3用於顯示手的3個座標。用Xtion pro模擬手位置
這是我在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(start)來控制機器人,會出現任何問題。任何人都可以告訴我我的錯誤,並幫助我糾正這個計劃嗎?
闡述了一下,你會從你按一下按鈕處理程序中實例化一個BackgroundWorker,給它一個方法,它執行並定義一些其他在後臺工作完成時調用的方法,以及何時有進度報告。然後,在您的CallThread,Data,HandPosition,PicDraw和其他在該線程上運行的方法中,只需將進度更新發送到BackgroundWorker,然後在您定義的回調方法中處理它。確保從新線程上運行的方法中獲取對WinForms控件的所有引用。 –
onemancat,非常感謝您的幫助。我將更多地瞭解BackgroundWorker。 –
不客氣。你能否以我的解答作爲答案的好意?這是讓人們想盡全力回答問題的一件事。 –