halcon 深度学习

1. 模型训练

1.1 深度学习的概念

  • (一)、深度学习类型
  • 监督学习
  • 有标注
  • 非监督学习
  • 无标注
  • (二)、模型参数
  • 超参数
  • 人为设定的, 网络无法学习的
  • 学习率
  • batch size
  • 图像大小(hwc)
  • L2 正则化系数
  • 动量值
  • 学习总轮数
  • 网络参数
  • 模型自己学习的参数(halcon 已经封装好了,直接调用)
  • (三)、数据
  • 训练数据
  • 用于模型训练,确定模型的权重和偏置这些参数
  • 验证数据
  • 而验证集用于模型的选择,更具体地来说,验证集并不参与学习参数的确定
  • 测试数据
  • 它既不参与学习参数过程,也不参数超参数选择过程,而仅仅使用于模型的评价

1.2 目标检测

  • (一)、主要任务
  • 确定物体位置
  • bounding box
  • xc、yc、w、h
  • x1、y1、x2、y2(halcon)
  • 确定物体类别
  • 数字(从0开始)

-(二)、 halcon 中的目标检测

  • 有锚框
  • 类聚几个有代表性的框

1.3 halcon模型训练

  • 设置模型
  • 选择模型
  • 设置参数
  • 准备数据
  • 处理数据
  • 图像增强
  • 模型训练
  • 模型保存
  • 最好模型
  • 根据指标选择
  • 最后模型
  • 字典
  • 键值对

2. 数据标注

dltool

3. halcon 目标检测代码全文注释

************************************
**     设置检测模型基本参数        **
************************************
*设置创建深度模型必须的2个参数:1.预训练的网络。2.分类的个数
*1.选择预训练的网络
*该网络类型设计用于简单的分类任务
* Backbone := 'pretrained_dl_classifier_alexnet.hdl'
*该网络类型旨在提高内存效率和运行时效率
Backbone := 'pretrained_dl_classifier_compact.hdl'
*该网络类型更适合于更复杂的分类任务,增加时间和内存需求为代价
* Backbone := 'pretrained_dl_classifier_enhanced.hdl'
* Backbone := 'pretrained_dl_classifier_resnet50'

*2.设置需要分类的个数
NumClasses := 22
*设置模型的尺寸和通道数量,这些参数会在预处理中对样本图像进行调整
ImageWidth := 512
ImageHeight := 512
ImageNumChannels := 1 

*将容量设置为“medium”,整个设置足以满足训练和推理的速度要求,相比“high”,在检测效果几乎差不多的情况下,速度可以提高2倍
Capacity := 'medium'
* Capacity := 'high'

*设置训练集和验证集的百分比
TrainingPercent := 90
ValidationPercent := 5
*设置随机数种子,在进行样本分割的时候需要用随机的方式进行。
*为保证后续重新运行时分割的样本能够一致,所以设定一个固定的随机数种子
SeedRand := 32


************************************
**        设置输入输出路径         **
************************************
# /// <设置项目文件夹,所有信息均保存在该文件夹下,必须设置项>
ExampleDataDir := 'detect_pills_data'


# /// <设置设置样本图像所在的文件夹,必须设置项>
* get_system ('example_dir', HalconExampleDir)
* HalconImageDir := 'C:/Users/Public/Documents/MVTec/HALCON-19.11-Progress/examples/images/pill_bag/'
* HalconImageDir := 'E:/PLImage/'

*初始化的深度学习模型保存地址,模型拓展名为hdl(Hdevelop DL),不必修改
DLModelFileName := ExampleDataDir + '/initialization_DL_model_detection.hdl'

*设置预处理函数’preprocess_dl_dataset‘输出内容的保存目录,不必修改
DataDirectory := ExampleDataDir + '/dldataset_' + ImageWidth + 'x' + ImageHeight

*设置保存预处理参数的地址,在推理部分会使用到,不必修改
PreprocessParamFileName := DataDirectory + '/dl_preprocess_param.hdict'

*如果目标文件夹不存在则进行创建
file_exists (ExampleDataDir, FileExists)
if (not FileExists)
    make_dir (ExampleDataDir)
