Halcon与Winform联合(三)

本期从某机构要了份免费代码实现读取tif点云图、变为om3点云模型、可视化与点云分割的项目
其中halcon代码如下

dev_update_off ()
dev_close_window ()
* 1、加载X,Y, z数据,缩放到米,并生成一个3D对象模型
ImagePath := 'time_of_flight/'
read_image (Image, ImagePath + 'engine_cover_xyz_01')
* 缩放图像的灰度值
* 将图像放大一个给定的倍数
scale_image (Image, Image, .001, .0)
zoom_image_factor (Image, Image, 2, 2, 'constant')
decompose3 (Image, X, Y, Z)
xyz_to_object_model_3d (X, Y, Z, ObjectModel3DID)
* 2、计算模型的网格(Delaunay三角测量)
* 为'segmentation',准备一个3D对象模型(如果要对同一操作多次使用3D对象模型,这样做会更快)
prepare_object_model_3d (ObjectModel3DID, 'segmentation', 'true', [], [])
* 
* 3、准备可视化并显示3D对象模型
create_pose (0.058, -0.165, 0.660, 345.0, 355.0, 356.0, 'Rp+T', 'gba', 'point', Pose)
* 
* Instructions for visualize_object_model_3d
Instructions[0] := 'Rotate: Left button'
Instructions[1] := 'Zoom:   Shift + left button'
Instructions[2] := 'Move:   Ctrl  + left button'
* Configuration
* 生成面阵相机初始参数,参数均为相机已知参数
* (: : 焦距, 畸变因子, Sx, Sy, Cx, Cy, 图像宽度, 图像高度 : CameraParam存储元组)
* (Sx, Sy为传感器芯片上两个相邻单元之间的水平竖直距离,也就是像素的大小,单位为m/像素;Cx, Cy为图像原点的行列坐标,单位为像素;)
gen_cam_par_area_scan_division (0.01, 0, 7e-6, 7e-6, 352, 288, 710, 576, CamParam)
GenParamName := ['color','disp_pose','alpha']
GenParamValue := ['green','false',0.8]
* 
dev_open_window (0, 0, 710, 576, 'black', WindowHandle)
set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
* 显示创建的3D模型
visualize_object_model_3d (WindowHandle, ObjectModel3DID, CamParam, Pose, GenParamName, GenParamValue, 'This scene will be segmented into single objects', [], Instructions, Pose)
* 
* 4、阈值三维对象模型
MinValue := 0.500
MaxValue := 0.670
* 对3D对象模型应用阈值
select_points_object_model_3d (ObjectModel3DID, 'point_coord_z', MinValue, MaxValue, ObjectModel3DIDReduced)
visualize_object_model_3d (WindowHandle, ObjectModel3DIDReduced, CamParam, Pose, GenParamName, GenParamValue, 'Result after thresholding at z=' + (MaxValue * 1e3)$'.3' + 'mm from the camera', [], Instructions, Pose)
* 
* Calculate the connected components and the volume and diameter
* of each of the resulting object
* 5、计算连接分量和每个结果对象的体积和直径
GenParamName[0] := 'colored'
GenParamValue[0] := 12
* 1)确定3D对象模型的连通分量 通过调节distance_3d参数,把一些噪点分离出来
* 2)计算三维物体模型相对于平面[0,0,MaxValue,0,0,0,0]的体积 Volume
* 3)计算3D对象模型的最大直径 Diameter
connection_object_model_3d (ObjectModel3DIDReduced, 'distance_3d', 0.010, ObjectModel3DIDConnections)
volume_object_model_3d_relative_to_plane (ObjectModel3DIDConnections, [0,0,MaxValue,0,0,0,0], 'signed', 'true', Volume)
max_diameter_object_model_3d (ObjectModel3DIDConnections, Diameter)
* 
* 6、显示结果
dev_open_window (0, 720, 400, 576, 'black', WindowHandle1)
set_display_font (WindowHandle1, 14, 'mono', 'true', 'false')
Indices := [0:|ObjectModel3DIDConnections| - 1]
disp_message (WindowHandle1, ['Features of the connected components:',' ',' '], 'window', 12, 12, 'white', 'false')
ResultMessage := '  #  Max. diameter    Volume'
Sequence := [0:|ObjectModel3DIDConnections| - 1]
ResultMessage := [ResultMessage,Sequence$' 3' + '     ' + (Diameter * 1e3)$'7.1f' + ' mm  ' + (Volume * 1e3)$'7.3f' + ' dm³']
disp_message (WindowHandle1, ResultMessage, 'window', 50, 12, 'white', 'false')
dev_set_window (WindowHandle)
visualize_object_model_3d (WindowHandle, ObjectModel3DIDConnections, CamParam, Pose, GenParamName, GenParamValue, 'Found ' + |ObjectModel3DIDConnections| + ' connected components', '#' + Indices, Instructions, Pose)
* 
* 7、根据组件的体积和最大直径选择组件
* 
MinVolume := 0.35e-003
MaxVolume := 1.0e-003
MinDiameter := 185.0e-003
MaxDiameter := 300.0e-003

