Exemple #1
0
        public override ProcessingBlock GetFilter()
        {
            var filter = new DecimationFilter();

            filter.Options[Option.FilterMagnitude].Value = FilterMagnitude;
            return(filter);
        }
 public void Init()
 {
     _pb          = new DecimationFilter();
     filterMag    = _pb.Options[Option.FilterMagnitude];
     streamFilter = _pb.Options[Option.StreamFilter];
     formatFilter = _pb.Options[Option.StreamFormatFilter];
 }
        private void SetupProcessingBlock(Pipeline pipeline, Colorizer colorizer, DecimationFilter decimate, SpatialFilter spatial, TemporalFilter temp, HoleFillingFilter holeFill, ThresholdFilter threshold)
        {
            // Setup / start frame processing
            processingBlock = new CustomProcessingBlock((f, src) =>
            {
                // We create a FrameReleaser object that would track
                // all newly allocated .NET frames, and ensure deterministic finalization
                // at the end of scope.
                using (var releaser = new FramesReleaser())
                {
                    using (var frames = pipeline.WaitForFrames().DisposeWith(releaser))
                    {
                        var processedFrames = frames
                                              .ApplyFilter(decimate).DisposeWith(releaser)
                                              .ApplyFilter(spatial).DisposeWith(releaser)
                                              .ApplyFilter(temp).DisposeWith(releaser)
                                              .ApplyFilter(holeFill).DisposeWith(releaser)
                                              .ApplyFilter(colorizer).DisposeWith(releaser)
                                              .ApplyFilter(threshold).DisposeWith(releaser);

                        // Send it to the next processing stage
                        src.FrameReady(processedFrames);
                    }
                }
            });
        }
        private void SetupFilters(out DecimationFilter decimate, out SpatialFilter spatial, out ThresholdFilter threshold)
        {
            // Colorizer is used to visualize depth data
            colorizer = new Colorizer();
            // Decimation filter reduces the amount of data (while preserving best samples)
            decimate = new DecimationFilter();
            decimate.Options[Option.FilterMagnitude].Value = 1.0F;//change scall

            // Define spatial filter (edge-preserving)
            spatial = new SpatialFilter();
            spatial.Options[Option.HolesFill].Value         = 1.0F; //change resolution on the edge of image
            spatial.Options[Option.FilterMagnitude].Value   = 5.0F;
            spatial.Options[Option.FilterSmoothAlpha].Value = 1.0F;
            spatial.Options[Option.FilterSmoothDelta].Value = 50.0F;



            // Aline color to depth

            //align_to = new Align(Stream.Depth);

            //try to define depth max
            threshold = new ThresholdFilter();
            threshold.Options[Option.MinDistance].Value = 0;
            threshold.Options[Option.MaxDistance].Value = 1;
        }
        private void SetupFilters(out DecimationFilter decimate, out SpatialFilter spatial, out TemporalFilter temp, out HoleFillingFilter holeFill, out ThresholdFilter threshold)
        {
            // Colorizer is used to visualize depth data
            colorizer = new Colorizer();
            // Decimation filter reduces the amount of data (while preserving best samples)
            decimate = new DecimationFilter();
            decimate.Options[Option.FilterMagnitude].Value = 1.0F;//change scall

            // Define spatial filter (edge-preserving)
            spatial = new SpatialFilter();
            // Enable hole-filling
            // Hole filling is an agressive heuristic and it gets the depth wrong many times
            // However, this demo is not built to handle holes
            // (the shortest-path will always prefer to "cut" through the holes since they have zero 3D distance)
            spatial.Options[Option.HolesFill].Value         = 1.0F; //change resolution on the edge of image
            spatial.Options[Option.FilterMagnitude].Value   = 5.0F;
            spatial.Options[Option.FilterSmoothAlpha].Value = 1.0F;
            spatial.Options[Option.FilterSmoothDelta].Value = 50.0F;

            // Define temporal filter
            temp = new TemporalFilter();

            // Define holefill filter
            holeFill = new HoleFillingFilter();

            // Aline color to depth

            //align_to = new Align(Stream.Depth);

            //try to define depth max
            threshold = new ThresholdFilter();
            threshold.Options[Option.MinDistance].Value = 0;
            threshold.Options[Option.MaxDistance].Value = 1;
        }