endif
************************************
**       读取已标注的数据集        **
************************************
*利用MVTec DeepLearning Tool可以直接导出数据集信息,使用read_dict函数即可读出
* read_dict ('C:/Cross.dltp', [], [], DLDataset)

*如果是读取COCO(json保存格式)数据集,则利用下面两段程序进行读取。读取halcon例程数据集就是使用下面程序
* PillBagJsonFile := 'C:/Users/Public/Documents/MVTec/HALCON-19.11-Progress/examples/hdevelop/Deep-Learning/Detection/pill_bag.json'
* HalconImageDir := 'C:/Users/Public/Documents/MVTec/HALCON-19.11-Progress/examples/images/'
* read_dl_dataset_from_coco (PillBagJsonFile, HalconImageDir, [], DLDataset)


*将读出的数据集根据设定的比例分割出‘训练集’、‘验证集’和‘测试集’,执行完该步操作后,数据集信息有所调整:
*在‘sample’下面的标注样本中会增加一个名为‘split’的key,value值为‘train’\'validation'或‘test’,从而表明分割后的类型
split_dl_dataset (DLDataset, TrainingPercent, ValidationPercent, [])

************************************
**     根据数据集优化模型参数      **
************************************
*函数可以根据数据集中的标注信息对‘min_level’,'max_level','anchor_num_subscales,','anchor_aspect_ratios'等参数
*进行分析并给出建议值,从而优化训练结果。
*但是需要注意,对模型参数做过多的优化可能导致过拟合,也就是对于样本中缺陷识别的较好,与样本相比稍有差异的缺陷可能就会识别效果不理想
*因此,只有当实际使用中的数据与训练数据类似的时候才可以使用。
create_dict (GenParam)
*创建一个字典,将分割后的数据集的类型填入(训练集)
set_dict_tuple (GenParam, 'split', 'train')
*执行函数,得到建议参数的字典变量
determine_dl_model_detection_param (DLDataset, ImageWidth, ImageHeight, GenParam, DLDetectionModelParam)
*在字典变量中读出相关的建议参数
get_dict_tuple (DLDetectionModelParam, 'min_level', MinLevel)
get_dict_tuple (DLDetectionModelParam, 'max_level', MaxLevel)
get_dict_tuple (DLDetectionModelParam, 'anchor_num_subscales', AnchorNumSubscales)
get_dict_tuple (DLDetectionModelParam, 'anchor_aspect_ratios', AnchorAspectRatios)


************************************
**       创建目标检测模型          **
************************************
*创建一个用于装载多项模型参数的字典变量,模型相关的设置都放置在该变量中,在创建模型时候会传入函数
create_dict (DLModelDetectionParam)

*设置模型的各项参数
set_dict_tuple (DLModelDetectionParam, 'image_width', ImageWidth)
set_dict_tuple (DLModelDetectionParam, 'image_height', ImageHeight)
set_dict_tuple (DLModelDetectionParam, 'image_num_channels', ImageNumChannels)
set_dict_tuple (DLModelDetectionParam, 'min_level', MinLevel)
set_dict_tuple (DLModelDetectionParam, 'max_level', MaxLevel)
set_dict_tuple (DLModelDetectionParam, 'anchor_num_subscales', AnchorNumSubscales)
set_dict_tuple (DLModelDetectionParam, 'anchor_aspect_ratios', AnchorAspectRatios)
set_dict_tuple (DLModelDetectionParam, 'capacity', Capacity)


*根据标注框的类型对训练模型进行设置
get_dict_tuple (DLDataset, 'samples', Shape_Samples)
Shape_Sample:=Shape_Samples[0]
BboxKeyList:=['bbox_length1','bbox_length2','bbox_phi']
get_dict_param (Shape_Sample, 'key_exists', BboxKeyList, KeysExist)
if(sum(KeysExist)==3)
    *标注类型为rectangle2,否则标注类型为rectangle1(默认)
    set_dict_tuple (DLModelDetectionParam, 'instance_type', 'rectangle2')
endif


*从数据集中获取分类信息,并写入模型参数变量中
get_dict_tuple (DLDataset, 'class_ids', ClassIDs)
set_dict_tuple (DLModelDetectionParam, 'class_ids', ClassIDs)