***** 8、注意:
*     select_object_model_3d使用平面[0,0,0,0,0,0]进行体积计算!
*     因此,我们必须转换3d对象模型,以便参考平面(如前面对volume_object_model_3d_relative_to_plane的调用中定义的那样)与默认平面重合。
*
* 1)生成三维变换的齐次变换矩阵
* 2)增加平移变换
* 3)求齐次三维变换矩阵的逆
hom_mat3d_identity (HomMat3DIdentity)
hom_mat3d_translate (HomMat3DIdentity, 0, 0, -MaxValue, HomMat3DTranslation)
hom_mat3d_invert (HomMat3DTranslation, HomMat3DInvert)
affine_trans_object_model_3d (ObjectModel3DIDConnections, HomMat3DTranslation, ObjectModel3DTranslated)
* 4)为每个部分设置标签
for Index := 0 to |ObjectModel3DIDConnections| - 1 by 1
    set_object_model_3d_attrib_mod (ObjectModel3DTranslated[Index], '&Index', [], Index)
endfor
* 5)再次计算三维物体模型相对于平面[0,0,0,0,0,0,0]的体积 Volume1
* 6)从一组三维对象模型中选择三维对象模型('volume','diameter_object')
volume_object_model_3d_relative_to_plane (ObjectModel3DTranslated, [0,0,0,0,0,0,0], 'signed', 'true', Volume1)
select_object_model_3d (ObjectModel3DTranslated, ['volume','diameter_object'], 'and', [MinVolume,MinDiameter], [MaxVolume,MaxDiameter], ObjectModel3DSelected)
* 
Title := ['Parts selected by using the following features: ','       ' + (MinVolume * 1e3)$'3.1f' + ' dm³ <= volume <= ' + (MaxVolume * 1e3)$'3.1f' + ' dm³','and:   ' + (MinDiameter * 1e3)$'.1f' + ' mm <= max. diameter <= ' + (MaxDiameter * 1e3)$'.1f' + ' mm']
* 创建一个标签
Label := []
for Index := 0 to |ObjectModel3DSelected| - 1 by 1
    get_object_model_3d_params (ObjectModel3DSelected[Index], '&Index', FormerIndex)
    Label := [Label,'#' + FormerIndex]
endfor
* 
if (|ObjectModel3DSelected| > 1)
    visualize_object_model_3d (WindowHandle, ObjectModel3DSelected, CamParam, [], GenParamName, GenParamValue, Title, Label, Instructions, Pose)
else
    Message := 'No object left after using the following features: '
    Message[1] := '       ' + (MinVolume * 1e3)$'3.1f' + ' dm³ <= volume <= ' + (MaxVolume * 1e3)$'3.1f' + ' dm³'
    Message[2] := 'and:   ' + (MinDiameter * 1e3)$'.1f' + ' mm <= max. diameter <= ' + (MaxDiameter * 1e3)$'.1f' + ' mm'
    disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')
