halcon20.05示例程序
*
* 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 + '/bottles'
ImageSubDirs := ['good','broken_large','broken_small','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 [].
AnomalyDir := HalconImages + '/labels/bottles'
*
* Folder where the preprocessed samples will be stored.
OutputDir := './anomaly_bottle_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.
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 (GenParamDataset)
set_dict_tuple (GenParamDataset, 'image_sub_dirs', ImageSubDirs)
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.
split_dl_dataset (DLDataset, 50, 10, [])
*
* 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)
set_dl_model_param (DLModelHandle, 'runtime', 'gpu')
set_dl_model_param (DLModelHandle, 'runtime_init', 'immediately')
*
* Set preprocessing parameters and preprocess.
create_dict (PreprocessSettings)
set_dict_tuple (PreprocessSettings, 'overwrite_files', true)
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 (DLDataset, DLModelHandle, TrainParam, 0, TrainResults, TrainInfos, EvaluationInfos)
dev_disp_text ('Press Run (F5) to continue', 'window', 'bottom', 'right', 'black', [], [])
stop ()
*
dev_close_window ()
*
* Store the trained model.
write_dl_model (DLModelHandle, 'model_final.hdl')
*
*
* *** 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
* 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.
set_dict_tuple (GenParamDisplay, 'classification_threshold_index', 2)
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)
*
*
* *** 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[2]
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 min2(|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)
无注释版
dev_update_off ()
dev_close_window ()
set_system ('seed_rand', 73)
* *** 0.) SET INPUT/OUTPUT PATHS ***
get_image_dir (HalconImages)
ImageDir := HalconImages + '/bottles'
ImageSubDirs := ['good','broken_large','broken_small','contamination']
AnomalyDir := HalconImages + '/labels/bottles'
OutputDir := './anomaly_bottle_data'
ExampleSpecificPreprocessing := true
ImageWidth := 320
ImageHeight := 320
Complexity := 15
* *** 1.) PREPARE ***
create_dict (GenParamDataset)
set_dict_tuple (GenParamDataset, 'image_sub_dirs', ImageSubDirs)
read_dl_dataset_anomaly (ImageDir, AnomalyDir, [], [], GenParamDataset, DLDataset)
split_dl_dataset (DLDataset, 50, 10, [])
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)
set_dl_model_param (DLModelHandle, 'runtime', 'gpu')
set_dl_model_param (DLModelHandle, 'runtime_init', 'immediately')
create_dict (PreprocessSettings)
set_dict_tuple (PreprocessSettings, 'overwrite_files', true)
create_dl_preprocess_param ('anomaly_detection', ImageWidth, ImageHeight, 3, [], [], 'constant_values', 'full_domain', [], [], [], [], DLPreprocessParam)
preprocess_dl_dataset (DLDataset, OutputDir, DLPreprocessParam, PreprocessSettings, DLDatasetFileName)
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
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 ***
EnableDisplay := true
ErrorThreshold := 0.001
MaxNumEpochs := 15
DomainRatio := 0.25
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)
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 ()
write_dl_model (DLModelHandle, 'model_final.hdl')
* *** 3.) EVALUATE ***
StandardDeviationFactor := 1.0
set_dl_model_param (DLModelHandle, 'standard_deviation_factor', StandardDeviationFactor)
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 ()
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)
create_dict (GenParamDisplay)
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)
set_dict_tuple (GenParamDisplay, 'display_mode', ['pie_charts_precision','pie_charts_recall','absolute_confusion_matrix'])
set_dict_tuple (GenParamDisplay, 'classification_threshold_index', 2)
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)
* *** 4.) INFER ***
list_image_files (ImageDir + '/' + ImageSubDirs, 'default', 'recursive', ImageFiles)
tuple_shuffle (ImageFiles, ImageFilesShuffled)
InferenceClassificationThreshold := AnomalyClassificationThresholds[2]
InferenceSegmentationThreshold := AnomalySegmentationThreshold
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 min2(|ImageFilesShuffled|,10) - 1 by 1
read_image (Image, ImageFilesShuffled[IndexInference])
gen_dl_samples_from_images (Image, DLSample)
preprocess_dl_samples (DLSample, DLPreprocessParam)
if (ExampleSpecificPreprocessing)
preprocess_dl_samples_bottle (DLSample)
endif
apply_dl_model (DLModelHandle, DLSample, [], DLResult)
threshold_dl_anomaly_results (InferenceSegmentationThreshold, InferenceClassificationThreshold, DLResult)
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)