*根据已经设置好的参数创建目标检测模型
create_dl_model_detection (Backbone, NumClasses, DLModelDetectionParam, DLModelHandle)
*此步如果报错,请检查NumClasses中的个数和变量ClassIDs中的个数是否对应



*保存初始化后的模型(根据实际情况决定,也可不保存)
write_dl_model (DLModelHandle, DLModelFileName)



************************************
**          数据集预处理           **
************************************
*从已经创建的模型中获取预处理数据
create_dl_preprocess_param_from_model (DLModelHandle, 'none', 'full_domain', [], [], [], DLPreprocessParam)

*对数据集进行预处理,时间较长
*创建一个字典变量,用于执行图像预处理函数时传入参数。
*将"overwrite_files"设置为true,即处理后的数据集数据会覆盖原文件。
create_dict (GenParam)
set_dict_tuple (GenParam, 'overwrite_files', true)

*执行数据集预处理函数,*执行完该步操作后,数据集信息有所调整:
*1.在数据集中增加了'preprocess_param'的字段key,用于保存模型预处理的相关参数
*2.在数据集中增加了'dlsample_dir'的字段key,用于保存预处理后文件的保存地址
*3.在‘sample’下面的标注样本中会增加一个名为‘dlsample_file_name’的字段key,保存该样本经过预处理后生产文件的文件名

*该函数变量含义如下:*DLDataset:数据集   DataDirectory:输出文件夹 
*DLPreprocessParam:从模型中读出的参数变量   DLDetectionModelParam:调整后的数据集的保存地址
preprocess_dl_dataset (DLDataset, DataDirectory, DLPreprocessParam, GenParam, DLDatasetFilename)

*将从已创建的模型中获取的预处理参数进行保存
write_dict (DLPreprocessParam, PreprocessParamFileName, [], [])


*******************************************************************************************
*******************************************************************************************
******                        模  型  训  练  部  分                                  ****** 
*******************************************************************************************
*******************************************************************************************



************************************
**         设置输入输出路径        **
************************************
*所有训练输出数据保存的文件夹(在预训练部分中已经设置过)
* ExampleDataDir := 'detect_pills_data'
*在模型创建中初始化的模型位置
* InitialModelFileName := ExampleDataDir + '/initialization_DL_model_detection.hdl'
*经过预处理后数据集标注文件位置
* DataDirectory := ExampleDataDir + '/dldataset_512x320'
*经过预处理后的数据集位置。经过预处理后数据集中的图像大小进行了调整,所以需要读取调整后保存在文件夹中的数据集文件。
* DLDatasetFileName := DataDirectory + '/dl_dataset.hdict'
*保存评估效果最佳的训练模型位置
BestModelBaseName := ExampleDataDir+'/best_dl_model_detection'
*保存评估效果最佳的训练模型位置
FinalModelBaseName := ExampleDataDir+'/final_dl_model_detection'



************************************
**          设置基础参数           **
************************************
*设置批量数
BatchSize := 16
*设置初始学习率
InitialLearningRate := 0.00001
*设置动量值。如果批量数少则该值设置相对高一些。
Momentum := 0.999
*设置训练次数
NumEpochs := 600
*设置评估周期
EvaluationIntervalEpochs := 1
*设置训练方案的调整周期,当训练30次时调整训练方案,如训练30次时调整学习率
ChangeLearningRateEpochs := 10
*设置具体的训练方案的调整内容,例如训练30次时调整学习率,将原有学习率*0.1
ChangeLearningRateValues := InitialLearningRate * 0.1



************************************
**           设置超参数            **
************************************
*设置权重衰减参数,防止过拟合,可以针对较大的权重进行处理。
*该值太小模型可可能出现过拟合,太大可能会导致拟合不准确。
WeightPrior := 0.001
*选择是否将训练过程进行显示(true/false).
DisplayEvaluation := true

*使用函数‘create_dl_train_param’创建训练参数,创建两个变量用于传递函数。
GenParamName := []
GenParamValue := []
*样本拓展参数,相当于增加样本数量,首先创建一个用用户设置样本拓展参数的字典
create_dict (AugmentationParam)
*设置样本拓展的比例及对应的拓展方法,本例中拓展方法是图像根据横纵坐标做镜像的方式
set_dict_tuple (AugmentationParam, 'augmentation_percentage', 50)
set_dict_tuple (AugmentationParam, 'mirror', 'rc')
*将样本拓展的设置参数加入传递参数的数组中,待创建训练参数时传入
GenParamName := [GenParamName,'augment']
GenParamValue := [GenParamValue,AugmentationParam]

