problems with multithreading in VTK with winforms

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

problems with multithreading in VTK with winforms

Neel Patel 0-0-0
Hello all. I have a couple problems trying to do multithreading with VTK using winforms. Currently I have a form with a pictureBox and a RenderControlWindow, where the pictureBox is used for streaming data while the RenderWindow is used to display images on the side. From some previous reading, I've tried to implement a solution where updates to my image are done on one thread and the rendering is done on the main form thread. The problem is that when I try to re-render the window itself doesn't change. Some code below, at least what I think might be relevant can post more if need be.

Update Thread:
            vtkImageImport imageImport = null;

            o = new Thread(() =>
            {
                byte[] myByteArray = new byte[data.Size];
                int idx = 0;

                for (int k = 0; k < D; k++)
                {
                    for (int j = 0; j < H; j++)
                    {
                        for (int i = 0; i < W; i++)
                        {
                            idx = k * W * H + j * W + i;
                            myByteArray[idx] = (byte)data.Get(idx);
                        }
                    }
                }

                // Copy byte array into VTK
                // Based on: http://stackoverflow.com/questions/31670753/use-c-sharp-byte-image-data-in-vtk
                vtkUnsignedCharArray myCharArray = vtkUnsignedCharArray.New();
                GCHandle gPointer = GCHandle.Alloc(myByteArray, GCHandleType.Pinned);

                // Import image data
                imageImport = vtkImageImport.New();
                imageImport.SetDataSpacing(1, 1, 1);
                imageImport.SetDataOrigin(0, 0, 0);
                imageImport.SetDataExtent(0, W - 1, 0, H - 1, 0, D - 1);
                imageImport.SetWholeExtent(0, W - 1, 0, H - 1, 0, D - 1);
                imageImport.SetDataScalarTypeToUnsignedChar();
                imageImport.SetNumberOfScalarComponents(1);
                imageImport.SetImportVoidPointer(gPointer.AddrOfPinnedObject());
                imageImport.Update();

                if (InvokeRequired)
                {
                    this.Invoke(new Action(() => renderInMain()));
                    Thread.Sleep(1000);

                }
            });
            o.Start();
}

Rendering Method called in main thread:
        public void renderInMain() {
            lock (_lock)
            {
                vtkRenderer renderer = renderWindowControl1.RenderWindow.GetRenderers().GetFirstRenderer();
                vtkImageActor actor = vtkImageActor.New();
                vtkMatrix4x4 resliceAxes = vtkMatrix4x4.New();
                vtkImageReslice reslice = vtkImageReslice.New();
                vtkLookupTable table = vtkLookupTable.New();

                renderer.RemoveAllViewProps();
                //renderer.Modified();
                //renderer.Render();

                // Get extent and calculate the center of the volume
                int[] extent = imageImport.GetOutput().GetWholeExtent();
                double[] spacing = imageImport.GetOutput().GetSpacing();
                double[] origin = imageImport.GetOutput().GetOrigin();
                double[] center = new double[3];
                center[0] = origin[0] + spacing[0] * 0.5 * (extent[0] + extent[1]);
                center[1] = origin[1] + spacing[1] * 0.5 * (extent[2] + extent[3]);
                center[2] = origin[2] + spacing[2] * 0.5 * (extent[4] + extent[5]);

                // Matrices for axial, coronal, sagittal, oblique view orientations
                double[] axialElements = {
                    1, 0, 0, 0,
                    0, 1, 0, 0,
                    0, 0, 1, 0,
                    0, 0, 0, 1 };

                double[] coronalElements = {
                    1, 0, 0, 0,
                    0, 0, 1, 0,
                    0,-1, 0, 0,
                    0, 0, 0, 1 };

                double[] sagittalElements = {
                    0, 0,-1, 0,
                    1, 0, 0, 0,
                    0,-1, 0, 0,
                    0, 0, 0, 1 };

                double[] obliqueElements = {
                    1, 0, 0, 0,
                    0, 0.866025, -0.5, 0,
                    0, 0.5, 0.866025, 0,
                    0, 0, 0, 1 };


                // Set the slice orientation
                GCHandle sagittalElements_ptr = GCHandle.Alloc(coronalElements, GCHandleType.Pinned);
                resliceAxes.DeepCopy(sagittalElements_ptr.AddrOfPinnedObject());
                Thread.Sleep(1000);

                // Set the point through which to slice
                resliceAxes.SetElement(0, 3, center[0]);
                resliceAxes.SetElement(1, 3, center[1]);
                resliceAxes.SetElement(2, 3, center[2]);
                resliceAxes.Modified();

                Thread.Sleep(1000);

                // Extract a slice in the desired orientation
                reslice.SetInputConnection(imageImport.GetOutputPort());
                reslice.SetOutputDimensionality(2);
                reslice.SetResliceAxes(resliceAxes);
                reslice.SetInterpolationModeToLinear();
                reslice.Modified();
                Thread.Sleep(1000);


                // Create a greyscale lookup table
                table.SetRange(0, 255); // image intensity range
                table.SetValueRange(0.0, 1); // from black to white
                table.SetSaturationRange(0.0, 0.0); // no color saturation
                table.SetRampToLinear();
                table.Build();

                // Map the image through the lookup table
                vtkImageMapToColors color = vtkImageMapToColors.New();
                color.SetLookupTable(table);
                color.SetInputConnection(reslice.GetOutputPort());


                // Display the image
                actor.SetInput(color.GetOutput());
                actor.Modified();
                Console.WriteLine("Exit");
                Thread.Sleep(1000);

                // Set up renderer



                //if (renderFlag == 1)
                //{
                renderer.ResetCamera();
                renderer.AddActor(actor);
                renderer.SetBackground(0, 0, 0);
                renderer.Modified();
                renderer.Render();
            }

        }


Another curious thing is that if I run this normally the renderWindow doesn't change, but if I run it while debugging it seems to work fine and the window changes to what it should be.

Any help or insight would be greatly appreciated. Thanks!

                                      Regards,
                                          Neel
Loading...