1.最近使用halcon分类模型测试样品,感觉halcon自身带的demo,有很多封装起来的函数,不容易查看整个训练的原理,所以用halcon基本函数重写了模型训练跟推理的过程,及热图获取。
2.代码如下:
******
*简单化深度学习分类训练
*******
dev_update_off()
*获取当前window的句柄
dev_get_window(WindowHandle)
*为了获得可重复的分裂,我们设置了一个随机种子。
*这意味着重新运行脚本会导致相同的DLDataset分割。
SeedRand := 42
* 设置随机种子。
set_system ('seed_rand', SeedRand)
*********图片预处理************
***训练图片路径文件夹
image_dir:='D:/Source/SourceMe/HalconDeelLearn/HalconDeelLearnClassification/TestTrain'
***创建一个训练数据字典***
create_dict(DLTrainDataset)
***设置图片训练的路径***
set_dict_tuple(DLTrainDataset, 'image_dir', image_dir)
***设置类名***
class_names:=['ng','ok']
set_dict_tuple(DLTrainDataset, 'class_names', class_names)
***设置类id***
class_ids:=[0,1]
set_dict_tuple(DLTrainDataset, 'class_ids', class_ids)
***创建一个评估数据字典***
create_dict(DLValDataset)
***设置图片训练的路径***
set_dict_tuple(DLValDataset, 'image_dir', image_dir)
***设置类名***
class_names:=['ng','ok']
set_dict_tuple(DLValDataset, 'class_names', class_names)
***设置类id***
class_ids:=[0,1]
set_dict_tuple(DLValDataset, 'class_ids', class_ids)
***创建训练样品集合***
train_samples:=[]
***读取训练数据***
***获取最后一个样品引索***
count_train_samples:=|train_samples|
****读取第一个类数据****
train_frist_class_file_name_path_:=image_dir+'/train/ng'
* Image Acquisition 01: Code generated by Image Acquisition 01
list_files (train_frist_class_file_name_path_, ['files','follow_links'], ImageFiles)
tuple_regexp_select (ImageFiles, ['\\.(tif|tiff|gif|bmp|jpg|jpeg|jp2|png|pcx|pgm|ppm|pbm|xwd|ima|hobj)$','ignore_case'], ImageFiles)
for Index := 0 to |ImageFiles| - 1 by 1
read_image (Image, ImageFiles[Index])
create_dict(sample)
set_dict_tuple(sample, 'image_id', 0)
set_dict_tuple(sample, 'image_file_name', ImageFiles[Index])
set_dict_tuple(sample, 'image_label_id', 0)
set_dict_tuple(sample, 'split', 'train')
train_samples[Index+count_train_samples]:=sample
endfor
***获取最后一个样品引索***
count_train_samples:=|train_samples|
***读取第二个类数据***
train_second_class_file_name_path_:=image_dir+'/train/ok'
list_files (train_second_class_file_name_path_, ['files','follow_links'], ImageFiles)
tuple_regexp_select (ImageFiles, ['\\.(tif|tiff|gif|bmp|jpg|jpeg|jp2|png|pcx|pgm|ppm|pbm|xwd|ima|hobj)$','ignore_case'], ImageFiles)
for Index := 0 to |ImageFiles| - 1 by 1
read_image (Image, ImageFiles[Index])
create_dict(sample)
set_dict_tuple(sample, 'image_id', 1)
set_dict_tuple(sample, 'image_file_name', ImageFiles[Index])
set_dict_tuple(sample, 'image_label_id', 1)
set_dict_tuple(sample, 'split', 'train')
train_samples[Index+count_train_samples]:=sample
endfor
***读取评估数据***
stop()
***创建一个评估数据
val_samples:=[]
***获取最后一个样品引索***
count_val_samples:=|val_samples|
***读取第一个类评估数据***
****读取第一个类数据****
val_frist_class_file_name_path_:=image_dir+'/val/ng'
* Image Acquisition 01: Code generated by Image Acquisition 01
list_files (val_frist_class_file_name_path_, ['files','follow_links'], ImageFiles)
tuple_regexp_select (ImageFiles, ['\\.(tif|tiff|gif|bmp|jpg|jpeg|jp2|png|pcx|pgm|ppm|pbm|xwd|ima|hobj)$','ignore_case'], ImageFiles)
for Index := 0 to |ImageFiles| - 1 by 1
read_image (Image, ImageFiles[Index])
create_dict(sample)
set_dict_tuple(sample, 'image_id', 0)
set_dict_tuple(sample, 'image_file_name', ImageFiles[Index])
set_dict_tuple(sample, 'image_label_id', 0)
set_dict_tuple(sample, 'split', 'validation')
val_samples[Index+count_val_samples]:=sample
endfor
***获取最后一个样品引索***
count_val_samples:=|val_samples|
***读取第二个类数据***
val_second_class_file_name_path_:=image_dir+'/val/ok'
list_files (val_second_class_file_name_path_, ['files','follow_links'], ImageFiles)
tuple_regexp_select (ImageFiles, ['\\.(tif|tiff|gif|bmp|jpg|jpeg|jp2|png|pcx|pgm|ppm|pbm|xwd|ima|hobj)$','ignore_case'], ImageFiles)
for Index := 0 to |ImageFiles| - 1 by 1
read_image (Image, ImageFiles[Index])
create_dict(sample)
set_dict_tuple(sample, 'image_id', 1)
set_dict_tuple(sample, 'image_file_name', ImageFiles[Index])
set_dict_tuple(sample, 'image_label_id', 1)
set_dict_tuple(sample, 'split', 'validation')
val_samples[Index+count_val_samples]:=sample
endfor
stop()
***给入数据字典****
set_dict_tuple(DLTrainDataset, 'samples', train_samples)
set_dict_tuple(DLValDataset, 'samples', val_samples)
***生成预处理数据***
create_dict(DLPreprocessParam)
***给入分类***
set_dict_tuple(DLPreprocessParam, 'model_type', 'classification')
***给入训练图片宽***
set_dict_tuple(DLPreprocessParam, 'image_width', 300)
***给入训练图片长***
set_dict_tuple(DLPreprocessParam, 'image_height', 300)
***给入训练图片通道数***
set_dict_tuple(DLPreprocessParam, 'image_num_channels', 3)
***给入图片灰度范围***
set_dict_tuple(DLPreprocessParam, 'image_range_min', -127)
***给入图片灰度范围***
set_dict_tuple(DLPreprocessParam, 'image_range_max', 128)
***是否归一***
set_dict_tuple(DLPreprocessParam, 'normalization','none')
******
set_dict_tuple(DLPreprocessParam, 'domain_handling', 'full_domain')
***是否增强数据***
set_dict_tuple(DLPreprocessParam, 'augmentation', 'false')
set_dict_tuple(DLPreprocessParam, 'check_params', 0)
***储存预处理参数**
set_dict_tuple (DLTrainDataset, 'preprocess_param', DLPreprocessParam)
set_dict_tuple (DLValDataset, 'preprocess_param', DLPreprocessParam)
***数据路径
DataDirectory:=image_dir+'/DataDirectory'
***预处理数据字典保存路径**
DLDatasetTrainFileName := DataDirectory + '/dl_dataset_train.hdict'
DLDatasetValFileName := DataDirectory + '/dl_dataset_val.hdict'
***预处理样品路径***
DLTrainSampleDir := DataDirectory + '/trainsamples'
DLValSampleDir := DataDirectory + '/valsamples'
****预处理参数保存路径
PreprocessParamterSavePath:=DataDirectory+'/dl_preprocess_param.hdict'
****创建数据路径
make_dir (DataDirectory)
****创建样品
make_dir (DLTrainSampleDir)
make_dir (DLValSampleDir)
***设置样品路径
set_dict_tuple (DLTrainDataset, 'dlsample_dir', DLTrainSampleDir)
set_dict_tuple (DLValDataset, 'dlsample_dir', DLValSampleDir)
*****生成预处理训练数据的字典
get_dict_tuple (DLTrainDataset, 'samples', DLDatasetTrainSamples)
for sample_index:=0 to |DLDatasetTrainSamples| -1 by 1
****获取预处理参数
get_dict_tuple (DLPreprocessParam, 'image_width', ImageWidth)
get_dict_tuple (DLPreprocessParam, 'image_height', ImageHeight)
get_dict_tuple (DLPreprocessParam, 'image_num_channels', ImageNumChannels)
get_dict_tuple (DLPreprocessParam, 'image_range_min', ImageRangeMin)
get_dict_tuple (DLPreprocessParam, 'image_range_max', ImageRangeMax)
get_dict_tuple (DLPreprocessParam, 'domain_handling', DomainHandling)
get_dict_tuple (DLPreprocessParam, 'normalization', NormalizationType)
get_dict_tuple (DLPreprocessParam, 'model_type', ModelType)
DLDatasetSample:=DLDatasetTrainSamples[sample_index]
get_dict_tuple(DLDatasetTrainSamples[sample_index], 'image_id', image_id)
get_dict_tuple(DLDatasetTrainSamples[sample_index], 'image_label_id', image_label_id)
get_dict_tuple(DLDatasetTrainSamples[sample_index], 'image_file_name', image_file_name)
create_dict(DLSampleBatch)
set_dict_tuple(DLSampleBatch, 'image_id', image_id)
set_dict_tuple(DLSampleBatch, 'image_label_id', image_label_id)
read_image(Image, image_file_name)
count_obj (Image, NumImages)
get_image_type (Image, Type)
count_channels (Image, InputNumChannels)
if (DomainHandling == 'full_domain')
full_domain (Image, Image)
endif
****预处理图片
zoom_image_size(Image, Image, ImageWidth, ImageHeight, 'constant')
convert_image_type(Image, Image, 'real')
RescaleRange := (ImageRangeMax - ImageRangeMin) / 255.0
select_obj (Image, ImageSelected, 1)
scale_image (ImageSelected, ImageSelected, RescaleRange, ImageRangeMin)
replace_obj (Image, ImageSelected, Image, 1)
set_dict_object(Image, DLSampleBatch, 'image')
****保存预处理数据
get_dict_tuple (DLTrainDataset, 'dlsample_dir', OutDir)
FileNameOut := sample_index + '_dlsample.hdict'
write_dict (DLSampleBatch, OutDir + '/' + FileNameOut, 'raise_error_if_content_not_serializable', true)
set_dict_tuple(DLDatasetSample, 'dlsample_file_name', FileNameOut)
endfor
****保存预处理字典
write_dict (DLTrainDataset, DLDatasetTrainFileName, [], [])
stop()
*****生成预处理评估数据的字典
get_dict_tuple (DLValDataset, 'samples', DLDatasetValSamples)
for sample_index:=0 to |DLDatasetValSamples| -1 by 1
****获取预处理参数
get_dict_tuple (DLPreprocessParam, 'image_width', ImageWidth)
get_dict_tuple (DLPreprocessParam, 'image_height', ImageHeight)
get_dict_tuple (DLPreprocessParam, 'image_num_channels', ImageNumChannels)
get_dict_tuple (DLPreprocessParam, 'image_range_min', ImageRangeMin)
get_dict_tuple (DLPreprocessParam, 'image_range_max', ImageRangeMax)
get_dict_tuple (DLPreprocessParam, 'domain_handling', DomainHandling)
get_dict_tuple (DLPreprocessParam, 'normalization', NormalizationType)
get_dict_tuple (DLPreprocessParam, 'model_type', ModelType)
DLDatasetSample:=DLDatasetValSamples[sample_index]
get_dict_tuple(DLDatasetValSamples[sample_index], 'image_id', image_id)
get_dict_tuple(DLDatasetValSamples[sample_index], 'image_label_id', image_label_id)
get_dict_tuple(DLDatasetValSamples[sample_index], 'image_file_name', image_file_name)
create_dict(DLSampleBatch)
set_dict_tuple(DLSampleBatch, 'image_id', image_id)
set_dict_tuple(DLSampleBatch, 'image_label_id', image_label_id)
read_image(Image, image_file_name)
count_obj (Image, NumImages)
get_image_type (Image, Type)
count_channels (Image, InputNumChannels)
if (DomainHandling == 'full_domain')
full_domain (Image, Image)
endif
****预处理图片
zoom_image_size(Image, Image, ImageWidth, ImageHeight, 'constant')
convert_image_type(Image, Image, 'real')
RescaleRange := (ImageRangeMax - ImageRangeMin) / 255.0
select_obj (Image, ImageSelected, 1)
scale_image (ImageSelected, ImageSelected, RescaleRange, ImageRangeMin)
replace_obj (Image, ImageSelected, Image, 1)
set_dict_object(Image, DLSampleBatch, 'image')
****保存预处理数据
get_dict_tuple (DLValDataset, 'dlsample_dir', OutDir)
FileNameOut := sample_index + '_dlsample.hdict'
write_dict (DLSampleBatch, OutDir + '/' + FileNameOut, 'raise_error_if_content_not_serializable', true)
set_dict_tuple(DLDatasetSample, 'dlsample_file_name', FileNameOut)
endfor
****保存预处理字典
write_dict (DLValDataset, DLDatasetValFileName, [], [])
*单独存储预处理参数,以便在推理期间使用它。
write_dict(DLPreprocessParam, PreprocessParamterSavePath, [], [])
******读取预处理数据显示下
stop()
*******训练
***获取gpu或cpu设备训练
query_available_dl_devices ('runtime', 'gpu', DLDeviceHandles)
if (|DLDeviceHandles| == 0)
throw ('No supported device found to continue this example.')
endif
DLDevice := DLDeviceHandles[0]
*检测训练驱动是cpu还是gpu
get_dl_device_param (DLDevice, 'type', DLDeviceType)
if (DLDeviceType == 'cpu')
*使用的线程数可能会有影响
*关于培训时间。
NumThreadsTraining := 4
set_system ('thread_num', NumThreadsTraining)
endif
***读取模型
read_dl_model('pretrained_dl_classifier_compact.hdl', DLModelHandle)
*设置动量采用默认
set_dl_model_param (DLModelHandle, 'momentum', 0.5)
******设置分类名称*******
get_dict_tuple (DLTrainDataset, 'class_names', ClassNames)
set_dl_model_param (DLModelHandle, 'class_names', ClassNames)
*获取维度
get_dict_tuple (DLPreprocessParam, 'image_width', ImageWidth)
get_dict_tuple (DLPreprocessParam, 'image_height', ImageHeight)
get_dict_tuple (DLPreprocessParam, 'image_num_channels', ImageNumChannels)
*设置模型维度
set_dl_model_param (DLModelHandle, 'image_dimensions', [ImageWidth,ImageHeight,ImageNumChannels])
BatchSize:=4
*设置批量
set_dl_model_param (DLModelHandle, 'batch_size', BatchSize)
*设置训练的设备
set_dl_model_param (DLModelHandle, 'device', DLDevice)
***初始化模型学习率
set_dl_model_param(DLModelHandle, 'learning_rate', 0.0001)
***模型训练周期次数
NumEpochs:=100
***数据批次的计数
DatasetSampleIndex:=0
***训练结果的集合
TrainResultsIndex:=0
TrainResults:=[]
***创建一个显示训练的窗口
dev_open_window(0, 0, 512, 512, 'black', WindowHandleTrain)
***创建一个显示信息的窗口
dev_open_window(0, 0, 512, 512, 'black', WindowHandleMessage)
**读取批量数据
get_dict_tuple(DLTrainDataset, 'samples', DatasetSamples)
SampleIndicesTrain := []
n:= ceil(NumEpochs)
for Index := 0 to ceil(NumEpochs) - 1 by 1
*tuple_shuffle (DatasetSamples, Shuffled)
n:=rand(|DatasetSamples|)
n:= sort_index(n)
ShuffleIndices := sort_index(rand(|DatasetSamples|))
Shuffled := DatasetSamples[ShuffleIndices]
SampleIndicesTrain := [SampleIndicesTrain,Shuffled]
endfor
NumIterationsPerEpoch := int(floor(|DatasetSamples| / real(BatchSize)))
NumIterations := int(NumIterationsPerEpoch * NumEpochs)
ComputeMeanLoss:=60
for NumEpoch:=0 to NumIterations by 1
***计算时间
count_seconds(Startime)
***显示训练信息
dev_set_window(WindowHandleMessage)
dev_disp_text('AllNumEpochs:'+NumIterations+' NumEpoch:'+NumEpoch, 'window', 10, 10, 'red', [], [])
* Get the dlsample_dir.
get_dict_tuple (DLTrainDataset, 'dlsample_dir', DictDir)
***判断要不要更换学习率
**批量是BatchSize,读取多小个样品
DLSampleBatch:=[]
for DLSamplesProIndex:=0 to BatchSize-1 by 1
if ((DatasetSampleIndex+DLSamplesProIndex)>=|SampleIndicesTrain|)
DatasetSampleIndex:=0
else
DatasetSampleIndex:=DatasetSampleIndex+DLSamplesProIndex
endif
DLSamplesProc := SampleIndicesTrain[DatasetSampleIndex]
get_dict_tuple (DLSamplesProc, 'dlsample_file_name', DictPath)
read_dict (DictDir + '/' + DictPath, [], [], DLSample)
DLSampleBatch[DLSamplesProIndex]:=DLSample
***显示训练图片
get_dict_object(train_pre_image, DLSampleBatch[DLSamplesProIndex], 'image')
dev_set_window(WindowHandleTrain)
dev_display(train_pre_image)
endfor
***当前批次训练模型
train_dl_model_batch (DLModelHandle, DLSampleBatch, TrainResult)
***记录训练的结果
TrainResults[TrainResultsIndex]:=TrainResult
get_dict_tuple (TrainResult, 'total_loss', LossValue)
***显示平均loss
dev_set_window(WindowHandleMessage)
***显示当前loss
dev_disp_text('total_loss:'+LossValue, 'window', 100, 10, 'red', [], [])
if(TrainResultsIndex==ComputeMeanLoss)
***计算平均loss
LossValues:=[]
for LossValuesIndex:=0 to TrainResultsIndex by 1
get_dict_tuple (TrainResults[LossValuesIndex], 'total_loss', LossValue)
LossValues[LossValuesIndex]:=LossValue
endfor
LossMean := mean(LossValues)
***显示平均loss
dev_set_window(WindowHandleMessage)
***显示当前loss
dev_disp_text('mean_loss:'+LossMean, 'window', 200, 10, 'red', [], [])
TrainResultsIndex:=0
else
***下一次结果加一
TrainResultsIndex:=TrainResultsIndex+1
endif
count_seconds(Endtime)
t:=Endtime-Startime
all_t:=t*NumIterations
use_t:=t*NumEpoch
***显示时间
dev_set_window(WindowHandleMessage)
***显示时间
dev_disp_text('AllTime:'+all_t+'SpeedTime'+use_t, 'window', 300, 10, 'red', [], [])
endfor
stop()
dev_close_window()
dev_close_window()
*优化内存消耗
set_dl_model_param (DLModelHandle, 'optimize_for_inference', 'true')
**优化模型的路径
path_optimize_model_:=DataDirectory+'/optimize_model.hdl'
*重新模型
write_dl_model (DLModelHandle, path_optimize_model_)
********训练完推理
***读取模型
read_dl_model(path_optimize_model_, DLInferenceModel)
***读取预处理数据
read_dict(PreprocessParamterSavePath,[], [], PreprocessParameterInference)
***获取预处理参数
get_dict_tuple(PreprocessParameterInference, 'image_width', image_width)
get_dict_tuple(PreprocessParameterInference, 'image_height', image_height)
get_dict_tuple(PreprocessParameterInference, 'image_num_channels', image_num_channels)
get_dict_tuple(PreprocessParameterInference, 'image_range_min', image_range_min)
get_dict_tuple(PreprocessParameterInference, 'image_range_max', image_range_max)
get_dict_tuple(PreprocessParameterInference, 'normalization', normalization_type)
get_dict_tuple(PreprocessParameterInference, 'domain_handling', domain_handling)
***读取一张图片
read_image(Image, 'D:/Source/SourceMe/Halcon分类基本模型/Classify_all_step_simple/Data/train/ng/pill_ginseng_crack_008.png')
***生成DLSampleBatch
create_dict (DLInferenceSampleBatch)
****预处理图片
convert_image_type(Image, Image, 'real')
zoom_image_size(Image, Image, image_width, image_height, 'constant')
RescaleRange := (image_range_max - image_range_min) / 255.0
*select_obj (Image, ImageSelected, 1)
scale_image (Image, Image, RescaleRange, image_range_min)
*replace_obj (Image, ImageSelected, Image, 1)
set_dict_object(Image, DLInferenceSampleBatch, 'image')
apply_dl_model (DLModelHandle, DLInferenceSampleBatch, [], DLResultBatch)
***显示结果
DLResult := DLResultBatch[0]
get_dict_param(DLResult,'keys',[],dict_keys)
get_dict_tuple(DLResult, dict_keys[0], socres)
get_dict_tuple(DLResult, dict_keys[1], ids)
get_dict_tuple(DLResult, dict_keys[2], names)
dev_get_window(WindowHandle)
set_tposition(WindowHandle, 200, 200)
set_display_font(WindowHandle, 48, 'sans', 'false', 'false')
write_string(WindowHandle, names[0])
set_display_font(WindowHandle, 16, 'sans', 'false', 'false')
dev_disp_text ('socre:'+socres[0]+'-id:'+ids[0]+'-class:'+names[0], 'window', 'bottom', 'right', 'black', [], [])
stop()
***获取推理图片的热图信息
gen_dl_model_heatmap (DLModelHandle, DLInferenceSampleBatch, 'grad_cam', [], [], DLResult)
***获取热图字典
get_dict_tuple(DLResult, 'heatmap_grad_cam', DLSampleBatchHeatmapGradCam)
***获取热图
get_dict_param(DLSampleBatchHeatmapGradCam, 'key_exists', 'heatmap_image_class_0', GenParamValue)
if(GenParamValue==1)
get_dict_object(DLSampleBatchHeatImage, DLSampleBatchHeatmapGradCam, 'heatmap_image_class_0')
else
get_dict_object(DLSampleBatchHeatImage, DLSampleBatchHeatmapGradCam, 'heatmap_image_class_1')
endif
get_image_type (DLSampleBatchHeatImage, Type)
* The image LUT needs a byte image. Rescale real images.
***把图片变成0到255灰度
scale_image (DLSampleBatchHeatImage, DLSampleBatchHeatImage, 255, 0)
convert_image_type (DLSampleBatchHeatImage, DLSampleBatchHeatImage, 'byte')
*
X := [0:255]
tuple_gen_const (256, 0, Low)
tuple_gen_const (256, 255, High)
* Scheme Jet: from blue to red
OffR := 3.0 * 64.0
OffG := 2.0 * 64.0
OffB := 64.0
A1 := -4.0
A0 := 255.0 + 128.0
R := min2(max2(abs(X - OffR) * A1 + A0,Low),High)
G := min2(max2(abs(X - OffG) * A1 + A0,Low),High)
B := min2(max2(abs(X - OffB) * A1 + A0,Low),High)
lut_trans (DLSampleBatchHeatImage, ImageR, R)
lut_trans (DLSampleBatchHeatImage, ImageG, G)
lut_trans (DLSampleBatchHeatImage, ImageB, B)
compose3 (ImageR, ImageG, ImageB, ResultImage)
***获取预处理的图片
get_dict_object(DLSampleBatchImage, DLInferenceSampleBatch, 'image')
* Convert input image to byte image for visualization.
image_to_channels (DLSampleBatchImage, Channels)
count_channels (DLSampleBatchImage, NumChannels)
gen_empty_obj (ChannelsScaled)
for ChannelIndex := 1 to NumChannels by 1
select_obj (Channels, Channel, ChannelIndex)
min_max_gray (Channel, Channel, 0, ChannelMin, ChannelMax, _)
*scale_image_range (Channel, ChannelScaled, ChannelMin, ChannelMax)
Mult := real(255 - 0) / (ChannelMax - ChannelMin)
Add := -Mult * ChannelMin + 0
* Scale image.
scale_image (Channel, Channel, Mult, Add)
convert_image_type (Channel, ChannelScaledByte, 'byte')
concat_obj (ChannelsScaled, ChannelScaledByte, ChannelsScaled)
endfor
channels_to_image (ChannelsScaled, ImageByte)
* Note that ImageByte needs to have the same number of channels as
* RGBValueImage to display colormap image correctly.
count_channels (ImageByte, NumChannels)
if (NumChannels != 3)
* Just take the first channel and use this to generate
* an image with 3 channels for visualization.
access_channel (ImageByte, ImageByteR, 1)
copy_image (ImageByteR, ImageByteG)
copy_image (ImageByteR, ImageByteB)
compose3 (ImageByteR, ImageByteG, ImageByteB, ImageByte)
endif
add_image (ImageByte, ResultImage, RGBValueImage, 0.5, 0)
dev_display (RGBValueImage)
3.整体用接近halcon基础函数编写。