endif
* 
* Clear the 3d object models
dev_set_window (WindowHandle1)
dev_close_window ()
clear_object_model_3d ([ObjectModel3DID,ObjectModel3DIDReduced,ObjectModel3DSelected,ObjectModel3DTranslated,ObjectModel3DIDConnections])

导出程序使用的Winform代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using HalconDotNet;

namespace PointsCloudHandler
{
    public partial class Form1 : Form
    {
        private HDevelopExport export = new HDevelopExport();
        private HSmartWindowControl hwControl;
        private HWindow hWindow;
        private HObject ho_Image;
        private HTuple objectModel3D;
        private HTuple hv_ObjectModel3DIDReduced;
        private HTuple hv_TriangulatedObjectModel3D;
        private HTuple hv_GenParamValue;
        private HTuple hv_GenParamName;
        private HTuple hv_CamParam;
        private HTuple poseOut;


        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            // 创建Halcon控件
            hwControl = new HSmartWindowControl();
            // 获取halcon控件上面的窗口对象
            hWindow = hwControl.HalconWindow;
            // 设置halcon控件以填充方式置于容器中
            hwControl.Dock = DockStyle.Fill;
            // 添加控件到对应容器
            panel1.Controls.Add(hwControl);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            // 创建对话框
            var dialog = new OpenFileDialog();
            dialog.InitialDirectory = @"D:\Gerry\备课\Halcon的3D点云处理";
            dialog.Filter = "打开点云文件|*.tif";
            if (dialog.ShowDialog() == DialogResult.OK)
            {
                // 获取选择的点云文件路径
                var filePath = dialog.FileName;
                // 创建一个Halcon图像对象
                ho_Image = new HImage(filePath);
                // 把图像显示到Halcon控件的窗口上面
                hWindow.DispObj(ho_Image);
                // 图像自适应容器大小
                //hwControl.SetFullImagePart();
            }
        }
        /// <summary>
        /// 生成3D点云模型
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button2_Click(object sender, EventArgs e)
        {
            // 缩放图像灰度值
            HOperatorSet.ScaleImage(ho_Image, out ho_Image, .001, .0);
            // 放大图像到原来2呗
            HOperatorSet.ZoomImageFactor(ho_Image, out ho_Image, 2, 2, "constant");
            // 把放大图像拆分为3个通道
            HOperatorSet.Decompose3(ho_Image, out HObject x, out HObject y, out HObject z);
            // 生成3D点云模型
            HOperatorSet.XyzToObjectModel3d(x, y, z, out objectModel3D);
            // 持久化生成的3D模型
            HOperatorSet.WriteObjectModel3d(objectModel3D, "om3", "pcl.om3", new HTuple(), new HTuple());
            // 提示生成3D模型成功
            MessageBox.Show("生成3D模型OK");
        }
        /// <summary>
        /// 显示3D模型(很的企业包括开发人员都没有搞定)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button3_Click(object sender, EventArgs e)
        {
            // 创建3D模型显示位姿
            HOperatorSet.CreatePose(0.058, -0.165, 0.660, 345.0, 355.0, 356.0, "Rp+T", "gba", "point", out HTuple hv_Pose);
            // 初始化相机已经参数
            hv_CamParam = new HTuple(0.01, 0, 7e-6, 7e-6, 352, 288, 710, 576);
            // 初始化3D模型显示的颜色,是否显示坐标系,设置透明的元组
            hv_GenParamName = new HTuple("color", "disp_pose", "alpha");
            hv_GenParamValue = new HTuple("green", "false", 0.8);
            // 设置显示字体大小
            export.set_display_font(hWindow, 16, "mono", "true", "false");
            // 读取刚刚持久化的3D模型对象
            HOperatorSet.ReadObjectModel3d("pcl.om3", "m",
                new HTuple(), new HTuple(), out objectModel3D, out HTuple stats);
            // 把窗口对象推窗口栈中
            HDevWindowStack.Push(hWindow);
            // 显示3D模型
            Task.Run(() =>
            {
                export.visualize_object_model_3d(hWindow, objectModel3D, hv_CamParam,
                hv_Pose, hv_GenParamName, hv_GenParamValue, "显示3D点云模型",
                new HTuple(), new HTuple(), out poseOut);
            });

        }
        /// <summary>
        /// 点云数据切割
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button4_Click(object sender, EventArgs e)
        {
            //对3D对象模型应用阈值
            HOperatorSet.SelectPointsObjectModel3d(objectModel3D, "point_coord_z",
                0.5, 0.67, out hv_ObjectModel3DIDReduced);
            // 三角化,对其分割好的点云数据实现三维重建
            HOperatorSet.TriangulateObjectModel3d(hv_ObjectModel3DIDReduced, "greedy", new HTuple(),
                new HTuple(), out hv_TriangulatedObjectModel3D, out HTuple information);
            // 显示3D模型
            Task.Run(() =>
            {
                export.visualize_object_model_3d(hWindow, hv_TriangulatedObjectModel3D, hv_CamParam,
                poseOut, hv_GenParamName, hv_GenParamValue, "显示3D点云模型",
                new HTuple(), new HTuple(), out poseOut);
            });
        }
        /// <summary>
        /// 对象重建后的点云模型分割区域分别计算直径和体积
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button5_Click(object sender, EventArgs e)
        {
            // 通过阈值联通区域
            HOperatorSet.ConnectionObjectModel3d(hv_TriangulatedObjectModel3D, "distance_3d",
                0.01, out HTuple hv_ObjectModel3DIDConnections);
            // 设置不同连通区域显示颜色
            if (hv_GenParamName == null)
                hv_GenParamName = new HTuple();
            hv_GenParamName[0] = "colored";
            if (hv_GenParamValue == null)
                hv_GenParamValue = new HTuple();
            hv_GenParamValue[0] = 12;

            // 测试体积
            HOperatorSet.VolumeObjectModel3dRelativeToPlane(hv_ObjectModel3DIDConnections, ((((new HTuple(0)).TupleConcat(0)).TupleConcat(0.67))).TupleConcat(
              (((new HTuple(0)).TupleConcat(0)).TupleConcat(0)).TupleConcat(0)), "signed", "true", out HTuple hv_Volume);
            // 计算直径
            HOperatorSet.MaxDiameterObjectModel3d(hv_ObjectModel3DIDConnections, out HTuple hv_Diameter);
            HTuple hv_ResultMessage = "  #  Max. diameter    Volume";
            // 显示编号
            var hv_Indices = HTuple.TupleGenSequence(0, (new HTuple(hv_ObjectModel3DIDConnections.TupleLength())) - 1, 1);
            // 显示序列
            var hv_Sequence = HTuple.TupleGenSequence(0, (new HTuple(hv_ObjectModel3DIDConnections.TupleLength())) - 1, 1);
            // 显示结果
            HTuple ExpTmpLocalVar_ResultMessage = hv_ResultMessage.TupleConcat((((((hv_Sequence.TupleString(" 3")) + "     ") +
                (((hv_Diameter * 1e3)).TupleString("7.1f"))) + " mm  ") + (((hv_Volume * 1e3)).TupleString("7.3f"))) + " dm³");
            // 创建字符串构建对象
            var sb = new StringBuilder();
            for (int i = 0; i < ExpTmpLocalVar_ResultMessage.Length; i++)
            {
                sb.Append(ExpTmpLocalVar_ResultMessage[i].S + "\r\n");
            }
            textBox1.Text = sb.ToString();
            // 显示分割的后的模型
            Task.Run(() =>
            {
                export.visualize_object_model_3d(hWindow, hv_ObjectModel3DIDConnections, hv_CamParam,
                    poseOut, hv_GenParamName, hv_GenParamValue, "分割后的3D模型", "#" + hv_Indices, new HTuple(), out poseOut);
            });
        }

  
    }
}

窗体控件:一个panel,五个button,一个textbox即可,操作步骤同往期

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值