*训练策略调整方式变更设置,即在训练过程中会对某些参数进行调整。
*下面针对学习率进行动态调整
if (|ChangeLearningRateEpochs| > 0)
    *创建一个字典变量用于保存学习率调整策略的参数
    create_dict (ChangeStrategy)
    *传入需要动态调整的项目,本例为学习率
    set_dict_tuple (ChangeStrategy, 'model_param', 'learning_rate')
    *传入初始参数
    set_dict_tuple (ChangeStrategy, 'initial_value', InitialLearningRate)
    *设置策略调整的时间点,即在训练过程中的哪个周期进行调整
    set_dict_tuple (ChangeStrategy, 'epochs', ChangeLearningRateEpochs)
    *设置调整后的参数
    set_dict_tuple (ChangeStrategy, 'values', ChangeLearningRateValues)
    *将设置完的学习率调整变量传递到参数的数组中
    GenParamName := [GenParamName,'change']
    GenParamValue := [GenParamValue,ChangeStrategy]
endif

*序列化方案,在模型训练过程中,有多种类型的过程模型可以保存。
*下面以保存最佳模型和最终模型为例
*创建字典变量用于保存序列化方案参数
create_dict (SerializationStrategy)
*选择需要保存的训练模型类型,最佳模型
set_dict_tuple (SerializationStrategy, 'type', 'best')
*设置保存的地址和文件名
set_dict_tuple (SerializationStrategy, 'basename', BestModelBaseName)
*添加到参数数组中
GenParamName := [GenParamName,'serialize']
GenParamValue := [GenParamValue,SerializationStrategy]

*设置保存最终模型的参数,具体操作同上
create_dict (SerializationStrategy)
set_dict_tuple (SerializationStrategy, 'type', 'final')
set_dict_tuple (SerializationStrategy, 'basename', FinalModelBaseName)
GenParamName := [GenParamName,'serialize']
GenParamValue := [GenParamValue,SerializationStrategy]

*显示参数。在本例中,在训练过程中,训练的评估方式时不进行显示的(默认),如需显示则选择一个特定的百分比数量
*选择一个较低的值有助于实现快速评估。如不需要显示,则将百分比参数设置为0.
SelectedPercentageTrainSamples := 0
create_dict (DisplayParam)
set_dict_tuple (DisplayParam, 'selected_percentage_train_samples', SelectedPercentageTrainSamples)
GenParamName := [GenParamName,'display']
GenParamValue := [GenParamValue,DisplayParam]


************************************
** 读取创建的模型和预处理后的数据集 **
************************************
*读取模型
*如果是读取硬盘上已经保存的模型,则需要设置对应地址进行读取
*在前文中创建的模型可以直接使用,所以不需要读取,因此该部分代码屏蔽,只做说明
*InitialModelFileName:='path'
* read_dl_model (InitialModelFileName, DLModelHandle)

*读取经过预处理后的数据集文件
*如果是读取硬盘上已经保存的预处理数据集文件,则需要设置对应地址进行读取
*在前文中创建的模型可以直接使用,所以不需要读取,因此该部分代码屏蔽,只做说明
* DLDatasetFileName:='path'
* read_dict (DLDatasetFileName, [], [], DLDataset)


************************************
**          设置模型参数           **
************************************
*设置学习率参数
set_dl_model_param (DLModelHandle, 'learning_rate', InitialLearningRate)
*设置动量参数
set_dl_model_param (DLModelHandle, 'momentum', Momentum)
if (BatchSize == 'maximum')
    set_dl_model_param_max_gpu_batch_size (DLModelHandle, 100)
else
    set_dl_model_param (DLModelHandle, 'batch_size', BatchSize)
endif
if (|WeightPrior| > 0)
    set_dl_model_param (DLModelHandle, 'weight_prior', WeightPrior)
endif
set_dl_model_param (DLModelHandle, 'runtime_init', 'immediately')


