基于Halcon深度学习之分类

发布于:2025-06-04 ⋅ 阅读:(21) ⋅ 点赞:(0)
*****
***环境准备***
***系统:win7以上系统
***显卡:算力3.0以上
***显卡驱动:10.1以上版本(nvidia-smi查看指令)

***读取深度学习模型***
read_dl_model ('pretrained_dl_classifier_compact.hdl', DLModelHandle)
***获取模型中的图象张量及对应的灰度值范围
get_dl_model_param (DLModelHandle, 'image_width', ImgWidth)
get_dl_model_param (DLModelHandle, 'image_height', ImgHeight)
get_dl_model_param (DLModelHandle, 'image_num_channels', ImgChannel)
get_dl_model_param (DLModelHandle, 'image_range_min', ImgRangMin)
get_dl_model_param (DLModelHandle, 'image_range_max', ImgRangMax)


************预处理数据准备及拆分**********
classNames := ['1-2','1-3','1-4','2-4','3-5','4-7','5-6']
rawImageFolders := '../images/' + classNames
***把原图像数据转换为对应的Dataset格式***
read_dl_dataset_classification (rawImageFolders, 'last_folder', DLDataset)
***对数据集进行拆分***
trainPrecent := 60 // 用于训练的比例
validdatatPrecent := 20 // 用于测试的比例
GenSplitParam := dict{overwrite_split:'true'}
split_dl_dataset (DLDataset, trainPrecent, validdatatPrecent, GenSplitParam)
***预处理数据***
*1、创建预处理参数
** 预处理数据存储路径
processFolder := 'ProcessData'
** 定义预处理参数文件路径
dlProcessFileName := processFolder + '/dl_preprocess_param.hdict'
** 检查文件是否存在
file_exists (processFolder, FileExists)
if(not FileExists)
    make_dir (processFolder)
endif
** 创建预处理参数
create_dl_preprocess_param ('classification', ImgWidth, ImgHeight, ImgChannel, \
                            ImgRangMin, ImgRangMax, 'none', 'full_domain',\
                            [], [], [], [], DLPreprocessParam)
** 对数据进行预处理
GenParam := dict{overwrite_files:'true'}
preprocess_dl_dataset (DLDataset, processFolder, DLPreprocessParam, \
                       GenParam, DLDatasetFileName)
** 保存预处理参数文件
write_dict (DLPreprocessParam, dlProcessFileName, [], [])

************使用预处理数据对模型进行训练************
** 总周期(所有图片训练一次为一个周期)
numEpochs := 100
** 批次数(一个周期本分割的份数)
batchSize := 5
** 评估周期(每训练几个周期进行一次评估)
evluationIntervalEphochs := 2
** 学习率
learningRate := 0.001
**** 设置模型参数
set_dl_model_param(DLModelHandle, 'class_names', classNames)
set_dl_model_param(DLModelHandle, 'image_dimensions', [ImgWidth,ImgHeight,ImgChannel])
set_dl_model_param(DLModelHandle, 'learning_rate', learningRate)
set_dl_model_param (DLModelHandle, 'batch_size', batchSize)
** 设置增强参数
GenParamName := []
GenParamValue := []
** 定义参数字典,增强参数
augmentParam := dict{}
augmentParam.augmentation_percentage := 100
augmentParam.mirror := 'rc'
GenParamName := [GenParamName,'augment']
GenParamValue := [GenParamValue,augmentParam]

** 定义存储最佳模型路径和最终模型路径
augmentBest := dict{}
augmentBest.type := 'best'
augmentBest.basename := processFolder + '/model_best'
GenParamName := [GenParamName,'serialize']
GenParamValue := [GenParamValue,augmentBest]

augmentFinal := dict{}
augmentFinal.type := 'final'
augmentFinal.basename := processFolder + '/model_final'
GenParamName := [GenParamName,'serialize']
GenParamValue := [GenParamValue,augmentFinal]
** 创建训练参数及执行训练
create_dl_train_param (DLModelHandle, numEpochs, evluationIntervalEphochs, \
                       'true', 32, GenParamName, GenParamValue, TrainParam)