Exemple #6
0
    protected override void OnStopStreaming()
    {
        if (aligner != null)
        {
            aligner.Dispose();
            aligner = null;
        }

        if (decimationFilter != null)
        {
            decimationFilter.Dispose();
            decimationFilter = null;
        }

        if (spatialFilter != null)
        {
            spatialFilter.Dispose();
            spatialFilter = null;
        }

        if (temporalFilter != null)
        {
            temporalFilter.Dispose();
            temporalFilter = null;
        }
    }
 void OnDisable()
 {
     if (_pb != null)
     {
         _pb.Dispose();
         _pb = null;
     }
 }
Exemple #8
0
    private void InitializePostProcessingFilter()
    {
        decimationFilter = new DecimationFilter();
        spatialFilter    = new SpatialFilter();
        temporalFilter   = new TemporalFilter();

        // Set some reasonable defaults for now
        spatialFilter.Options[Option.HolesFill].Value         = 1;
        spatialFilter.Options[Option.FilterMagnitude].Value   = 3.0f;
        spatialFilter.Options[Option.FilterSmoothAlpha].Value = 0.5f;
        spatialFilter.Options[Option.FilterSmoothDelta].Value = 18.0f;

        temporalFilter.Options[Option.HolesFill].Value         = 2;
        temporalFilter.Options[Option.FilterSmoothAlpha].Value = 0.6f;
        temporalFilter.Options[Option.FilterSmoothDelta].Value = 30.0f;
    }
Exemple #9
0
        /// <inheritdoc/>
        public override ProcessingBlock Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            //Note: Maybe we should add checks for each read.

            _ = reader.Read();                         // Read start object
            _ = reader.GetString();                    // Read "Name"
            _ = reader.Read();                         // Read the ':'
            var             name = reader.GetString(); // Read the name
            ProcessingBlock block;

            switch (name)
            {
            case "Decimation Filter":
                block = new DecimationFilter();
                _     = reader.Read();      // Read the ','
                _     = reader.GetString(); // Read "FilterMagnitude"
                _     = reader.Read();      // Read the ':'
                block.Options[Option.FilterMagnitude].Value = reader.GetSingle();
                _ = reader.Read();          // Read end object
                break;

            case "Spatial Filter":
                block = new SpatialFilter();
                _     = reader.Read();      // Read the ','
                _     = reader.GetString(); // Read "FilterMagnitude"
                _     = reader.Read();      // Read the ':'
                block.Options[Option.FilterMagnitude].Value = reader.GetSingle();
                _ = reader.Read();          // Read the ','
                _ = reader.GetString();     // Read "FilterSmoothAlpha"
                _ = reader.Read();          // Read the ':'
                block.Options[Option.FilterSmoothAlpha].Value = reader.GetSingle();
                _ = reader.Read();          // Read the ','
                _ = reader.GetString();     // Read "FilterSmoothDelta"
                _ = reader.Read();          // Read the ':'
                block.Options[Option.FilterSmoothDelta].Value = reader.GetSingle();
                _ = reader.Read();          // Read end object
                break;

            case "Temporal Filter":
                block = new TemporalFilter();
                _     = reader.Read();      // Read the ','
                _     = reader.GetString(); // Read "FilterSmoothAlpha"
                _     = reader.Read();      // Read the ':'
                block.Options[Option.FilterSmoothAlpha].Value = reader.GetSingle();
                _ = reader.Read();          // Read the ','
                _ = reader.GetString();     // Read "FilterSmoothDelta"
                _ = reader.Read();          // Read the ':'
                block.Options[Option.FilterSmoothDelta].Value = reader.GetSingle();
                _ = reader.Read();          // Read end object
                break;

            case "Hole Filling Filter":
                block = new HoleFillingFilter();
                _     = reader.Read();      // Read the ','
                _     = reader.GetString(); // Read "HolesFill"
                _     = reader.Read();      // Read the ':'
                block.Options[Option.HolesFill].Value = reader.GetSingle();
                _ = reader.Read();          // Read end object
                break;

            case "Threshold Filter":
                block = new ThresholdFilter();
                _     = reader.Read();      // Read the ','
                _     = reader.GetString(); // Read "MinDistance"
                _     = reader.Read();      // Read the ':'
                block.Options[Option.MinDistance].Value = reader.GetSingle();
                _ = reader.Read();          // Read the ','
                _ = reader.GetString();     // Read "MaxDistance"
                _ = reader.Read();          // Read the ':'
                block.Options[Option.MaxDistance].Value = reader.GetSingle();
                _ = reader.Read();          // Read end object
                break;

            default:
                throw new NotSupportedException($"The filter {name} is not supported in this converter");
            }
            return(block);
        }