************************************
**            模型训练            **
************************************
*创建训练参数
create_dl_train_param (DLModelHandle, NumEpochs, EvaluationIntervalEpochs, DisplayEvaluation, SeedRand, GenParamName, GenParamValue, TrainParam)
*调用下面的训练函数开启训练
train_dl_model (DLDataset, DLModelHandle, TrainParam, 0.0, TrainResults, TrainInfos, EvaluationInfos)
* Stop after the training has finished, before closing the windows.
dev_disp_text ('Complete The Training !!!', 'window', 'bottom', 'right', 'black', [], [])
stop ()

*******************************************************************************************
*******************************************************************************************
******                        模  型  应  用  部  分                                  ****** 
*******************************************************************************************
*******************************************************************************************
*对于需要使用训练后的模型进行检测的图像,需要根据预处理的相关参数进行预处理操作。
*因为目标检测的模型就是使用根据这些参数进行过预处理的图像进行训练得到的。


************************************
**      设置检测所需的路径和参数    **
************************************
 ExampleDataDir := 'D:/testdata/'
*设置预处理参数的保存路径
PreprocessParamFileName:=ExampleDataDir+'/dldataset_512x512/dl_preprocess_param.hdict'
*设置需要读取的检测模型的路径
RetrainedModelFileName := ExampleDataDir+'/best_dl_model_detection'

*提供分类的名称和对应的ID号,在后面显示结果的时候会使用到,在实际使用过程中不需要进行设置
* ClassNames := ['Omega-3','KMW','Stomach tablet','Ginko','Ginseng','Glucosamine','Cognivia','Capsularum I','Iron tablet','Vitamin-B']
* ClassIDs := [1,2,3,4,5,6,7,8,9,10]

*检测中使用到的batch,设置为1
BatchSizeInference := 1

*设置检测模型的后处理参数
*设置最小置信度,如果检测的置信度小于该值则忽略
MinConfidence := 0.3
*设置最大重叠面积。当对同一个对象检测到多个同样分类时,可以设置该值,重叠面积百分比小于该值的会被滤掉,默认是是0.5
MaxOverlap := 0.5
*设置重叠区域分类参数。当对同一个对象检测到多个不同样分类时,可以设置该值,针对不同分类的重叠区域,重叠面积百分比小的分类区域会滤掉,默认值是1.0
MaxOverlapClassAgnostic := 0.7

*是否使用GPU进行检测
UseGPU := false

************************************
**        进行图像的推理检测       **
************************************
*检测是否使用GPU,如果使用则进行相应的设置
if (UseGPU)
    get_system ('cuda_loaded', CudaLoaded)
    get_system ('cudnn_loaded', CuDNNLoaded)
    get_system ('cublas_loaded', CuBlasLoaded)
    if (not (CudaLoaded == 'true' and CuDNNLoaded == 'true' and CuBlasLoaded == 'true'))
        UseGPU := false
    endif
endif

*读取已经训练好的检测模型,因为上文中已经训练完成,所以此处不需要读取
 read_dl_model (RetrainedModelFileName, DLModelHandle)

*设置批量大小
set_dl_model_param (DLModelHandle, 'batch_size', BatchSizeInference)

*根据是否使用GPU进行推导进行设置
if (not UseGPU)
    set_dl_model_param (DLModelHandle, 'runtime', 'cpu')
else
    set_dl_model_param (DLModelHandle, 'runtime', 'cpu')
endif
set_dl_model_param (DLModelHandle, 'runtime_init', 'immediately')

*将设置好的后处理参数传入检测模型
set_dl_model_param (DLModelHandle, 'min_confidence', MinConfidence)
set_dl_model_param (DLModelHandle, 'max_overlap', MaxOverlap)
set_dl_model_param (DLModelHandle, 'max_overlap_class_agnostic', MaxOverlapClassAgnostic)

*读入预处理的参数
 read_dict (PreprocessParamFileName, [], [], DLPreprocessParam)

get_dict_tuple (DLDataset, 'samples', Shape_Samples)
Shape_Sample:=Shape_Samples[0]
BboxKeyList:=['bbox_length1','bbox_length2','bbox_phi']
get_dict_param (Shape_Sample, 'key_exists', BboxKeyList, KeysExist)
if(sum(KeysExist)==3)
    shape_type:='ractangle2'