** 执行模型训练
train_dl_model (DLDataset, DLModelHandle, TrainParam, 0,\
                TrainResults, TrainInfos, EvaluationInfos)
** 释放资源
clear_dl_model (DLModelHandle)
** 关闭训练窗口
stop()
dev_close_window()
dev_close_window()

***********模型评估***********
** 定义评估模型文件路径
retainModelFile := processFolder + '/model_best.hdl'
** 读取训练后的模型
read_dl_model (retainModelFile, RetainDLModelHandle)
** 定义评估的指标
evaluateGenParam := ['f_score','recall','precision','absolute_confusion_matrix',\
                     'relative_confusion_matrix']
evaluateDict := dict{measures:evaluateGenParam}
** 执行模型评估
evaluate_dl_model(DLDataset, RetainDLModelHandle, 'split', 'test', \
                  evaluateDict, EvaluationResult, EvalParams)
** 显示评估结果
GenDispParam := dict{}
GenDispParam.display_mode := ['measures','pie_charts_recall','pie_charts_precision',\
                              'absolute_confusion_matrix','relative_confusion_matrix']
WindowHandleDict := dict{}
dev_display_classification_evaluation(EvaluationResult, EvalParams,\
                                      GenDispParam, WindowHandleDict)
stop()
dev_close_window_dict(WindowHandleDict)


***********模型推断***********
** 读取推断数据
list_image_files('../test_image','bmp',[],ImageFiles)
** 读取预处理参数
read_dict(dlProcessFileName,[],[],DLPreprocessParam)
** 设置显示字体大小
dev_get_window(WindowHandle)
set_display_font(WindowHandle, 26, 'mono', 'true', 'false')
** 循环检测每一张图像
for Index :=0 to |ImageFiles| -1 by 1
    ** 获取当前图像
    read_image(Image,ImageFiles[Index])
    ** 生产样本图像
    gen_dl_samples_from_images(Image, DLSampleBatch)
    ** 把推断图像处理成预处理图像数据
    preprocess_dl_samples(DLSampleBatch, DLPreprocessParam)
    **  使用模型进行推断类别
    apply_dl_model(RetainDLModelHandle, DLSampleBatch, [], DLResultBatch)
    ** 评估结果显示
    className := DLResultBatch.classification_class_names[0]
    score := DLResultBatch.classification_confidences[0]
    ** 显示图像上面
    dev_disp_text('类别:'+className+',分数:'+score, 'window',\
                  'top', 'left', 'white', 'box_color', 'forest green')
    stop()
endfor

clear_dl_model(RetainDLModelHandle)

以上为halcon源码,联合C#编程操作界面

