<think>我们正在详细说明数据准备阶段,即运行`create_defect_dataset.hdev`脚本的过程。这个阶段的目标是创建训练数据集,包括对每张训练图像中的缺陷区域进行标注,并指定每个缺陷的类别。标注数据将保存在`zinc_defect_dataset.hdict`文件中。###数据标注工具详细说明该脚本提供了一个交互式标注界面。用户需要为每张图像中的每个缺陷区域绘制轮廓,并选择对应的缺陷类别。以下是详细步骤及代码解释:####1.**初始化环境**```halcondev_close_window()dev_open_window(0,0,800,600,'black',WindowHandle)set_display_font(WindowHandle,16,'mono','true','false')```-关闭所有图形窗口,然后打开一个800x600像素的黑色背景窗口。-设置显示字体为等宽字体,字号16。####2.**定义缺陷类别**```halconDefectClasses:=['scratch','dent','stain','corrosion','inclusion','other']create_dict(AnnotationDict)set_dict_tuple(AnnotationDict,'classes',DefectClasses)set_dict_tuple(AnnotationDict,'samples',[])```-定义6种缺陷类别:划痕、凹痕、污点、腐蚀、夹杂物、其他。-创建一个字典`AnnotationDict`,用于存储整个数据集,包括类别列表和样本列表。####3.**加载训练图像**```halconImageDir:='C:/zinc_defects/train/'list_image_files(ImageDir,['format'],'recursive',ImageFiles)ImageCount:=|ImageFiles|SampleIndex:=0```-指定训练图像所在的目录(根据实际情况修改路径)。-递归获取该目录下所有图像文件的路径,存储在数组`ImageFiles`中。-获取图像数量`ImageCount`,并初始化样本索引`SampleIndex`。####4.**循环处理每张图像**```halconforImageIdx:=0toImageCount-1by1read_image(Image,ImageFiles[ImageIdx])dev_display(Image)```-遍历每张图像,读取并显示在窗口中。####5.**初始化当前图像的数据结构**```halconcreate_dict(SampleData)set_dict_tuple(SampleData,'image',ImageFiles[ImageIdx])set_dict_tuple(SampleData,'defects',[])```-为当前图像创建一个字典`SampleData`,用于存储图像路径和该图像中的所有缺陷标注。####6.**交互式标注当前图像的缺陷区域**```halconwhile(true)dev_set_color('green')dev_set_draw('margin')set_tposition(WindowHandle,10,10)write_string(WindowHandle,'Left-clicktodrawdefect,Right-clicktofinish')*绘制缺陷区域draw_region(DefectRegion,WindowHandle)if(|DefectRegion|=0)breakendif```-进入无限循环,直到用户右键点击结束标注。-设置绘制颜色为绿色,绘制模式为轮廓(margin)。-提示用户左键绘制缺陷区域,右键结束。-调用`draw_region`让用户绘制一个缺陷区域。如果绘制的区域为空(即用户右键点击),则退出循环。####7.**选择缺陷类别**```halconClassChoice:=1while(ClassChoice< |DefectClasses|andClassChoice>0)disp_message(WindowHandle,'Selectdefectclass:','window',50,10,'black','true')fori:=0to|DefectClasses|-1disp_message(WindowHandle,(i+1)$'d:'+DefectClasses[i],'window',80+i*30,20,'forestgreen','true')endforget_mbutton(WindowHandle,RowY,ColumnX,Button)ClassChoice:=Buttonendwhile```-在窗口上显示所有缺陷类别及其对应的编号(1到6)。-等待用户点击鼠标,用户点击左键(按钮值为1)到右键(按钮值可能为2-6)来选择类别。注意:实际中鼠标按钮值可能为1(左键)、2(中键)、3(右键),但这里我们通过按钮值直接对应类别编号(1-6),超出范围则重新选择。####8.**保存当前缺陷的标注信息**```halconif(ClassChoice>=1andClassChoice<=|DefectClasses|)create_dict(DefectAnnotation)set_dict_tuple(DefectAnnotation,'region',DefectRegion)set_dict_tuple(DefectAnnotation,'class',ClassChoice-1)*类别索引从0开始set_dict_tuple(DefectAnnotation,'class_name',DefectClasses[ClassChoice-1])*提取特征用于验证area_center(DefectRegion,Area,Row,Column)set_dict_tuple(DefectAnnotation,'area',Area)set_dict_tuple(DefectAnnotation,'position',[Row,Column])*添加到当前样本的缺陷列表defects:=get_dict_tuple(SampleData,'defects')defects:=[defects,DefectAnnotation]set_dict_tuple(SampleData,'defects',defects)dev_set_color('gold')dev_display(DefectRegion)endifendwhile```-如果用户选择的类别编号有效(1到6),则创建缺陷标注字典`DefectAnnotation`,存储区域、类别索引(0-5)、类别名称。-计算该区域的面积和中心位置,并保存。-将该缺陷标注添加到当前图像的`defects`列表中,并用金色显示已标注的区域。####9.**将当前样本添加到数据集**```halconsamples:=get_dict_tuple(AnnotationDict,'samples')samples:=[samples,SampleData]set_dict_tuple(AnnotationDict,'samples',samples)*显示进度set_tposition(WindowHandle,500,10)write_string(WindowHandle,'Progress:'+(SampleIndex+1)$'d'+'/'+ImageCount$'d')SampleIndex:=SampleIndex+1endfor```-将当前图像样本添加到整个数据集的样本列表。-在窗口右上角显示标注进度。####10.**保存数据集**```halconwrite_dict(AnnotationDict,'zinc_defect_dataset.hdict',[],[])dev_disp_text('Datasetsavedsuccessfully!','window',300,300,'white',[],[])```-循环结束后,将整个标注字典写入文件`zinc_defect_dataset.hdict`。-显示保存成功的消息。###使用说明1.**准备图像**:将训练图像放入指定目录(例如`C:/zinc_defects/train/`),支持多种格式(jpg,png,bmp等)。2.**运行脚本**:在HDevelop中运行`create_defect_dataset.hdev`。3.**标注过程**:-每打开一张图像,使用鼠标左键绘制缺陷区域(绘制时按住左键移动,松开完成绘制)。-绘制完成后,窗口会显示类别选项,此时用户按键盘上的数字键(1-6)选择对应类别(或通过鼠标按钮选择,实际中可能需要调整选择方式)。-继续标注当前图像的下一个缺陷,右键结束当前图像的标注。-自动进入下一张图像。4.**结果保存**:所有图像标注完成后,数据集文件会自动生成。###注意事项-该脚本仅支持鼠标操作,实际中可能需要根据标注习惯调整类别选择方式(如使用键盘按键选择类别)。-在Halcon中,`get_mbutton`返回的按钮值通常是1(左键)、2(中键)、3(右键),因此上述类别选择逻辑可能需要调整。更常见的做法是使用键盘选择类别。以下是修改后的类别选择代码示例(使用键盘):```halcondisp_message(WindowHandle,'Presskey(1-6)forclass,Esctoskip','window',50,10,'black','true')while(true)get_key(Key)if(Key>='1'andKey<='6')ClassChoice:=Key-'0'breakelseif(Key=#Esc)ClassChoice:=0breakendifendwhile```-以上修改代码使用`get_key`等待键盘输入,用户按数字键1-6选择类别,按Esc跳过(放弃)当前绘制的区域。###相关问题现在我们将根据要求提出相关问题:§§相关问题§§:1.如何在Halcon标注工具中实现撤销(undo)功能?2.如何改进标注工具以支持多边形标注(而不仅是区域绘制)?3.除了手动标注,Halcon是否支持半自动标注(如基于预训练模型的建议区域)?4.如何将标注数据转换为常见的机器学习数据集格式(如COCO)?</think>
下面我将详细解释锌板缺陷检测项目的数据准备阶段,包括`create_defect_dataset.hdev`脚本的完整工作流程、关键技术和操作指南:
### 数据准备阶段完整详解
```halcon
*=== 锌板缺陷数据集标注工具 ===*
* 功能:交互式标注缺陷区域并保存训练数据集
* 1. 初始化环境
dev_close_window()
dev_open_window(0, 0, 1000, 700, 'black', WindowHandle)
set_display_font(WindowHandle, 14, 'mono', 'true', 'false')
dev_set_part(0, 0, 1024, 768) // 设置显示范围
* 2. 定义缺陷类别体系
DefectClasses := ['scratch', 'dent', 'stain', 'corrosion', 'inclusion', 'edge_damage', 'other']
ColorMap := ['red', 'green', 'blue', 'yellow', 'cyan', 'magenta', 'white']
* 3. 创建数据集结构
create_dict(Dataset)
set_dict_tuple(Dataset, 'classes', DefectClasses)
set_dict_tuple(Dataset, 'color_map', ColorMap)
set_dict_tuple(Dataset, 'creation_date', date())
set_dict_tuple(Dataset, 'images', [])
* 4. 加载图像文件
ImageDir := 'C:/zinc_defects/train/'
list_image_files(ImageDir, 'default', 'recursive', ImageFiles)
ImageCount := |ImageFiles|
if (ImageCount == 0)
dev_disp_text('错误:找不到图像文件!', 'window', 300, 300, 'red', 'box', 'true')
stop()
endif
* 5. 标注流程核心逻辑
for ImageIdx := 0 to ImageCount-1 by 1
* 5.1 读取并显示当前图像
read_image(CurrentImage, ImageFiles[ImageIdx])
get_image_size(CurrentImage, Width, Height)
* 调整窗口适配图像
if (Width > 1000 or Height > 700)
Ratio := min([1000.0/Width, 700.0/Height])
ZoomFactor := 0.8*Ratio
dev_resize_window_fit_image(CurrentImage, ZoomFactor, ZoomFactor)
endif
dev_display(CurrentImage)
* 5.2 创建图像元数据
create_dict(ImageData)
set_dict_tuple(ImageData, 'path', ImageFiles[ImageIdx])
set_dict_tuple(ImageData, 'width', Width)
set_dict_tuple(ImageData, 'height', Height)
set_dict_tuple(ImageData, 'defects', [])
* 5.3 标注引导界面
DispMsg := '图像 ' + (ImageIdx+1)$'d' + '/' + ImageCount$'d' + ': ' + basename(ImageFiles[ImageIdx])
dev_disp_text(DispMsg, 'window', 20, 20, 'white', 'box', 'true')
dev_disp_text('左键: 绘制缺陷区域 | 右键: 完成当前图像', 'window', Height-50, 20, 'cyan', [], [])
* 5.4 循环标注当前图像所有缺陷
DefectIndex := 1
while (true)
* 显示类别选择菜单
set_tposition(WindowHandle, 60, 20)
write_string(WindowHandle, '选择缺陷类别:')
for cls := 0 to |DefectClasses|-1
dev_set_color(ColorMap[cls])
set_tposition(WindowHandle, 100 + cls*40, 50)
write_string(WindowHandle, (cls+1)$'d' + ': ' + DefectClasses[cls])
endfor
dev_set_color('white')
* 5.5 交互式绘制缺陷区域
set_tposition(WindowHandle, 100, 20)
write_string(WindowHandle, '绘制缺陷 #' + DefectIndex$'d')
draw_region(CurrentRegion, WindowHandle)
* 检查退出条件(右键结束)
if (|CurrentRegion| == 0)
break
endif
* 5.6 类别选择
ClassChoice := 0
set_tposition(WindowHandle, 150, 20)
write_string(WindowHandle, '按下对应数字键选择类别 (1-7)')
while (ClassChoice < 1 or ClassChoice > |DefectClasses|)
get_key(Key)
ClassChoice := ord(Key) - ord('0')
endwhile
SelectedClass := ClassChoice - 1 // 0-based index
* 5.7 创建缺陷条目
create_dict(DefectData)
set_dict_tuple(DefectData, 'id', DefectIndex)
set_dict_tuple(DefectData, 'class', SelectedClass)
set_dict_tuple(DefectData, 'class_name', DefectClasses[SelectedClass])
* 计算区域特征
area_center(CurrentRegion, Area, Row, Column)
smallest_rectangle1(CurrentRegion, Row1, Col1, Row2, Col2)
compactness(CurrentRegion, Compactness)
circularity(CurrentRegion, Circularity)
* 存储几何数据
create_dict(Geometry)
set_dict_tuple(Geometry, 'area', Area)
set_dict_tuple(Geometry, 'centroid', [Row, Column])
set_dict_tuple(Geometry, 'bbox', [Row1, Col1, Row2, Col2])
set_dict_tuple(Geometry, 'compactness', Compactness)
set_dict_tuple(Geometry, 'circularity', Circularity)
set_dict_tuple(DefectData, 'geometry', Geometry)
set_dict_tuple(DefectData, 'region', CurrentRegion)
* 5.8 添加到图像数据
defects := get_dict_tuple(ImageData, 'defects')
defects := [defects, DefectData]
set_dict_tuple(ImageData, 'defects', defects)
* 高亮显示已标注区域
dev_set_color(ColorMap[SelectedClass])
dev_display(CurrentRegion)
set_tposition(WindowHandle, Row1-25, Col1)
write_string(WindowHandle, DefectClasses[SelectedClass] + ' #' + DefectIndex$'d')
DefectIndex := DefectIndex + 1
endwhile
* 5.9 将当前图像添加到数据集
images := get_dict_tuple(Dataset, 'images')
images := [images, ImageData]
set_dict_tuple(Dataset, 'images', images)
* 进度显示
dev_disp_text(f'完成标注: {|get_dict_tuple(ImageData, "defects")|}个缺陷',
'window', Height-100, Width-250, 'lime', 'box', 'true')
endfor
* 6. 保存数据集
Filepath := 'zinc_defect_dataset_' + date()$'Ymd' + '.hdict'
write_dict(Dataset, Filepath, [], [])
dev_disp_text('数据集已保存: ' + Filepath, 'window', Height/2, Width/2-150, 'gold', 'box', 'true')
* 7. 生成数据统计
TotalDefects := 0
ClassCount := [0,0,0,0,0,0,0]
* 7.1 统计各类别数量
for image_idx := 0 to |get_dict_tuple(Dataset, 'images')|-1 by 1
ImageDefects := get_dict_tuple(Dataset.images[image_idx], 'defects')
TotalDefects := TotalDefects + |ImageDefects|
for def_idx := 0 to |ImageDefects|-1 by 1
cls := get_dict_tuple(ImageDefects[def_idx], 'class')
ClassCount[cls] := ClassCount[cls] + 1
endfor
endfor
* 7.2 显示统计信息
CreateTable := []
CreateTable[0] := '缺陷类别统计:'
for cls := 0 to |DefectClasses|-1 by 1
Percentage := (ClassCount[cls]/TotalDefects)*100
CreateTable[cls+1] := f'{DefectClasses[cls]:<12} {ClassCount[cls]:>3} ({Percentage:.1f}%)'
endfor
CreateTable[|DefectClasses|+1] := '----------------------'
CreateTable[|DefectClasses|+2] := f'总计: {TotalDefects}个缺陷 | {ImageCount}张图像'
* 输出统计表
dev_disp_table([40, Width-250], [50, 150], CreateTable, 'window', [Width-400, 50], 'white', 'box_colored')
stop()
```
### 完整工作流程解析
#### 1. 初始设置
- **窗口配置**:创建适合标注的可视化窗口
- **缺陷类别定义**:常见7类缺陷(可自定义扩展)
- **颜色映射**:为每类缺陷分配唯一颜色
- **数据结构**:使用Halcon字典构建层级化数据存储
#### 2. 文件加载与验证
- 遍历扫描指定目录下所有图像文件
- 自动检测并处理异常情况(空目录提示)
- 动态调整窗口大小适配不同分辨率图像
#### 3. 交互式标注流程
1. **图像导航**:
- 自动顺序加载图像
- 显示当前进度(N/M)
- 展示文件名便于识别
2. **区域绘制**:
- 使用`draw_region`函数实时绘制轮廓
- 支持任意形状区域的勾勒
- 右键完成当前图像标注
3. **类别选择**:
- 显示颜色编码的类别菜单
- 通过数字键(1-7)快速选择
- 视觉反馈(区域着色+文字标签)
4. **特征提取**:
- 自动计算区域属性:面积、中心点、外接矩形
- 量化形态特征:紧凑度、圆形度
- 保存原始区域对象供后续使用
#### 4. 数据存储结构
```python
dataset {
"classes": ["scratch", "dent", ...],
"color_map": ["red", "green", ...],
"creation_date": "20230615",
"images": [
{
"path": "C:/.../img01.jpg",
"width": 1024,
"height": 768,
"defects": [
{
"id": 1,
"class": 0,
"class_name": "scratch",
"geometry": {
"area": 245.3,
"centroid": [125, 312],
"bbox": [110, 300, 140, 324],
"compactness": 1.23,
"circularity": 0.85
},
"region": <Halcon Region Object>
},
...
]
},
...
]
}
```
#### 5. 数据质量保障
1. **自动统计**:
- 各类缺陷比例分布
- 每张图像的缺陷数量
- 总数统计(总图像数/总缺陷数)
2. **视觉验证**:
- 标注后立即可视化
- 类别颜色高亮显示
- 防止漏标/错标
3. **命名规范**:
- 自动添加日期标签
- 保留完整路径信息
- JSON式分层存储
### 实践操作指南
1. **启动标注**:
```bash
hdevelop create_defect_dataset.hdev
```
2. **标注步骤**:
1. 查看左上角当前图像信息
2. 鼠标左键绘制缺陷轮廓
3. 按下数字键(1-7)选择类别
4. 自动显示标注结果
5. 右键完成当前图像
6. 自动载入下一张图像
3. **注意事项**:
- 保持目录路径与脚本一致
- 确保图像格式被支持(JPG/PNG/BMP)
- 复杂缺陷可分解为多个区域标注
- 小缺陷可适当放大后标注
4. **质量检查**:
- 关注统计信息中的类别平衡性
- 确保每类缺陷至少30个样本
- 特殊缺陷可单独创建"other"类别
5. **结果示例**:
```
缺陷类别统计:
scratch 48 (17.2%)
dent 32 (11.5%)
stain 65 (23.3%)
corrosion 23 (8.2%)
inclusion 41 (14.7%)
edge_damage 45 (16.1%)
other 25 (9.0%)
----------------------
总计: 279个缺陷 | 42张图像
```
### 高级功能扩展点
1. **快捷键增强**:
```halcon
* 添加撤销功能
if (ord(Key) == ord('z') and |CurrentDefects| > 0)
remove_defect_last_entry()
endif
```
2. **尺寸标注**:
```halcon
* 手动标注实际尺寸
set_tposition(WindowHandle, Row2+10, Col1)
input_number('输入实际尺寸(mm): ', ActualSize)
set_dict_tuple(Geometry, 'actual_size', ActualSize)
```
3. **自动保存**:
```halcon
* 每5张图像自动保存备份
if (ImageIdx % 5 == 0 and ImageIdx > 0)
BackupFile := 'backup_'+date()$'YmdHis')+'.hdict'
write_dict(Dataset, BackupFile, [], [])
endif
```