else
    shape_type:='ractangle1'
endif

*读取需要进行检测的图像
dev_update_off()
list_files ('D:test_image', 'files', Files)
for Index := 0 to |Files| - 1 by 1
    read_image (Image1, Files[Index])
    select_obj (Image1, Image, 1)
    gen_dl_samples_from_images (Image, DLSampleBatch)
    preprocess_dl_samples (DLSampleBatch, DLPreprocessParam)
    apply_dl_model (DLModelHandle, DLSampleBatch, [], DLResultBatch)
    
    *解析检测结果
    DLSample := DLSampleBatch
    DLResult := DLResultBatch
*             get_dict_tuple (DLResult, 'bbox_confidence',idence)
* confidence:=[confidence,idence]

* if(min(idence)<0.2)
*  stop()   
* endif
    zoom_image_size (Image, ImageZoom, 512, 512, 'constant')
    dev_display (ImageZoom)
    if(shape_type=='ractangle2')
        get_dict_tuple (DLResult, 'bbox_row', row)
        get_dict_tuple (DLResult, 'bbox_col', col)
        get_dict_tuple (DLResult, 'bbox_length1',length1)
        get_dict_tuple (DLResult, 'bbox_length2',length2)
        get_dict_tuple (DLResult, 'bbox_phi',phi)
        if(|row|==0)
            
        else
            gen_rectangle2 (Rectangle, row, col, phi, length1, length2)
        endif
    else
        get_dict_tuple (DLResult, 'bbox_row1', row1)
        get_dict_tuple (DLResult, 'bbox_col1', col1)
        get_dict_tuple (DLResult, 'bbox_row2', row2)
        get_dict_tuple (DLResult, 'bbox_col2', col2)
        if(|row1|==0)
            
        else
            gen_rectangle1 (Rectangle, row1, col1, row2, col2)
            
            for Index2 := 0 to |row1| - 1 by 1       
                gen_rectangle1 (Rectangle, row1[Index2], col1[Index2], row2[Index2], col2[Index2])
            endfor
        endif
    endif
endfor

*     tuple_sort(confidence, Sorted)

Imagepath:=''
* read_image (Image, Imagepath)
list_files ('D:/test_image', 'files', Files)
for Index1 := 0 to |Files|-1 by 1
    read_image (ImageSrc, Files[Index1])
    select_obj (ImageSrc, Image,1)
    
*         median_rect (Image, ImageMedian, 9, 9)
* binomial_filter (ImageMedian, Image, 7, 7)
    *将图像转换为字典格式
    gen_dl_samples_from_images (Image, DLSampleBatch)
    *根据预处理参数对需要检测的图像进行检测预处理
    preprocess_dl_samples (DLSampleBatch, DLPreprocessParam)
    *使用已经训练好的模型进行图像检测推理,其中DLResultBatch为得出的结果
    apply_dl_model (DLModelHandle, DLSampleBatch, [], DLResultBatch)

    *解析检测结果
    DLSample := DLSampleBatch
    DLResult := DLResultBatch
    
    zoom_image_size (Image, ImageZoom, 512, 512, 'constant')
    dev_display (ImageZoom)
    if(shape_type=='ractangle2')
        get_dict_tuple (DLResult, 'bbox_row', row)
        get_dict_tuple (DLResult, 'bbox_col', col)
        get_dict_tuple (DLResult, 'bbox_length1',length1)
        get_dict_tuple (DLResult, 'bbox_length2',length2)
        get_dict_tuple (DLResult, 'bbox_phi',phi)
        if(|row|==0)
            continue
        else
            gen_rectangle2 (Rectangle, row, col, phi, length1, length2)
        endif
    else
        get_dict_tuple (DLResult, 'bbox_row1', row1)
        get_dict_tuple (DLResult, 'bbox_col1', col1)
        get_dict_tuple (DLResult, 'bbox_row2', row2)
        get_dict_tuple (DLResult, 'bbox_col2', col2)
        if(|row1|==0)
            continue
        else
            gen_rectangle1 (Rectangle, row1, col1, row2, col2)
        endif
    endif
    dev_display (Rectangle)
