1
votes

So I'm trying to programe a kinect sensor with the SDK. Here is the code.

public partial class MainWindow : Window
{
    bool mirror=false;
    bool displayActive = true;
    int redOffset;
    int greenOffset;
    int blueOffset;
    WriteableBitmap colorImageBitmap = null;
    KinectSensor myKinect;
    public MainWindow()
    {
        InitializeComponent();
    }

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {

        kinectVideo.Source = colorImageBitmap;
        myKinect = KinectSensor.KinectSensors[0];
        if (KinectSensor.KinectSensors.Count == 0)
        {
            MessageBox.Show("No Kinects detected", "Camera Viewer");
            Application.Current.Shutdown();
        }
        myKinect.ColorStream.Enable();
        myKinect.Start();

        Thread updateVideoThread;
        updateVideoThread = new Thread(new ThreadStart(videoDisplay));
        updateVideoThread.Start();

    }



    void videoDisplay()
    {
        while (displayActive)
        {
            using (ColorImageFrame colorFrame = myKinect.ColorStream.OpenNextFrame(10))
            {
                if (colorFrame == null) continue;

                byte[] colorData = new byte[colorFrame.PixelDataLength];

                colorFrame.CopyPixelDataTo(colorData);


                //----------------------------Methodos 2 for image color adjustment------------------------------------------------------------------------------------

                updateColor(colorData);

                //----------------------------Methodos 1 for mirror------------------------------------------------------------------------------------

                if (mirror) { reflectImage(colorData, colorFrame.Width, colorFrame.Height); }

                //----------------------------Methodos 2 for update image------------------------------------------------------------------------------------

                kinectVideo.Source = colorImageBitmap;

                if (colorImageBitmap == null)
                {
                    this.colorImageBitmap = new WriteableBitmap(colorFrame.Width,
                                                                    colorFrame.Height,
                                                                    96, // DpiX
                                                                    96, // DpiY
                                                                    PixelFormats.Bgr32,
                                                                    null);
                }

                this.colorImageBitmap.WritePixels(new Int32Rect(0, 0, colorFrame.Width, colorFrame.Height),
                                                                colorData, // video data
                                                                colorFrame.Width * colorFrame.BytesPerPixel, // stride,
                                                                 0 // offset into the array - start at 0
                                                                 );

            }
        }
    }

and in the line "kinectVideo.Source = colorImageBitmap;" is gives me an exception that says "The calling thread cannot access this object because a different thread owns it.". I dont understand why. I am new in programming with C# and Visual Studio. I have only one Thread so I don't know why the exception. Any help?

2
You have 2 threads. The main thread that the application is running in and the thread you create to run videoDisplay. Where does the kinectVideo object come from? - Nanhydrin
I understand. So if I got it correctly, when I made the thread for videoDisplay, both the thread I made (updateVideoThread) and the main thread of the program try to run the method so the exception is called? The kinect object come from this line of code ---->using Microsoft.Kinect; With is more up and dint copied it here. - Jim
It's not that they're both trying to run the method, it's probably that the kinectVideo object belongs to the main thread. kinectVideo is an instance of what class and where is it created? The way it's named looks like it's a variable and I can't see any static class called kinectVideo in Microsft.Kinect. Is it an object on a form or something? - Nanhydrin
First late me say that this is a WPF project. Second this is an object on the form. More specific this is the cone in the XAML thaτ creates the object--> "<Image Name="kinectVideo" Margin="0,0,84,0" />" - Jim

2 Answers

0
votes

Ok so basically you're trying to update the UI from a thread that is not the main thread, and this never works without an invoke of some description.

Have a look at the answers on this thread, it looks to be exactly the same problem as you're having
The calling thread cannot access this object because a different thread owns it.How do i edit the image?

According to those answers you should change the code in videoDisplay() to read as follows:

...    

Action action = delegate { kinectVideo.Source = colorImageBitmap; };
kinectVideo.Dispatcher.Invoke(action);

if (colorImageBitmap == null){
...

And if that doesn't work try:

...    

colorImageBitmap.Freeze();
Action action = delegate { kinectVideo.Source = colorImageBitmap; };
kinectVideo.Dispatcher.Invoke(action);

if (colorImageBitmap == null){
...

And considering you also use the line kinectVideo.Source = colorImageBitmap; in the Window_Loaded method as well you might need to use the .Freeze() there too.

I'm not really familiar with XAML and Freeze() but since the colorImageBitmap doesn't appear to be initialized inside either of those methods it might cause other problems for you.
Using GetAsFrozen() might be a better option for you but it may well have memory implications.

0
votes

Do I found the answer to my problem. This is what I did.

1) Declared a thread

Private Backgroundworker _worker;

2) Create an instance, subscribe to the DoWork event, and start the new thread

this._worker=new BackgroundWorker();
this._worker.DoWork += Worker_DoWork;
this._worker.RunWorkerAsync();

3) Write the event handler

private void Worker_DoWork(object sender, DoWorkEventArgsn e) { ... }

4) And put this code around the place you create the bitmap and where you rewrite the bitmap.

this.ColorImageElement.Dispatcher.BeginInvoke(new Action(() => { ... }