Exemple #10
0
        private void RunThread(CancellationToken token)
        {
            Intel.RealSense.PointCloud pc = new Intel.RealSense.PointCloud();

            DecimationFilter dec_filter  = new DecimationFilter();
            SpatialFilter    spat_filter = new SpatialFilter();
            TemporalFilter   temp_filter = new TemporalFilter();

            dec_filter.Options[Option.FilterMagnitude].Value = DecimationMagnitude;

            spat_filter.Options[Option.FilterMagnitude].Value   = SpatialMagnitude;
            spat_filter.Options[Option.FilterSmoothAlpha].Value = Math.Min(1.0f, (float)SpatialSmoothAlpha);
            spat_filter.Options[Option.FilterSmoothDelta].Value = (float)SpatialSmoothDelta;

            temp_filter.Options[Option.FilterSmoothAlpha].Value = Math.Min(1.0f, (float)TemporalSmoothAlpha);
            temp_filter.Options[Option.FilterSmoothDelta].Value = (float)TemporalSmoothDelta;

            List <ProcessingBlock> filters = new List <ProcessingBlock> {
                dec_filter, spat_filter, temp_filter
            };
            Align align_to_depth = new Align(Stream.Depth);

            var cfg = new Config();

            cfg.EnableStream(Stream.Depth, 640, 480);
            cfg.EnableStream(Stream.Color, 1280, 720, Format.Rgb8);

            var             pipeline = new Pipeline();
            PipelineProfile pp       = null;

            try
            {
                pp = pipeline.Start(cfg);
            }
            catch (Exception e)
            {
                RhinoApp.WriteLine("RsToolkit: " + e.Message);
                return;
            }

            while (!token.IsCancellationRequested)
            {
                try
                {
                    using (var frames = pipeline.WaitForFrames())
                    {
                        var aligned = align_to_depth.Process <FrameSet>(frames).DisposeWith(frames);
                        var color   = aligned.ColorFrame.DisposeWith(frames);

                        pc.MapTexture(color);

                        var filtered = aligned[Stream.Depth].DisposeWith(frames);

                        foreach (var filter in filters)
                        {
                            filtered = filter.Process(filtered).DisposeWith(frames);
                        }

                        Points points = pc.Process <Points>(filtered);

                        var vertices   = new Point3f[points.Count];
                        var tex_coords = new Point2f[points.Count];

                        points.CopyVertices <Point3f>(vertices);
                        points.CopyTextureCoords <Point2f>(tex_coords);

                        Debug.Assert(vertices.Length == tex_coords.Length);

                        // ======== CULL INVALID POINTS ========

                        if (true)
                        {
                            var flags    = new bool[vertices.Length];
                            int new_size = 0;
                            for (int i = 0; i < vertices.Length; ++i)
                            {
                                if (vertices[i].Z > 0.1)
                                {
                                    flags[i] = true;
                                    new_size++;
                                }
                            }

                            var new_vertices   = new Point3f[new_size];
                            var new_tex_coords = new Point2f[new_size];

                            for (int i = 0, j = 0; i < vertices.Length; ++i)
                            {
                                if (flags[i])
                                {
                                    new_vertices[j]   = vertices[i];
                                    new_tex_coords[j] = tex_coords[i];
                                    ++j;
                                }
                            }

                            vertices   = new_vertices;
                            tex_coords = new_tex_coords;
                        }

                        // ======== TRANSFORM ========

                        if (m_xform.IsValid)
                        {
                            Parallel.For(0, vertices.Length - 1, (i) =>
                            {
                                vertices[i].Transform(m_xform);
                            });
                        }

                        // ======== CLIP TO BOX ========

                        if (m_clipping_box.IsValid &&
                            m_clipping_box.X.Length > 0 &&
                            m_clipping_box.Y.Length > 0 &&
                            m_clipping_box.Z.Length > 0)
                        {
                            Point3d box_centre = m_clipping_box.Plane.Origin;
                            double  minx = m_clipping_box.X.Min + box_centre.X, maxx = m_clipping_box.X.Max + box_centre.X;
                            double  miny = m_clipping_box.Y.Min + box_centre.Y, maxy = m_clipping_box.Y.Max + box_centre.Y;
                            double  minz = m_clipping_box.Z.Min + box_centre.Z, maxz = m_clipping_box.Z.Max + box_centre.Z;

                            var flags    = new bool[vertices.Length];
                            int new_size = 0;
                            for (int i = 0; i < vertices.Length; ++i)
                            {
                                if (
                                    vertices[i].X <maxx && vertices[i].X> minx &&
                                    vertices[i].Y <maxy && vertices[i].Y> miny &&
                                    vertices[i].Z <maxz && vertices[i].Z> minz
                                    )
                                {
                                    flags[i] = true;
                                    new_size++;
                                }
                            }

                            var new_vertices   = new Point3f[new_size];
                            var new_tex_coords = new Point2f[new_size];

                            for (int i = 0, j = 0; i < vertices.Length; ++i)
                            {
                                if (flags[i])
                                {
                                    new_vertices[j]   = vertices[i];
                                    new_tex_coords[j] = tex_coords[i];
                                    ++j;
                                }
                            }

                            vertices   = new_vertices;
                            tex_coords = new_tex_coords;
                        }

                        Debug.Assert(vertices.Length == tex_coords.Length);

                        var point_colors = GetPointColors(color, tex_coords);

                        RPointCloud new_pointcloud = new RPointCloud();
                        new_pointcloud.AddRange(vertices.Select(x => new Point3d(x)), point_colors);

                        lock (m_pointcloud)
                            m_pointcloud = new_pointcloud;
                    }
                }
                catch (Exception e)
                {
                    RhinoApp.WriteLine("RsToolkit: " + e.Message);
                    m_is_on = false;
                    break;
                }
            }

            RhinoApp.WriteLine("RsToolkit: Task cancelled.");

            if (pipeline != null)
            {
                pipeline.Stop();
            }
        }