*     stop ()
endfor

* get_dict_tuple (DLResult, 'bbox_class_id', DetectedClassIDs)
* tuple_gen_const (|ClassIDs|, 0, NumberDetectionsPerClass)
* for Index := 0 to |ClassIDs| - 1 by 1
*     NumberDetectionsPerClass[Index] := sum(DetectedClassIDs [==] ClassIDs[Index])
* endfor   

*显示检测结果的相关信息,包括位置、置信度、分类、分类说明等。在实际应用过程中以下部分不需要
*提供分类的名称和对应的ID号,在后面显示结果的时候会使用到,在实际使用过程中不需要进行设置
ClassNames := ['Cross']
ClassIDs := [1]

*创建一个字典变量用于设置窗口进行显示结果
create_dict (WindowHandleDict)
*创建一个用于类和对应编号显示的字典变量,在展示窗口中使用
create_dict (DLDataInfo)
set_dict_tuple (DLDataInfo, 'class_names', ClassNames)
set_dict_tuple (DLDataInfo, 'class_ids', ClassIDs)
*设置用于显示的常规参数
create_dict (GenParam)
set_dict_tuple (GenParam, 'scale_windows', 1.2)
*显示检测的结果
dev_display_dl_data (DLSample, DLResult, DLDataInfo, 'bbox_result', GenParam, WindowHandleDict)



*******************************************************************************************
*******************************************************************************************
******                        模  型  评  估  部  分                                  ****** 
*******************************************************************************************
*模型评估就是对已经标注的样本利用训练好的模型进行推理检测,将检测结果与样本的标注信息进行比对,从而得出评估结果

************************************
**      设置评估所需的文件路径      **
************************************
*设置项目所在的文件夹
* ExampleDataDir:='E:/DeepLearnProject/test0123'
*设置训练好的模型的所在路径
RetrainedModelFileName := ExampleDataDir+'/best_dl_model_detection'
*设置经过预处理后的数据集所在位置
DLDatasetFileName := ExampleDataDir+'/dldataset_512x320/dl_preprocess_param.hdict'


************************************
**       设置评估所需的参数        **
************************************
*设定评测方法
EvaluationMeasures := 'all'

*确定IoU阈值
IoUThresholds := []
 
*确定需要显示细节结果的IoU阈值,只有IoU值等于该设定值才会显示具体的对应信息
DisplayIoUThreshold := 0.7

*评估阶段使用的Batch值
BatchSize := 1

*确定某个尺寸目标的评估子集
AreaNames := []
AreaMin := []
AreaMax := []
* 
*确定每个方法的最大检测数量
MaxNumDetections := []

*是否使用GPU进行运算
UseGPU := true


************************************
**        读取模型和数据集         **
************************************
*如果使用GPU则进行对应设置
if (UseGPU)
    get_system ('cuda_loaded', CudaLoaded)
    get_system ('cudnn_loaded', CuDNNLoaded)
    get_system ('cublas_loaded', CuBlasLoaded)
    if (not (CudaLoaded == 'true' and CuDNNLoaded == 'true' and CuBlasLoaded == 'true'))
        UseGPU := false
    endif
endif

*读取已经训练好的数据
*因为本例程中已经存在训练好的模型,所以不需要再次读取
* read_dl_model (RetrainedModelFileName, DLModelHandle)

*设置评估时是否采用GPU进行运算处理
if (not UseGPU)
    set_dl_model_param (DLModelHandle, 'runtime', 'cpu')
endif

*先临时将BatchSize设置为1
set_dl_model_param (DLModelHandle, 'batch_size', 1)
set_dl_model_param (DLModelHandle, 'runtime_init', 'immediately')

*读取经过预处理后的数据集
*因为本例程中已经存在经过预处理后的数据集,所以不需要再次读取
* read_dict (DLDatasetFileName, [], [], DLDataset)


************************************
**      设置用于推理的优化参数      **
************************************
set_dl_model_param (DLModelHandle, 'max_overlap_class_agnostic', 0.7)
set_dl_model_param (DLModelHandle, 'max_overlap', 0.2)
set_dl_model_param (DLModelHandle, 'min_confidence', 0.6)
 

