C# winform界面显示3D点云图像(halcon+VTK)

        前一段时间研究了下halcon里的3d算法,想着把3d图像显示在C#编写的软件界面上,试了下halcon的控件,没成功。后来学习了一点VTK的知识,实现了3d图像的显示,可旋转,平移,缩放观察,当然也能按照自己喜欢的风格进行渲染。

 

具体实现步骤

 在VS里,工具->NuGet包管理器->管理解决方案的NuGet程序包,搜索Activiz  安装上去,工具箱多了个RenderWindowControl控件,这个控件用来显示3d图像的。

我在halcon里处理完点云数据,halcon里的3d模型是hv_ObjectModel3D,在此模型里获取各个点的时候,可以顺带把各个点的渲染参数也加上,获取的点转换的vtk里的数据格式

代码

static vtkPoints h2v_cloud(HTuple hv_ObjectModel3D,out vtkUnsignedCharArray colors_rgb)
        {
            HTuple hv_x = new HTuple();
            HTuple hv_y = new HTuple();
            HTuple hv_z = new HTuple();
            HTuple hv_num = new HTuple();

            HOperatorSet.GetObjectModel3dParams(hv_ObjectModel3D, "point_coord_x", out hv_x);
            HOperatorSet.GetObjectModel3dParams(hv_ObjectModel3D, "point_coord_y", out hv_y);
            HOperatorSet.GetObjectModel3dParams(hv_ObjectModel3D, "point_coord_z", out hv_z);
            HOperatorSet.GetObjectModel3dParams(hv_ObjectModel3D, "num_points", out hv_num);

            double x_mid=(hv_x.TupleMax().D+hv_x.TupleMin().D)/2;
            double y_mid=(hv_y.TupleMax().D+hv_y.TupleMin().D)/2;
            double z_mid = (hv_z.TupleMax().D + hv_z.TupleMin().D) / 2;


            int num = hv_num[0].I;
            vtkPoints points = new vtkPoints();

            for (int i = 1; i < num; i++)
            {
                points.InsertPoint(i, hv_x.DArr[i]-x_mid, hv_y.DArr[i]-y_mid, hv_z.DArr[i]-z_mid);
            }

            colors_rgb = vtkUnsignedCharArray.New();
            colors_rgb.SetNumberOfComponents(3);
            double zMax = hv_z.TupleMax().D;
            double zMin = hv_z.TupleMin().D;
            double z=zMax - zMin;
            double z_median = z * 1.0 / 2;
            double r = 0, g = 0, b = 0;
            for(int i = 0; i < num;i++)
            {
                if (hv_z.DArr[i]-zMin>z_median)
                {
                    r = 255 * ((hv_z.DArr[i] - zMin - z_median) / z_median);
                    g= 255 * (1-((hv_z.DArr[i] - zMin - z_median) / z_median));
                    b = 0;
                    colors_rgb.InsertNextTuple3(r, g, b);
                }
                else
                {
                    r = 0;
                    g = 255 * ((hv_z.DArr[i] - zMin - z_median) / z_median);
                    b = 255 * (1 - ((hv_z.DArr[i] - zMin - z_median) / z_median));
                    colors_rgb.InsertNextTuple3(r, g, b);
                }
            }

            return points;
        }

显示在控件上的代码