Exemple #11
0
        private Vector4[] CreateFileData(out float minx, out float miny, out float minz, out float maxx, out float maxy, out float maxz)
        {
            //string file = "../../test/data/1.2-with-color.las";
            string file = "../../test/data/hobu.las";

            Vector4 red   = new Vector4(1, 0, 0, 1);
            Vector4 green = new Vector4(0, 1, 0, 1);
            Vector4 blue  = new Vector4(0, 0, 1, 1);

            List <Vector4> points = new List <Vector4>();

            istream istr = Utils.openFile(file);

            m_reader = new LiblasReader(istr);

            Stage stage = m_reader;
            {
                int np = (int)m_reader.getNumPoints();
                if (np > 100000)
                {
                    int step = np / 100000;
                    m_filter = new DecimationFilter(m_reader, step);
                    stage    = m_filter;
                }
            }

            Header        header = stage.getHeader();
            Bounds_double bounds = header.getBounds();

            minx = (float)bounds.getMinimum(0);
            miny = (float)bounds.getMinimum(1);
            minz = (float)bounds.getMinimum(2);
            maxx = (float)bounds.getMaximum(0);
            maxy = (float)bounds.getMaximum(1);
            maxz = (float)bounds.getMaximum(2);

            // 1.2-with-color
            //minx 635619.9f
            //miny 848899.7f
            //minz 406.59f
            //maxx 638982.563
            //maxy 853535.438
            //maxz 586.38

            ulong numPoints = stage.getNumPoints();
            //numPoints = Math.Min(numPoints, 100000);

            Schema       schema = stage.getHeader().getSchema();
            SchemaLayout layout = new SchemaLayout(schema);

            PointData data = new PointData(layout, (uint)numPoints);

            uint numRead = stage.read(data);

            uint offsetX  = (uint)schema.getDimensionIndex(Dimension.Field.Field_X);
            uint offsetY  = (uint)schema.getDimensionIndex(Dimension.Field.Field_Y);
            uint offsetZ  = (uint)schema.getDimensionIndex(Dimension.Field.Field_Z);
            uint offsetR  = (uint)schema.getDimensionIndex(Dimension.Field.Field_Red);
            uint offsetG  = (uint)schema.getDimensionIndex(Dimension.Field.Field_Green);
            uint offsetBG = (uint)schema.getDimensionIndex(Dimension.Field.Field_Blue);

            for (uint index = 0; index < numRead; index++)
            {
                Int32 xraw = data.getField_Int32(index, offsetX);
                Int32 yraw = data.getField_Int32(index, offsetY);
                Int32 zraw = data.getField_Int32(index, offsetZ);
                float x    = (float)schema.getDimension(offsetX).getNumericValue_Int32(xraw);
                float y    = (float)schema.getDimension(offsetY).getNumericValue_Int32(yraw);
                float z    = (float)schema.getDimension(offsetZ).getNumericValue_Int32(zraw);

                if (index == 0)
                {
                    minx = maxx = x;
                    miny = maxy = y;
                    minz = maxz = z;
                }
                else
                {
                    minx = Math.Min(x, minx);
                    miny = Math.Min(y, miny);
                    minz = Math.Min(z, minz);
                    maxx = Math.Max(x, maxx);
                    maxy = Math.Max(y, maxy);
                    maxz = Math.Max(z, maxz);
                }

                UInt16 r = data.getField_UInt16(index, offsetX);
                UInt16 g = data.getField_UInt16(index, offsetY);
                UInt16 b = data.getField_UInt16(index, offsetZ);

                points.Add(new Vector4(x, y, z, 1));

                float rf = (float)r / 65535.0f;
                float gf = (float)g / 65535.0f;
                float bf = (float)b / 65535.0f;
                points.Add(new Vector4(rf, gf, bf, 1));
                //points.Add(blue);
            }

            Utils.closeFile(istr);

            return(points.ToArray());
        }
