*****
***环境准备***
***系统: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
完整打包资料资料包