前一段时间研究了下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();
}