Exemple #12
0
        private CustomProcessingBlock SetupProcessingBlock(Pipeline pipeline, Colorizer colorizer, DecimationFilter decimate, SpatialFilter spatial, TemporalFilter temp, HoleFillingFilter holeFill, Align align_to)
        {
            CustomProcessingBlock processingBlock = null;

            if (showType == imgType.color)
            {
                processingBlock = new CustomProcessingBlock((f, src) =>
                {
                    using (var releaser = new FramesReleaser())
                    {
                        using (var frames = pipeline.WaitForFrames().DisposeWith(releaser))
                        {
                            var processedFrames = frames
                                                  .ApplyFilter(align_to).DisposeWith(releaser);
                            // Send it to the next processing stage
                            src.FramesReady(processedFrames);
                        }
                    }
                });
            }
            else if (showType == imgType.mix)
            {
                // Setup / start frame processing
                processingBlock = new CustomProcessingBlock((f, src) =>
                {
                    using (var releaser = new FramesReleaser())
                    {
                        using (var frames = pipeline.WaitForFrames().DisposeWith(releaser))
                        {
                            var processedFrames = frames
                                                  .ApplyFilter(align_to).DisposeWith(releaser)
                                                  .ApplyFilter(decimate).DisposeWith(releaser)
                                                  .ApplyFilter(spatial).DisposeWith(releaser)
                                                  .ApplyFilter(temp).DisposeWith(releaser)
                                                  .ApplyFilter(holeFill).DisposeWith(releaser)
                                                  .ApplyFilter(colorizer).DisposeWith(releaser);

                            // Send it to the next processing stage
                            src.FramesReady(processedFrames);
                        }
                    }
                });
            }

            return(processingBlock);
        }
        void Init()
        {
            try
            {
                #region FILTERS

                spatialFilter = new SpatialFilter();
                spatialFilter.Options[Option.FilterMagnitude].Value   = 5.0F;
                spatialFilter.Options[Option.FilterSmoothAlpha].Value = 0.25F;
                spatialFilter.Options[Option.FilterSmoothDelta].Value = 50.0F;

                decimationFilter = new DecimationFilter();
                decimationFilter.Options[Option.FilterMagnitude].Value = 2.0F;

                holeFilter = new HoleFillingFilter();

                thresholdFilter = new ThresholdFilter();
                //thresholdFilter.Options[Option.MinDistance].Value = 0.73F;
                //thresholdFilter.Options[Option.MaxDistance].Value = 0.81F;

                #endregion

                align_to  = new Align(Intel.RealSense.Stream.Depth);
                colorizer = new Colorizer();
                pipeline  = new Pipeline();

                //CONFIG SETTINGS
                var cfg = new Config();
                cfg.EnableStream(Intel.RealSense.Stream.Depth, resolutionW, resolutionH, Format.Z16, FPS); //depth resolution manuel change
                cfg.EnableStream(Intel.RealSense.Stream.Color, 640, 480, Format.Rgb8, 30);
                pipelineProfile = pipeline.Start(cfg);                                                     //stream starting with user config

                var advancedDevice = AdvancedDevice.FromDevice(pipelineProfile.Device);                    //connected device
                //read device's configuration settings from json file
                advancedDevice.JsonConfiguration = File.ReadAllText(@"CustomConfig.json");
                selectedDevice = pipelineProfile.Device;

                #region Field Of View Info

                float[] dfov, cfov, irfov;

                var        depth_stream = pipelineProfile.GetStream <VideoStreamProfile>(Intel.RealSense.Stream.Depth);
                Intrinsics depthIntr    = depth_stream.GetIntrinsics();
                dfov = depthIntr.FOV; // float[2] - horizontal and vertical field of view in degrees

                var        color_stream = pipelineProfile.GetStream <VideoStreamProfile>(Intel.RealSense.Stream.Color);
                Intrinsics colorIntr    = color_stream.GetIntrinsics();
                cfov = colorIntr.FOV; // float[2] - horizontal and vertical field of view in degrees

                var        ir_stream = pipelineProfile.GetStream <VideoStreamProfile>(Intel.RealSense.Stream.Infrared);
                Intrinsics irIntr    = ir_stream.GetIntrinsics();
                irfov = irIntr.FOV; // float[2] - horizontal and vertical field of view in degrees

                lblDepthFov.Text    = "Depth FOV : " + "H = " + Convert.ToInt32(dfov[0]).ToString() + "° , " + "V = " + Convert.ToInt32(dfov[1]).ToString() + "°";
                lblColorFov.Text    = "RGB FOV   : " + "H = " + Convert.ToInt32(cfov[0]).ToString() + "° , " + "V = " + Convert.ToInt32(cfov[1]).ToString() + "°";
                lblInfraredFov.Text = "IR FOV   : " + "H = " + Convert.ToInt32(irfov[0]).ToString() + "° , " + "V = " + Convert.ToInt32(irfov[1]).ToString() + "°";


                #endregion


                //get primary screen resolutions
                screenWidth  = Convert.ToInt32(System.Windows.SystemParameters.PrimaryScreenWidth.ToString());
                screenHeight = Convert.ToInt32(System.Windows.SystemParameters.PrimaryScreenHeight.ToString());

                //camera started working. transfer image to interface
                SetupWindow(pipelineProfile, out updateDepth, out updateColor, out updateIR1, out updateIR2);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
Exemple #14
0
        private Vector4[] CreateFileData(out float minx, out float miny, out float minz, out float maxx, out float maxy, out float maxz)
        {
            //string file = "../../test/data/1.2-with-color.las";
            string file = "../../test/data/hobu.las";

            Vector4 red = new Vector4(1, 0, 0, 1);
            Vector4 green = new Vector4(0, 1, 0, 1);
            Vector4 blue = new Vector4(0, 0, 1, 1);

            List<Vector4> points = new List<Vector4>();

            istream istr = Utils.openFile(file);
            m_reader = new LiblasReader(istr);

            Stage stage = m_reader;
            {
                int np = (int)m_reader.getNumPoints();
                if (np > 100000)
                {
                    int step = np / 100000;
                    m_filter = new DecimationFilter(m_reader, step);
                    stage = m_filter;
                }
            }

            Header header = stage.getHeader();
            Bounds_double bounds = header.getBounds();
            minx = (float)bounds.getMinimum(0);
            miny = (float)bounds.getMinimum(1);
            minz = (float)bounds.getMinimum(2);
            maxx = (float)bounds.getMaximum(0);
            maxy = (float)bounds.getMaximum(1);
            maxz = (float)bounds.getMaximum(2);

            // 1.2-with-color
            //minx 635619.9f
            //miny 848899.7f
            //minz 406.59f
            //maxx 638982.563
            //maxy 853535.438
            //maxz 586.38

            ulong numPoints = stage.getNumPoints();
            //numPoints = Math.Min(numPoints, 100000);

            Schema schema = stage.getHeader().getSchema();
            SchemaLayout layout = new SchemaLayout(schema);

            PointData data = new PointData(layout,(uint)numPoints);

            uint numRead = stage.read(data);

            uint offsetX = (uint)schema.getDimensionIndex(Dimension.Field.Field_X);
            uint offsetY = (uint)schema.getDimensionIndex(Dimension.Field.Field_Y);
            uint offsetZ = (uint)schema.getDimensionIndex(Dimension.Field.Field_Z);
            uint offsetR = (uint)schema.getDimensionIndex(Dimension.Field.Field_Red);
            uint offsetG = (uint)schema.getDimensionIndex(Dimension.Field.Field_Green);
            uint offsetBG = (uint)schema.getDimensionIndex(Dimension.Field.Field_Blue);

            for (uint index=0; index<numRead; index++)
            {
                Int32 xraw = data.getField_Int32(index, offsetX);
                Int32 yraw = data.getField_Int32(index, offsetY);
                Int32 zraw = data.getField_Int32(index, offsetZ);
                float x = (float)schema.getDimension(offsetX).getNumericValue_Int32(xraw);
                float y = (float)schema.getDimension(offsetY).getNumericValue_Int32(yraw);
                float z = (float)schema.getDimension(offsetZ).getNumericValue_Int32(zraw);

                if (index == 0)
                {
                    minx = maxx = x;
                    miny = maxy = y;
                    minz = maxz = z;
                }
                else
                {
                    minx = Math.Min(x, minx);
                    miny = Math.Min(y, miny);
                    minz = Math.Min(z, minz);
                    maxx = Math.Max(x, maxx);
                    maxy = Math.Max(y, maxy);
                    maxz = Math.Max(z, maxz);
                }

                UInt16 r = data.getField_UInt16(index, offsetX);
                UInt16 g = data.getField_UInt16(index, offsetY);
                UInt16 b = data.getField_UInt16(index, offsetZ);

                points.Add(new Vector4(x, y, z, 1));

                float rf = (float)r / 65535.0f;
                float gf = (float)g / 65535.0f;
                float bf = (float)b / 65535.0f;
                points.Add(new Vector4(rf, gf, bf, 1));
                //points.Add(blue);
            }

            Utils.closeFile(istr);

            return points.ToArray();
        }