使用版本:Halcon21.05,内含深度学习模块
1.确定阈值
计算阈值使用compute_dl_anomaly_thresholds算子,具体解释:
get_dl_model_param (DLModelHandle, 'type', ModelType):请求模型对图像施加的要求
DLModelHandle含有的参数:
get_dict_tuple (DLDataset, 'samples', DLSamples):将数据集参数传给模型
DLDataSet中的参数:
具体到每张图片,会根据文件名给分为ok还是ng
get_dict_param (DLSamples[0], 'key_exists', 'split', SplitExists):查询数据集参数
*
* Deep learning anomaly detection example.
*
* This example demonstrates the general workflow for anomaly detection
* based on deep learning.
*
* The workflow typically consists of four steps which are described here:
* 1. Dataset preprocessing.
* 2. Training of the model and threshold estimation on 'ok' images.
* 3. Qualitative evaluation of the trained model.
* 4. Inference on new images.
*
dev_update_off ()
dev_close_window ()
set_system ('seed_rand', 73)
*
*
* *** 0.) SET INPUT/OUTPUT PATHS ***
*
* Set path to data.
get_image_dir (HalconImages)
*
* Base directory containing the folders with the used images.
* There must be a 'good' or 'ok' subfolder in ImageDir.
* For training, only images in the 'good' or 'ok' folders are used.
* Images in subfolders named differently will be treated as containing anomalies.
* They can be used for qualitative evaluation later.
*
* Note: You can immediately train an anomaly detection model on your own data as long
* as your images not showing any anomaly are located in a subfolder called 'good' or 'ok'.
ImageDir := HalconImages + '/bottlegap'
*'C:/Users/Leonardo/AppData/Roaming/MVTec/HALCON-21.05-Progress/examples/images/bottles'
*图片分类(好的和坏的)
ImageSubDirs := ['good','contamination']
*
* Folder where the ground truth anomaly regions are stored.
* This folder is not required for training.
* If there is no ground truth data available, set AnomalyDir to [].
*存放标签的文件夹
*train不用这个文件夹
*如果没有标签,可以将AnomalyDir设置为[]
AnomalyDir := HalconImages + '/labels/bottlegap'
*
* Folder where the preprocessed samples will be stored.
OutputDir := './anomaly_bottlegap_data'
*
* Dataset specific preprocessing.
*对数据集进行预处理
ExampleSpecificPreprocessing := true
*
* Set image size. It should be large enough if the defects are small.
* Please refer to the documentation of read_dl_model for possible restrictions
* depending on the network.
*设置图像大小。如果缺陷很小,它应该足够大。
*有关可能的限制,请参阅read_dl_model的文档
*这取决于网络
ImageWidth := 320
ImageHeight := 320
*
* Set the complexity of the model which roughly describes the capability of the model
* to handle complex application images. A higher value can improve the performance but
* increases the time needed to train the model.
*设定模型复杂性,用来描述模型的能力以处理复杂的应用程序图像。较高的值可以提高性能,但增加了训练模型所需的时间。
Complexity := 15
*
*
* *** 1.) PREPARE ***
*
* Read and preprocess an anomaly detection dataset.
* For optimal performance it is beneficial to do a custom
* preprocessing step that defines input domains.
*
* Load and split the dataset.
*加载并拆分数据集
*create_dict 创建一个新的空字典并且返回handle(字典用法和python差不多)
create_dict (GenParamDataset)
*创建类别标签字典(木有作用)
set_dict_tuple (GenParamDataset, 'image_sub_dirs', ImageSubDirs)
*转换数据集的信息内容,DLDataset,作为一个数据库并存储关于数据的所有必要信息
read_dl_dataset_anomaly (ImageDir, AnomalyDir, [], [], GenParamDataset, DLDataset)
*
* Note: make sure that every split contains at least one 'ok' image.
* For a small number of images in the dataset you might need to increase
* the validation fraction.
*拆分字典DLDataset表示的数据集
split_dl_dataset (DLDataset, 50, 10, [])
* 加载异常检测模型
*首先利用read_dl_model读取模型
*操作读取由编写的深度学习模型。结果,返回句柄DLModelHandle
* Load the anomaly detection model and set parameters.
* For documentation see set_dl_model_param () and get_dl_model_param ().
read_dl_model ('initial_dl_anomaly_medium.hdl', DLModelHandle)
*设置模型参数
set_dl_model_param (DLModelHandle, 'image_width', ImageWidth)
set_dl_model_param (DLModelHandle, 'image_height', ImageHeight)
set_dl_model_param (DLModelHandle, 'complexity', Complexity)
* In this example, the training of the anomaly detection model is done on the CPU.
*利用CPU完成训练
query_available_dl_devices (['runtime','id'], ['gpu',0], DLDevice)
set_dl_model_param (DLModelHandle, 'device', DLDevice)
* 设置预处理参数并进行预处理
* Set preprocessing parameters and preprocess.
create_dict (PreprocessSettings)
set_dict_tuple (PreprocessSettings, 'overwrite_files', true)
*将所有参数存储到DLPreprocessParam字典中
create_dl_preprocess_param ('anomaly_detection', ImageWidth, ImageHeight, 3, [], [], 'constant_values', 'full_domain', [], [], [], [], DLPreprocessParam)
*对数据进行预处理
preprocess_dl_dataset (DLDataset, OutputDir, DLPreprocessParam, PreprocessSettings, DLDatasetFileName)
*
* Run a specific preprocessing for this example.
* Note: For your own application, this step needs to be adapted.
* In case the possible areas for defects (ROI) on the images can be restricted,
* we recommend to define these areas as domains. For this example, this is
* done in the exemplary procedure preprocess_dl_sample_bottle.
get_dict_tuple (DLDataset, 'samples', DatasetSamples)
if (ExampleSpecificPreprocessing)
read_dl_samples (DLDataset, [0:|DatasetSamples| - 1], DLSampleBatch)
preprocess_dl_samples_bottle (DLSampleBatch)
write_dl_samples (DLDataset, [0:|DatasetSamples| - 1], DLSampleBatch, [], [])
endif
*
* Visually inspect ten randomly selected preprocessed DLSamples.
create_dict (WindowDict)
for Index := 0 to 9 by 1
SampleIndex := int(rand(1) * |DatasetSamples|)
read_dl_samples (DLDataset, SampleIndex, DLSample)
dev_display_dl_data (DLSample, [], DLDataset, 'anomaly_ground_truth', [], WindowDict)
dev_disp_text ('Press Run (F5) to continue', 'window', 'bottom', 'right', 'black', [], [])
*
get_dict_tuple (WindowDict, 'anomaly_ground_truth', WindowHandles)
dev_set_window (WindowHandles[0])
dev_disp_text ('Preprocessed image', 'window', 'top', 'left', 'black', [], [])
*
stop ()
endfor
dev_close_window_dict (WindowDict)
*
stop ()
* 模型训练
*
* *** 2.) TRAIN ***
*
* Create training parameters.
*
* Control whether the training progress is displayed (true/false).
EnableDisplay := true
*
* Set a threshold for the training error and a maximum number of training epochs.
* If the training error falls below this threshold, the training is finished.
* Otherwise the training continues until the maximum number of epochs is reached.
*设置训练错误的阈值和最大训练周期数。
*如果训练误差低于此阈值,则训练结束
*否则,训练将继续进行,直到达到最大周期数。
ErrorThreshold := 0.001
MaxNumEpochs := 15
*
* Set the domain ratio which controls the fraction of each image used for training.
* The training result might be improved by setting a greater value, but this also
* increases the training time.
*设置控制用于训练的每个图像的分数的域比率。
*通过设置更大的值,可以提高训练结果,但这也是
*增加了训练时间。
DomainRatio := 0.25
*
* Regularization noise can make the training more robust. In case the training fails,
* setting a higher value might help.
*正则化噪声可以使训练更健壮。如果训练失败,
*设置更高的值可能会有所帮助。
RegularizationNoise := 0.01
* 创建上述参数组成的字典
create_dict (TrainParamAnomaly)
set_dict_tuple (TrainParamAnomaly, 'regularization_noise', RegularizationNoise)
set_dict_tuple (TrainParamAnomaly, 'error_threshold', ErrorThreshold)
set_dict_tuple (TrainParamAnomaly, 'domain_ratio', DomainRatio)
create_dl_train_param (DLModelHandle, MaxNumEpochs, [], EnableDisplay, 73, 'anomaly', TrainParamAnomaly, TrainParam)
*
* The training and thus the call of train_dl_model_anomaly_dataset ()
* is done using the following procedure. This may take some time.
*训练,并因此调用train_dl_model_anomaly_dataset()
*使用以下步骤完成。这可能需要一些时间。
train_dl_model (DLDataset, DLModelHandle, TrainParam, 0, TrainResults, TrainInfos, EvaluationInfos)
dev_disp_text ('Press Run (F5) to continue', 'window', 'bottom', 'right', 'black', [], [])
stop ()
*
dev_close_window ()
*
*
* *** 3.) EVALUATE ***
* *计算分类和分割阈值并执行评估。
* Calculate classification and segmentation thresholds and perform evaluation.
* 设置用于计算异常分数的因子。
* Set the factor used to calculate the anomaly score. See the documentation of
* get_dl_model_param for details.
* This parameter can help to improve the anomaly score for a better classification
* between 'ok' and 'nok' images. For example, in case the defects are small, a larger
* value might be suitable.
StandardDeviationFactor := 1.0
set_dl_model_param (DLModelHandle, 'standard_deviation_factor', StandardDeviationFactor)
*
* Estimate threshold values. They are used to determine whether a pixel or image
*估计阈值,用来确定是否为异常
*compute_dl_anomaly_threresholds返回基于所用数据集的可能建议。根据应用,手动微调可能是有益的。
* is regarded as anomalous. The procedure compute_dl_anomaly_thresholds returns
* possible suggestions based on the dataset used. Depending on the application, manual
* fine-tuning may be beneficial.
create_dict (GenParamThreshold)
set_dict_tuple (GenParamThreshold, 'enable_display', 'true')
compute_dl_anomaly_thresholds (DLModelHandle, DLDataset, GenParamThreshold, AnomalySegmentationThreshold, AnomalyClassificationThresholds)
dev_disp_text ('Press Run (F5) to continue', 'window', 'bottom', 'right', 'black', [], [])
stop ()
*
dev_close_window ()
*
* Set generic evaluation parameters and evaluate the model on the test split.
create_dict (GenParamEvaluation)
set_dict_tuple (GenParamEvaluation, 'measures', 'all')
set_dict_tuple (GenParamEvaluation, 'anomaly_classification_thresholds', AnomalyClassificationThresholds)
evaluate_dl_model (DLDataset, DLModelHandle, 'split', 'test', GenParamEvaluation, EvaluationResult, EvalParams)
*
* Set display parameters.
create_dict (GenParamDisplay)
*
* Visualize the histogram over the anomaly scores and with it the classification
* thresholds used for the evaluation.
set_dict_tuple (GenParamDisplay, 'display_mode', ['score_histogram','score_legend'])
create_dict (WindowDict)
dev_display_anomaly_detection_evaluation (EvaluationResult, EvalParams, GenParamDisplay, WindowDict)
dev_disp_text ('Press Run (F5) to continue', 'window', 'bottom', 'right', 'black', 'box', 'true')
stop ()
*
dev_close_window_dict (WindowDict)
*
* Visualize evaluation results such as precision, recall, and confusion matrix
* for a given classification threshold.
set_dict_tuple (GenParamDisplay, 'display_mode', ['pie_charts_precision','pie_charts_recall','absolute_confusion_matrix'])
* Select evaluation results for one threshold by its index in
* AnomalyClassificationThresholds for display. We use the last
* one of the computed AnomalyClassificationThresholds. Note that
* you have to use the AnomalyClassificationThreshold which suits
* your application best.
ClassificationThresholdIndex := |AnomalyClassificationThresholds| - 1
set_dict_tuple (GenParamDisplay, 'classification_threshold_index', ClassificationThresholdIndex)
create_dict (WindowDict)
dev_display_anomaly_detection_evaluation (EvaluationResult, EvalParams, GenParamDisplay, WindowDict)
dev_disp_text ('Press Run (F5) to continue', 'window', 'bottom', 'right', 'black', [], [])
stop ()
*
dev_close_window_dict (WindowDict)
*
* Store the trained model.
write_dl_model (DLModelHandle, 'model_final.hdl')
*
*
* *** 4.) INFER ***
*
* To demonstrate the inference steps, we apply the
* trained model to some randomly chosen example images.
list_image_files (ImageDir + '/' + ImageSubDirs, 'default', 'recursive', ImageFiles)
tuple_shuffle (ImageFiles, ImageFilesShuffled)
*
* Choose thresholds for inference.
InferenceClassificationThreshold := AnomalyClassificationThresholds[ClassificationThresholdIndex]
InferenceSegmentationThreshold := AnomalySegmentationThreshold
*
* Create dictionary with dataset parameters used for display.
create_dict (DLDatasetInfo)
set_dict_tuple (DLDatasetInfo, 'class_names', ['ok','nok'])
set_dict_tuple (DLDatasetInfo, 'class_ids', [0,1])
*
create_dict (WindowDict)
for IndexInference := 0 to max2(|ImageFilesShuffled|,10) - 1 by 1
read_image (Image, ImageFilesShuffled[IndexInference])
gen_dl_samples_from_images (Image, DLSample)
preprocess_dl_samples (DLSample, DLPreprocessParam)
*
* Use the same dataset specific preprocessing as for training.
if (ExampleSpecificPreprocessing)
preprocess_dl_samples_bottle (DLSample)
endif
*
apply_dl_model (DLModelHandle, DLSample, [], DLResult)
*
* Apply thresholds to classify regions and the entire image.
threshold_dl_anomaly_results (InferenceSegmentationThreshold, InferenceClassificationThreshold, DLResult)
*
* Display the inference result.
dev_display_dl_data (DLSample, DLResult, DLDatasetInfo, ['anomaly_result','anomaly_image'], [], WindowDict)
dev_disp_text ('Press F5 (continue)', 'window', 'bottom', 'center', 'black', [], [])
stop ()
endfor
*
dev_close_window_dict (WindowDict)