public void show_cloud(vtkPoints points, vtkUnsignedCharArray colors_rgb, double r = 1.0, double g = 1.0, double b = 1.0, float size = 4f)
        {
            m_points = null;
            m_points = points;

            vtkPolyData polydata = vtkPolyData.New();
            polydata.SetPoints(points);


             设置点云的渲染标量
            polydata.GetPointData().SetScalars(colors_rgb);

            vtkVertexGlyphFilter glyphFilter = vtkVertexGlyphFilter.New();
            glyphFilter.SetInputConnection(polydata.GetProducerPort());

            vtkPolyDataMapper mapper = vtkPolyDataMapper.New();
            mapper.SetInputConnection(glyphFilter.GetOutputPort());


            // 开启颜色渲染
            mapper.ScalarVisibilityOn();

            // 设置渲染范围
            mapper.SetScalarRange(0, 500);


            vtkActor actor = vtkActor.New();
            actor.SetMapper(mapper);
            //actor.GetProperty().SetPointSize(size);
            //actor.GetProperty().SetColor(r, g, b);

            //vtkScalarBarActor scalarBar = vtkScalarBarActor.New();
            //scalarBar.SetLookupTable(mapper.GetLookupTable());
            //scalarBar.SetTitle("Point Cloud");
            //scalarBar.SetHeight(0.7);
            //scalarBar.SetWidth(0.1);
            //scalarBar.SetNumberOfLabels(10);
            //scalarBar.GetLabelTextProperty().SetFontSize(4);
            vtkRenderer render = renderWindowControl1.RenderWindow.GetRenderers().GetFirstRenderer();

             清空点云
            for (int i = 0; i < render.GetActors().GetNumberOfItems(); i++)
            {
                var item = render.GetActors().GetItemAsObject(i);
                render.RemoveActor((vtkActor)item);
                item.Dispose();
            }

            render.AddActor(actor);
            //render.AddActor(scalarBar);
            render.SetViewport(0.0, 0.0, 1, 1);
            render.ResetCamera();
            this.Refresh();
        }

 

 

  • 6
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
### 回答1: 在WinForm显示动态点云可以通过使用WPF来实现。WPF(Windows Presentation Foundation)是一种基于 .NET Framework 的图形显示引擎,可以用于构建富客户端应用程序。以下是一种实现方式: 1. 创建一个新的WPF User Control,并将其嵌入到WinForm中。将该User Control命名为PointCloudViewer。 2. 在PointCloudViewer中,使用WPF的Canvas控件来承载点云数据。Canvas是WPF中用于显示图形对象的面板控件。 3. 在PointCloudViewer中创建一个方法,例如UpdatePointCloud,用于更新点云数据。 4. 在UpdatePointCloud方法中,根据传入的点云数据,使用WPF的Ellipse控件来绘制每个点。可以根据点的属性,如位置、颜色等,在画布上绘制相应的椭圆。 5. 在WinForm中,添加一个按钮或其他交互控件,用于触发更新点云数据的操作。 6. 在按钮的Click事件中调用PointCloudViewer的UpdatePointCloud方法,并传入新的点云数据。这样就可以实现动态更新点云的效果。 使用WPF来显示动态点云的好处是可以更好地利用硬件加速和图形渲染功能,提高显示性能和交互体验。同时,由于WPF与WinForm可以很好地集成,可以方便地将其嵌入到现有的WinForm应用程序中。 ### 回答2: 在Winform显示动态点云,可以使用OpenGL来实现。下面是一种可能的实现方式: 1. 首先,在Winform中添加一个PictureBox控件,用于显示OpenGL渲染的图像。 2. 创建一个继承自OpenGLControl的自定义控件,并在其中重写OnPaint方法。在OnPaint方法中,利用OpenGL的API绘制点云。 3. 在Winform的代码中,实例化上述自定义控件,并添加到PictureBox中。 4. 给点云数据绑定一个定时器,通过定时器的Tick事件来更新点云数据。 5. 在Tick事件中,更新点云数据,然后调用自定义控件的Invalidate方法,强制刷新控件,使新的点云数据得以渲染。 6. 在自定义控件的OnPaint方法中,根据点云数据,使用OpenGL的API来渲染点云。 具体实现的代码如下: ``` csharp // 自定义OpenGL控件 public class MyOpenGLControl: OpenGLControl { private float[] pointCloudData; // 点云数据 protected override void OnPaint(PaintEventArgs e) { OpenGL gl = this.OpenGL; gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT); gl.LoadIdentity(); // 绘制点云 if(pointCloudData != null) { gl.Begin(OpenGL.GL_POINTS); for (int i = 0; i < pointCloudData.Length; i += 3) { gl.Color(1.0f, 1.0f, 1.0f); // 设置点云的颜色 gl.Vertex(pointCloudData[i], pointCloudData[i + 1], pointCloudData[i + 2]); } gl.End(); } gl.Flush(); } public void UpdatePointCloudData(float[] data) { pointCloudData = data; } } // Winform窗口 public partial class Form1 : Form { private MyOpenGLControl myOpenGLControl; private Timer timer; public Form1() { InitializeComponent(); // 初始化自定义OpenGL控件 myOpenGLControl = new MyOpenGLControl(); myOpenGLControl.Dock = DockStyle.Fill; pictureBox1.Controls.Add(myOpenGLControl); // 初始化定时器 timer = new Timer(); timer.Interval = 100; // 设置刷新间隔,单位为毫秒 timer.Tick += Timer_Tick; } private void Timer_Tick(object sender, EventArgs e) { // 更新点云数据 float[] newData = // 获取新的点云数据 myOpenGLControl.UpdatePointCloudData(newData); myOpenGLControl.Invalidate(); // 立即刷新OpenGL控件 } private void button1_Click(object sender, EventArgs e) { // 启动定时器 timer.Start(); } private void button2_Click(object sender, EventArgs e) { // 停止定时器 timer.Stop(); } } ``` 以上是一种使用OpenGL在Winform显示动态点云的实现方式,通过定时器不断更新点云数据,并利用OpenGL的API进行渲染,从而实现动态显示的效果。具体的实现可能会因需求而有所不同,在实际开发中需进一步调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值