这个例子是halcon18例程中深度学习系列例程中的一例。
它用了MVtec做好的一个药丸分类训练数据库,来做DL(深度学习)检测。
学习主要参考了自带的detect pills的例子,该例子分了四部分,分别是
创建网络和数据预处理
训练网络
评估训练的效果
测试新图像
本文记录了对其中第一步,即创建网络和数据集预处理这部分的一些理解。
创建深度学习网络
设置网络参数
这一步主要是设置选择halcon深度学习网络模型,如pretrained_dl_classifier_compact.hdl。设置类别的数量。指定图像的宽、高、通道数等。创建目标检测网络的模型
Halcon从18.11版本起,有了数据字典这样的概念。可以将上述设定的网络参数,以关键字的形式,存放在一个字典文件中。因而可以用create_dict算子创建数据字典,并set_dict_tuple将网络的参数存储在数据字典中。以修改“Key”值的方式设置模型的参数。
最后使用create_dl_model_detection创建网络的模型,输入上一步设置的模型参数等信息,输出一个DLModelHandle的模型句柄。
假如之前已经创建过合适的网络模型,并用write_dl_model算子进行过保存,也可以使用read_dl_model算子读取它。
数据集预处理
设置输入输出的路径
输入路径有两个,一个是图像路径HalconImageDir,一个是Json文件路径PillBagJsonFile。这两个参数用于后续在图像路径中读取coco文件。
输出路径首先定义一个新的文件夹路径,用于存放样本和模型文件等数据。
设置基于深度学习的目标检测模型的路径,该模型文件以.hdl结尾。
设置样本数据文件夹ExampleDataDir:'detect_pills_data'
数据字典文件夹路径,用于存放DLSampple文件。
设置存储预处理参数文件的路径。设置分割数据集参数
分割数据集是为了区分出训练数据集和验证数据集。这一步设置分割的比例,例如:
TrainingPercent := 70
ValidationPercent := 15
则表示训练数据集占70%,验证数据集占15%,剩下的为测试数据集。
同时指定随机数,用于选择随机图片组成数据集。因为想要在复现训练结果时数据集本身是固定的,因此先使用随机数将数据分散,然后进行分割。
创建DLDataset数据集并调整模型
先检查样本数据集文件夹是否存在,不存在就创建一个。
创建数据集DLDataset调用了自定义的函数read_dl_dataset_from_coco。其输入参数为coco文件名(以.json结尾)和图像路径,输出数据集名为DLDataset。
该函数主要是根据.json文件中的关键字对图像进行解析,如'categories'、'images'、'annotations'。'annotations'里面再读取'bbox'属性。然后将这些属性读取并转化,以key的形式存入数据字典DLDataset和DLSample。
存入数据字典DLDataset的属性有:
'image_dir'
'class_ids'
'class_names'
存入DLSample数据字典的属性有:
'image_id'、'image_file_name'、
'bbox_row1'、
'bbox_col1'、
'bbox_row2'、
'bbox_col2'、
'bbox_label_id'、
'coco_raw_annotations'
最后将DLSample数据字典以‘sample’的形式存入DLDataset数据字典。
创建好数据字典之后,读取DLDataset中的'class_ids'属性,将其设置为深度学习网络模型DLModelHandle的'class_ids'属性,同时根据网络模型的句柄DLModelHandle将该模型保存到预设的文件夹路径下,完成了目标检测模型的初始化操作。
分割数据集。
这一部分将数据集分割为训练数据集、验证数据集和测试数据集三类。先设置系统随机数SeedRand。再按照之前设置的分割比例,进行数据集的分割。Halcon的例程中使用了自定义函数split_dl_dataset完成这一步操作。该函数先从DLDataset中获取样本数据,将样本与标注的类对应起来。然后创建了数据字典,基于单个分类进行分割。在每个类别的图像中提取一定比例用于构建三类数据集。数据集预处理
先从模型中获取预处理参数,例程中使用了自定义函数create_dl_preprocess_param_from_model从深度学习网络中提取预处理参数,如:
'type'
'image_width'
'image_height'
'image_num_channels'
'image_range_min'
'image_range_max'
'ignore_class_ids'
并创建预处理参数字典DLPreprocessParam。
接下来这部分是最耗时的,即数据的预处理。例程中使用了自定义的preprocess_dl_dataset算子,用于对数据字典中的DLDataset、DLPreprocessParam样本进行预处理。
获取DLDataset中的'samples',存为DLDatasetSamples。这里面DLDatasetSamples一共有400个样本。将每个样本保存为一个数据字典,并对样本进行预处理。处理的步骤包括给每一个DLSamples样本创建数据字典,获取样本的图像,从图像中获取标注框区域,存入DLSamples数据字典中等。预览预处理数据集
在开始训练之前,建议检查一遍预处理的数据集。使用get_dict_tuple算子从数据字典DLDataset中提取样本DatasetSamples。接着对其进行排序。读取排序后的样本并使用dev_display_dl_data算子将其显示出来。
ps:
在读取read_dl_dataset_from_coco时,如果要使用自己的数据集,需要先将标注文件转为coco格式的.json文件,这部分有空再写。
* * This example is part of a series of examples, which summarizes * the workflow for DL object detection. It uses the MVTec pill bag dataset. * * The four parts are: * 1. Creation of the model and dataset preprocessing. * 2. Training of the model. * 3. Evaluation of the trained model. * 4. Inference on new images. * * This example covers part 1: 'Creation of model and dataset preprocessing'. * * It explains how to create a DL object detection model (part 1.1) and * the need of adapting the data for this model (preprocessing, part 1.2). * dev_update_off () * * In this example, the preprocessing steps are explained in graphics windows, * before they are executed. Set the following parameter to false in order to * skip this visualization. ShowExampleScreens := true * if (ShowExampleScreens) * * Initial example windows and parameters. dev_example_init (ShowExampleScreens, ExampleInternals) * * Introduction text of example series. dev_display_screen_introduction_part_1 (ExampleInternals) stop () dev_display_screen_introduction_part_2 (ExampleInternals) stop () * * Introduction text about creation of object detection model. dev_display_screen_introduction_model (ExampleInternals) stop () * * Explain how to choose the image width and height. dev_display_screen_model_image_size (ExampleInternals) stop () * * Explain how to choose min_level and max_level. dev_display_screen_model_levels (ExampleInternals) stop () * * Explain how to choose num_subscales. dev_display_screen_model_subscales (ExampleInternals) stop () * * Explain how to choose aspect ratios. dev_display_screen_model_aspect_ratios (ExampleInternals) stop () * * Introduction text of preprocessing the dataset. dev_display_screen_preprocessing_introduction (ExampleInternals) stop () * * Explain object detection dataset. dev_display_screen_detection_data_part_1 (ExampleInternals) stop () dev_display_screen_detection_data_part_2 (ExampleInternals) stop () * * Explain splitting the dataset. dev_display_screen_split_dataset (ExampleInternals) stop () * * Explain how to preprocess the dataset. dev_display_screen_preprocessing_data (ExampleInternals) stop () * * Run the program. dev_display_screen_run_program (ExampleInternals) stop () endif * * ***************************************************** * ***************************************************** * ** Part 1.1: Create an object detection model *** * ***************************************************** * ***************************************************** * * ************************ * ** Set parameters *** * ************************ * * Set obligatory parameters. Backbone := 'pretrained_dl_classifier_compact.hdl' NumClasses := 10 * * Image dimensions of the network. Later, these values are * used to rescale the images during preprocessing. ImageWidth := 512 ImageHeight := 320 ImageNumChannels := 3 * * Set min_level, max_level, num_subscales, and aspect_ratios. MinLevel := 2 MaxLevel := 4 NumSubscales := 3 AspectRatios := [1.0,0.5,2.0] * * Set capacity to 'medium', which is sufficient for this task * and delivers better inference and training speed. Compared to * 'high', the model with 'medium' is more than twice as fast, * while showing almost the same detection performance. Capacity := 'medium' * * ******************************************* * ** Create the object detection model *** * ******************************************* * * Create dictionary for generic parameters and create the object detection model. 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, 'num_subscales', NumSubscales) set_dict_tuple (DLModelDetectionParam, 'aspect_ratios', AspectRatios) set_dict_tuple (DLModelDetectionParam, 'capacity', Capacity) * * Create the model. create_dl_model_detection (Backbone, NumClasses, DLModelDetectionParam, DLModelHandle) * * * **************************************** * **************************************** * ** Part 1.2: Preprocess the data *** * **************************************** * **************************************** * * ************************************ * ** Set input and output paths *** * ************************************ * * All example data is written to this folder. ExampleDataDir := 'detect_pills_data' * get_system ('example_dir', HalconExampleDir) * Path to the image directory. HalconImageDir:= HalconExampleDir + '/images/' * Path to the Json file of the dataset. PillBagJsonFile := HalconExampleDir + '/hdevelop/Deep-Learning/Detection/pill_bag.json' * * Write the initialized DL object detection model to train it in example part 2. DLModelFileName := ExampleDataDir + '/pretrained_dl_model_detection.hdl' * Dataset directory for any outputs written by preprocess_dl_dataset. DataDirectory := ExampleDataDir + '/dldataset_pill_bag_' + ImageWidth + 'x' + ImageHeight * Store preprocess parameters separately in order to use it e.g. during inference. PreprocessParamFileName := DataDirectory + '/dl_preprocess_param_' + ImageWidth + 'x' + ImageHeight + '.hdict' * * ************************ * ** Set parameters *** * ************************ * * Percentages for splitting the dataset. TrainingPercent := 70 ValidationPercent := 15 * * In order to get a reproducible split we set a random seed. * This means that re-running the script results in the same split of DLDataset. SeedRand := 42 * * *************************************************** * ** Read the labeled dataset and adapt model *** * *************************************************** * * Create the output directory if it does not exist yet. file_exists (ExampleDataDir, FileExists) if (not FileExists) make_dir (ExampleDataDir) endif * * Read the dataset from coco file. read_dl_dataset_from_coco (PillBagJsonFile, HalconImageDir, [], DLDataset) * * Set class IDs from dataset in model. get_dict_tuple (DLDataset, 'class_ids', ClassIDs) set_dl_model_param (DLModelHandle, 'class_ids', ClassIDs) * * Write the initialized DL object detection model * to train it later in part 2. write_dl_model (DLModelHandle, DLModelFileName) * *********************************************************** * ** Split the dataset into train/validation and test *** * *********************************************************** * * In order to get reproducible results we set a seed here. set_system ('seed_rand', SeedRand) * * Generate the split. split_dl_dataset (DLDataset, TrainingPercent, ValidationPercent, []) * ********************************* * ** Preprocess the dataset *** * ********************************* * * Get preprocessing parameters from model. create_dl_preprocess_param_from_model (DLModelHandle, 'false', 'full_domain', [], [], [], DLPreprocessParam) * * Preprocess the dataset. This might take a few minutes. create_dict (GenParam) set_dict_tuple (GenParam, 'overwrite_files', true) preprocess_dl_dataset (DLDataset, DataDirectory, DLPreprocessParam, GenParam, DLDatasetFilename) * * Write preprocessing parameters to use them in later parts. write_dict (DLPreprocessParam, PreprocessParamFileName, [], []) * ******************************************* * ** Preview the preprocessed dataset *** * ******************************************* * * Before moving on to training, it is recommended to check the preprocessed dataset. * * Display the DLSamples for 10 randomly selected train images. get_dict_tuple (DLDataset, 'samples', DatasetSamples) find_dl_samples (DatasetSamples, 'split', 'train', 'match', SampleIndices) tuple_shuffle (SampleIndices, ShuffledIndices) read_dl_samples (DLDataset, ShuffledIndices[0:9], DLSampleBatchDisplay) * * Set parameters for dev_display_dl_data. create_dict (WindowHandleDict) create_dict (GenParam) set_dict_tuple (GenParam, 'scale_windows', 1.2) * * Display the samples in DLSampleBatchDisplay. for Index := 0 to |DLSampleBatchDisplay| - 1 by 1 * * Loop over samples in DLSampleBatchDisplay. dev_display_dl_data (DLSampleBatchDisplay[Index], [], DLDataset, 'bbox_ground_truth', GenParam, WindowHandleDict) get_dict_tuple (WindowHandleDict, 'bbox_ground_truth', WindowHandles) * * Add explanatory text. dev_set_window (WindowHandles[0]) get_dict_object (Image, DLSampleBatchDisplay[Index], 'image') get_image_size (Image, ImageWidth, ImageHeight) dev_disp_text ('New image size after preprocessing: ' + ImageWidth + ' x ' + ImageHeight, 'window', 'bottom', 'right', 'black', [], []) * dev_set_window (WindowHandles[1]) dev_disp_text ('Press Run (F5) to continue', 'window', 'bottom', 'right', 'black', [], []) stop () endfor * * Close windows that have been used for visualization. dev_display_dl_data_close_windows (WindowHandleDict) * if (ShowExampleScreens) * Hint to the DL detection training process example. dev_disp_end_of_program (ExampleInternals) stop () * Close example windows. dev_close_example_windows (ExampleInternals) endif
未完待续。。。。。