*创建用于管理显示窗口的字典变量
create_dict (WindowHandleDict)

*创建用于传递控制显示信息的字典变量
create_dict (GenParam)
*设置为true,在图像检测框中显示置信度,设置为false则不显示
set_dict_tuple (GenParam, 'bbox_display_confidence', true)

*随机选择测试样本
get_dict_tuple (DLDataset, 'samples', DLSamples)
find_dl_samples (DLSamples, 'split', 'test', 'or', DLSampleIndices)
tuple_shuffle (DLSampleIndices, DLSampleIndicesShuffled)

*应用训练好的模型进行评估并显示对应的结果
for Index := 0 to 5 by 1
    read_dl_samples (DLDataset, DLSampleIndicesShuffled[Index], DLSampleBatch)
    apply_dl_model (DLModelHandle, DLSampleBatch, [], DLResultBatch)
    dev_display_dl_data (DLSampleBatch, DLResultBatch, DLDataset, 'bbox_both', GenParam, WindowHandleDict)
    dev_disp_text ('Press Run (F5) to continue', 'window', 'bottom', 'right', 'black', [], [])
    stop ()
endfor

dev_close_window_dict (WindowHandleDict)
set_dl_model_param (DLModelHandle, 'batch_size', BatchSize)


************************************
**   利用评估数据集对模型进行评估   **
************************************
*创建一个字典变量,用于传递评估参数
create_dict (GenParamEval)
*设置评估方法
set_dict_tuple (GenParamEval, 'measures', EvaluationMeasures)
*设置‘max_num_detections’参数
if (|MaxNumDetections|)
    set_dict_tuple (GenParamEval, 'max_num_detections', MaxNumDetections)
endif
*设置用于评估的区域子集
if (|AreaNames|)
    if ((|AreaNames| != |AreaMin|) or (|AreaNames| != |AreaMax|))
        throw ('AreaNames, AreaMin, and AreaMax must have the same size.')
    endif
    create_dict (AreaRanges)
    set_dict_tuple (AreaRanges, 'name', AreaNames)
    set_dict_tuple (AreaRanges, 'min', AreaMin)
    set_dict_tuple (AreaRanges, 'max', AreaMax)
    set_dict_tuple (GenParamEval, 'area_ranges', AreaRanges)
endif
*设置IoU阈值
if (|IoUThresholds|)
    set_dict_tuple (GenParamEval, 'iou_threshold', IoUThresholds)
endif
*设置是否进行细节评估,如果选择false,后面则无法进行评估细节信息的显示
set_dict_tuple (GenParamEval, 'detailed_evaluation', true)
*设置是否显示评估的进度
set_dict_tuple (GenParamEval, 'show_progress', true)
*对已经训练的模型进行评估
evaluate_dl_model (DLDataset, DLModelHandle, 'split', 'test', GenParamEval, EvaluationResultDetection, EvalParams)

*显示评估的细节结果
create_dict (DisplayParam)
*如果设置了需要评估的IoU阈值,则设置对应的参数
if (|DisplayIoUThreshold| == 1)
    get_dict_tuple (EvalParams, 'iou_threshold', EvalIoUThresholds)
    if (find(EvalIoUThresholds,DisplayIoUThreshold) != -1)
        set_dict_tuple (DisplayParam, 'iou_threshold', DisplayIoUThreshold)
    else
        throw ('No evaluation result for specified IoU threshold.')
    endif
endif
*设置显示模式,如本例:1.饼状图表格式,准确度信息;2.饼状图表格式,召回率信息。
set_dict_tuple (DisplayParam, 'display_mode', ['pie_charts_precision','pie_charts_recall'])
*创建用于管理显示窗口的字典变量
create_dict (WindowHandleDict)

*评估结果显示,以饼状图显示。
dev_display_detection_detailed_evaluation (EvaluationResultDetection, EvalParams, DisplayParam, WindowHandleDict)
stop () 

*评估结果显示,以混淆矩阵的方式显示。
set_dict_tuple (DisplayParam, 'display_mode', 'absolute_confusion_matrix')
dev_display_detection_detailed_evaluation (EvaluationResultDetection, EvalParams, DisplayParam, WindowHandleDict)
stop ()