C#源码

        /// <summary>
        /// 分类类别名称
        /// </summary>
        private HTuple classNames;

        /// <summary>
        /// 模型文件
        /// </summary>
        public string[] ModelFiles { get; private set; }

        #region 主界面相关事件
        public HomePage()
        {
            InitializeComponent();
        }

        private void HomePage_FormClosing(object sender, FormClosingEventArgs e)
        {
        }
        private void HomePage_Load(object sender, System.EventArgs e)
        {           
            // UI 显示日志
            ViewAppender viewAppender = new ViewAppender(dgvLog)
            {
                Location = "",
            };
            LogCombiner.Ins.Append(viewAppender);
            // 初始化网络模型
            InitializeModels();

            // 模型评估默认参数
            // recall
            cbMetric.SelectedIndex = 0;
            // test
            cbSampleSelectValues.SelectedIndex = 0;
        }
        #endregion

        #region 设置HWindowControl控件的显示方式
        private void DispImage(HImage image, HWindow window)
        {
            int imageWidth, imageHeight, winRow, winCol, winWidth, winHeight, partWidth, partHeight;
            try
            {
                image.GetImageSize(out imageWidth, out imageHeight);
                window.GetWindowExtents(out winRow, out winCol, out winWidth, out winHeight);
                if (winWidth > winHeight)
                {
                    partWidth = imageWidth;
                    partHeight = imageWidth * winHeight / winWidth;
                }
                else
                {
                    partWidth = imageHeight * winWidth / winHeight;
                    partHeight = imageHeight;
                }

                // 设置显示图像在窗口中间
                var offsetX = (imageWidth - partWidth) / 2;
                var offsetY = (imageHeight - partHeight) / 2;
                // 设置窗口显示区域
                HOperatorSet.SetPart(window, offsetY, offsetX, partHeight + offsetY - 1, partWidth + offsetX - 1);
                // 显示图形
                HOperatorSet.DispObj(image, window);
            }
            catch (HalconException hEx)
            {
                MessageBox.Show(hEx.Message);
            }
        }

        /// <summary>
        /// 把HObject转化为对应的HImage方法
        /// </summary>
        /// <param name="hObject"></param>
        /// <param name="image"></param>
        private HImage HObject2HImage(HObject hObject)
        {
            HImage image = new HImage();
            // 获取当前传人对象的通道数【灰度/彩色】
            HOperatorSet.CountChannels(hObject, out var channels);
            if (channels.I == 0)
            {
                return image;
            }
            // 判断通道数
            if (channels.I == 1)
            {
                // 获取传人图形的数据
                HOperatorSet.GetImagePointer1(hObject,
                    out var pointer, out var type, out var width, out var height);
                // 生成当通道图形
                image.GenImage1(type, width, height, pointer);
            }
            else
            {
                // 彩色图
                HOperatorSet.GetImagePointer3(hObject, out var pointerRed, out var pointerGreen,
                    out var pointerBlue, out var type, out var width, out var height);
                image.GenImage3(type, width, height, pointerRed, pointerGreen, pointerBlue);
            }

            return image;
        }
        #endregion

        #region 加载模型文件选择下拉框
        private void InitializeModels()
        {
            // 获取项目编译路径
            ModelFiles = Directory.GetFiles(Path.Combine(Directory.GetCurrentDirectory(), "hdl"),"*.hdl");
            // 把模型文件添加至下拉框中
            foreach(string modelFile in ModelFiles)
            {
                // 获取模型文件名
                string modelName = Path.GetFileNameWithoutExtension(modelFile);
                // 添加到下拉列表
                cbBackBone.Items.Add(modelName);
            }
            // 判断是否有模型文件
            if(ModelFiles.Length > 0)
            {
                // 默认选择第一个文件
                cbBackBone.SelectedIndex = 0;
                Logger.Notify("model load finished .", "Preprocess");
            }
            else
            {
                // 如果没有模型文件,下拉框禁用
                cbBackBone.Enabled = false;
                Logger.Warn("model files not found .", "Preprocess");
            }
        }
        #endregion

        #region 读取模型参数
        private void cbBackBone_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                // 读取选择的网络模型文件
                string modelFile = ModelFiles[cbBackBone.SelectedIndex];
                // 加载模型 read_dl_model
                HOperatorSet.ReadDlModel(modelFile, out var dLModelHandle);
                // 判断模型不为空
                if(dLModelHandle == null)
                {
                    Logger.Warn("read_dl_model failure .", "Preprocess");
                    return;
                }
                // 读取模型张量数
                HOperatorSet.GetDlModelParam(dLModelHandle, "image_width", out HTuple imageWidth);
                HOperatorSet.GetDlModelParam(dLModelHandle, "image_height", out HTuple imageHeight);
                HOperatorSet.GetDlModelParam(dLModelHandle, "image_num_channels", out HTuple imageChannels);
                HOperatorSet.GetDlModelParam(dLModelHandle, "image_range_min", out HTuple imageRangMin);
                HOperatorSet.GetDlModelParam(dLModelHandle, "image_range_max", out HTuple imageRangMax);
                // 数据填充至对应文本框
                tbImgWidth.Text = imageWidth.ToString();
                tbImgHeight.Text = imageHeight.ToString();
                tbChannel.Text = imageChannels.ToString();
                tbGrayMin.Text = imageRangMin.ToString();
                tbGrayMax.Text = imageRangMax.ToString();

                // 释放加载的模型
                HOperatorSet.ClearDlModel(dLModelHandle);
                dLModelHandle.Dispose();
                dLModelHandle = null;
            }
            catch (Exception ex)
            {
                Logger.Error(ex.Message, "Preprocess");
            }
        }
        #endregion

        #region 选择样本路径和存储路径
        private void btnSelectRawPath_Click(object sender, EventArgs e)
        {
            using (FolderBrowserDialog dlg = new FolderBrowserDialog())
            {
                if (dlg.ShowDialog() == DialogResult.OK)
                {
                    // 重新创建,防止重复添加
                    classNames = new HTuple();
                    tbRawPath.Text = dlg.SelectedPath;
                    // 获取选择文件夹下面的所有文件夹名称
                    string[] folder = Directory.GetDirectories(tbRawPath.Text);
                    // 把文件夹名添加到元组中
                    foreach (var item in folder)
                    {
                        classNames.Append(new DirectoryInfo(item).Name);
                    }
                }
            }
        }

        private void btnSelectPrePath_Click(object sender, EventArgs e)
        {
            using (FolderBrowserDialog dlg = new FolderBrowserDialog())
            {
                if (dlg.ShowDialog() == DialogResult.OK)
                {
                    tbPreStorPath.Text = dlg.SelectedPath;
                }
            }
        }
        #endregion

        #region 执行数据预处理操作
        private async void btnExecPreprocess_Click(object sender, EventArgs e)
        {
            // 获取预处理对象
            var preprocess = Classification.ProcessAction;
            // 绑定更新方法
            preprocess.UpdateImageAction += Preprocess_UpdateImageAction; 
            // 获取界面的参数
            var imageWith = Convert.ToInt32(tbImgWidth.Text);
            var imageHeight = Convert.ToInt32(tbImgHeight.Text);
            var imageNumChannels = Convert.ToInt32(tbChannel.Text);
            var imageRangeMin = Convert.ToInt32(tbGrayMin.Text);
            var imageRangeMax = Convert.ToInt32(tbGrayMax.Text);
            var backBoneFileName = ModelFiles[cbBackBone.SelectedIndex];
            var rawImagePath = tbRawPath.Text;
            var preprocessPath = tbPreStorPath.Text;

            // 设置到预处理对象属性中
            preprocess.ImageHeight = imageHeight;
            preprocess.ImageWidth = imageWith;
            preprocess.ImageNumChannels = imageNumChannels;
            preprocess.ImageRangeMin = imageRangeMin;
            preprocess.ImageRangeMax = imageRangeMax;
            preprocess.BackBonePath = backBoneFileName;
            preprocess.PreProcessPath = preprocessPath;
            preprocess.SamplesPath = rawImagePath;
            // 设置分类名称
            preprocess.ClassNames = classNames;
            // 界面显示信息
            HalconDLTool.set_display_font(hWinPre.HalconWindow, 20, "mono", "true", "false");
            // 调用预处理对象的预处理方法
            var res = await preprocess.ExecutePreProcess();
            // 判断执行结果
            if (res > 0)
            {
                HOperatorSet.DispText(hWinPre.HalconWindow, "Preprocess finished .", "window", 12, 12, "white", "box_color", "forest green");
                Logger.Notify("Preprocess finished .", "Preprocess");
            }
            else
            {
                HOperatorSet.DispText(hWinPre.HalconWindow, "Preprocess failure .", "window", 12, 12, "white", "box_color", "red");
                Logger.Error("Preprocess failure .", "Preprocess");
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="obj"></param>
        /// <exception cref="NotImplementedException"></exception>
        private void Preprocess_UpdateImageAction(HObject obj)
        {
            try
            {
                if (obj != null)
                {
                    var hw = hWinPre.HalconWindow;
                    hw.ClearWindow();
                    hw.SetWindowParam("flush", "false");
                    DispImage(HObject2HImage(obj), hw);
                    hw.FlushBuffer();
                }
            }
            catch (Exception)
            {

                throw;
            }
        }
        #endregion

        #region 选择训练的数据集文件
        private string SelectFile(string filter)
        {
            using(OpenFileDialog dlg = new OpenFileDialog())
            {
                dlg.Filter = filter;
                if(dlg.ShowDialog() == DialogResult.OK)
                {
                    return dlg.FileName;
                }
                return null;
            }
        }
        private void btnSelectData_Click(object sender, EventArgs e)
        {
            // 获取选择的数据集文件路径
            string datasetFile = SelectFile("Dataset(*.hdict)|*.hdict");
            // 把数据集路径存放至控件的Tag属性,并显示文件名称
            tbDataPath.Tag = datasetFile;
            if(datasetFile != null)
            {
                // 将数据集名称显示至文本框
                tbDataPath.Text = Path.GetFileNameWithoutExtension(datasetFile);
            }
            //  获取当前文件所在的路径,模型文件也在当前目录下
            Classification.TrainingAction.ModelFilePath = Path.GetDirectoryName(datasetFile);
        }
        #endregion

        #region 执行模型训练
        private async void btnTrain_Click(object sender, EventArgs e)
        {
            // 获取训练对象
            var training = Classification.TrainingAction;
            // 获取界面的数据
            var batchSize = Convert.ToInt32(tbBatchSize.Text);
            var learningRate = Convert.ToDouble(tbLearningRate.Text);
            var numEpochs = Convert.ToInt32(tbNumEpochs.Text);
            var evaluateNumEpochs = Convert.ToInt32(tbEvluationIntervalEphochs.Text);
            var trainingPrecent = Convert.ToInt32(tbTrainPrecent.Text);
            var validationPercent = Convert.ToInt32(tbValiddatatPrecent.Text);
            // 设置训练对象的属性
            training.TraingPercent = trainingPrecent;
            training.ValidationPercent = validationPercent;
            training.BatchSize = batchSize;
            training.LearningRate = learningRate;
            training.NumEpochs = numEpochs;
            training.EvaluateNumEpoch = evaluateNumEpochs;
            // 设置显示窗口的的背景
            var hw = hWinTrain.HalconWindow;
            hw.SetWindowParam("background_color", "light gray");
            training.TrainWindow = hw;

            // 调用模型训练的方法
            int res = await training.ExecuteTraining();

            if (res > 0)
            {
                Logger.Notify("training finished .", "Training");
            }
            else
            {
                Logger.Error("training exception .", "Training");
            }
        }
        #endregion

        #region 执行评估
        private void btnEvaluate_Click(object sender, EventArgs e)
        {
            // 获取评估对象并给属性赋值
            var evaluate = Classification.EvaluateAction;
            evaluate.EvaluateMetric = cbMetric.Text;
            evaluate.EvaluateDataName = cbSampleSelectValues.Text;
            evaluate.EvaluateWindow = hWinEvaluate.HalconWindow;

            // 执行模型评估
            int res = evaluate.ExecuteEvaluate();

            if (res > 0)
            {
                Logger.Notify("evaluate finished .", "Evaluate");
            }
            else
            {
                Logger.Error("evaluate error .", "Evaluate");
            }
        }
        private void btnSelectEvaluateModel_Click(object sender, EventArgs e)
        {
            // 获取选择的数据集文件路径
            string datasetFile = SelectFile("Model(*.hdl)|*.hdl");
            if (datasetFile != null)
            {
                // 将数据集名称显示至文本框
                tbEvaluateModelFile.Text = Path.GetFileNameWithoutExtension(datasetFile);
            }
            // 设置完成的模型路径
            Classification.EvaluateAction.EvaluateModelFileName = datasetFile;
        }
        #endregion

        #region 执行推断
        private void btnSelectInferModel_Click(object sender, EventArgs e)
        {
            // 获取选择的数据集文件路径
            string datasetFile = SelectFile("Model(*.hdl)|*.hdl");
            // 把数据集路径存放至控件的Tag属性,并显示文件名称
            tbInferModel.Tag = datasetFile;
            if (datasetFile != null)
            {
                // 将数据集名称显示至文本框
                tbInferModel.Text = Path.GetFileNameWithoutExtension(datasetFile);
            }
            // 设置推断使用的模型文件
            Classification.InferenceAction.ModelTypeName = datasetFile;
        }
        private void btnSelectInferImg_Click(object sender, EventArgs e)
        {

            var dialog = new FolderBrowserDialog();
            if (dialog.ShowDialog() == DialogResult.OK)
            {
                // 获取用户选择的目录
                var inferDataPath = dialog.SelectedPath;
                // 给文本框赋值
                tbInferPath.Text = inferDataPath;
                // 设置推断文件,这里可以进行优化文件后缀,避免放置非图像文件
                Classification.InferenceAction.InferImages = Directory.GetFiles(inferDataPath).ToList();
            }
        }
        private async void btnSigInfer_Click(object sender, EventArgs e)
        {
            // 获取推断对象
            var infer = Classification.InferenceAction;
            infer.UpdateInvoker += InferOnece_UpdateInvoker;

            // 调用推断方法
            int res = await infer.ExecuteInfer(InferType.ONECE);

            if (res > 0)
            {
                // 赋值推断结果
                tbClass.Text = infer.Class;
                tbScore.Text = (infer.Score*100).ToString("F2");
                tbTicks.Text = (infer.Ticks * 1000).ToString("F4");
                Logger.Log($"{infer.Index}.Type:{infer.Class},Score:{(infer.Score * 100).ToString("F2")}", "Inference");
            }
            else
            {
                Logger.Log("infer method error.", "Inference");
            }
        }

        private void InferOnece_UpdateInvoker(HObject obj)
        {
            if (obj != null)
            {
                var hw = hWinInfer.HalconWindow;
                // 关闭窗口缓存更新
                hw.SetWindowParam("flush", "false");
                // 把上一次窗口显示数据清空
                hw.ClearWindow();
                // 显示采集图像
                DispImage(HObject2HImage(obj), hw);
                // 更新创建数据
                hw.FlushBuffer();
            }
        }

        private async void btnContinueInfer_Click(object sender, EventArgs e)
        {
            // 获取推断对象
            var infer = Classification.InferenceAction;
            infer.ContinueUpdateInvoker += InferContinue_UpdateInvoker;

            // 调用推断方法
            int res = await infer.ExecuteInfer(InferType.CONTINUE);

            if (res > 0)
            {
                // 赋值推断结果
                Logger.Notify("continue inference finished.", "Inference");
            }
            else
            {
                Logger.Log("continue infer method error.", "Inference");
            }
        }

        private void InferContinue_UpdateInvoker(HObject obj, Inference inference)
        {
            if (obj != null)
            {
                var hw = hWinInfer.HalconWindow;
                // 关闭窗口缓存更新
                hw.SetWindowParam("flush", "false");
                // 把上一次窗口显示数据清空
                hw.ClearWindow();
                // 显示采集图像
                DispImage(HObject2HImage(obj), hw);
                // 更新创建数据
                hw.FlushBuffer();

                // 多线程中调用必须使用异步调用方式
                BeginInvoke(new Action(() =>
                {
                    // 赋值推断结果
                    tbClass.Text = inference.Class;
                    tbScore.Text = (inference.Score*100).ToString("F2");
                    tbTicks.Text = (inference.Ticks * 1000).ToString("F4");
                }));
                Logger.Log($"{inference.Index}.Type:{inference.Class},Score:{(inference.Score * 100).ToString("F2")}", "Inference");
            }
        }
        #endregion

完整打包资料资料包​​​​​​​


网站公告

今日签到

点亮在社区的每一天
去签到