3. 图像文件批量读取与保存
本案例用 HALCON 的 HDevelop 脚本完成一个最小可用的批处理工具:扫描一个输入目录下的所有图像文件,逐个读取、统一转换为 8 位灰度图,再以 PNG 格式写入输出目录。整个过程不依赖任何前序章节代码,可直接复制运行。
任务拆解与关键对象
- 输入目录:存放待处理图像,例如
D:/halcon_in,内含.bmp、.jpg、.png、.tif等混合格式。 - 输出目录:保存转换结果,例如
D:/halcon_out,统一输出.png。 - 文件列表:用
list_files获取目录下所有文件,再用tuple_regexp_select过滤出图像扩展名。 - 循环处理:
for循环逐个读取,read_image读入,rgb1_to_gray转灰度,write_image写出。 - 文件名映射:用
parse_filename拆出基名,拼接输出路径,保证输入输出文件名一一对应。
完整可运行代码
* ============================================================
* 案例 3:图像文件批量读取与保存
* 功能:读取输入目录下所有图像,转 8 位灰度后另存为 PNG
* ============================================================
* ---------- 1. 参数设置 ----------
InputDir := 'D:/halcon_in'
OutputDir := 'D:/halcon_out'
OutExt := 'png'
* 支持的图像扩展名(正则,忽略大小写)
ImgPattern := '\\.(bmp|jpg|jpeg|png|tif|tiff)$'
* ---------- 2. 准备输出目录 ----------
* 若输出目录不存在则创建(HALCON 无直接 mkdir,用 file_exists 判断)
file_exists (OutputDir, FileExists)
if (not FileExists)
make_dir (OutputDir)
endif
* ---------- 3. 获取输入目录下所有文件 ----------
list_files (InputDir, 'files', AllFiles)
* 过滤出图像文件
tuple_regexp_select (AllFiles, ImgPattern, 'ignore_case', ImageFiles)
* 统计数量
Count := |ImageFiles|
if (Count == 0)
disp_message (3600, '未找到图像文件,请检查输入目录', 'window', 12, 12, 'red', 'true')
stop ()
endif
* ---------- 4. 循环读取、转换、保存 ----------
* 打开一个窗口用于显示进度(可选)
dev_close_window ()
dev_open_window (0, 0, 512, 512, 'black', WindowHandle)
set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
for Index := 0 to Count - 1 by 1
* 4.1 取当前文件完整路径
CurrentFile := ImageFiles[Index]
* 4.2 读取图像
read_image (Image, CurrentFile)
* 4.3 统一转为 8 位灰度图
* 若原图为彩色(3 通道),rgb1_to_gray 转换;
* 若已是单通道,count_channels 判断后跳过转换。
count_channels (Image, NumChannels)
if (NumChannels == 3)
rgb1_to_gray (Image, ImageGray)
else
ImageGray := Image
endif
* 4.4 构造输出文件名:基名 + .png
parse_filename (CurrentFile, BaseName, Extension, Directory)
OutFileName := BaseName + '.' + OutExt
OutFilePath := OutputDir + '/' + OutFileName
* 4.5 保存
write_image (ImageGray, OutExt, 0, OutFilePath)
* 4.6 显示进度
dev_display (ImageGray)
disp_message (WindowHandle, 'Processing ' + (Index + 1) + '/' + Count + ': ' + OutFileName, \
'window', 12, 12, 'green', 'true')
endfor
disp_message (WindowHandle, '全部完成,共处理 ' + Count + ' 张图像', 'window', 12, 12, 'yellow', 'true')
关键算子说明
| 算子 | 作用 | 本案例取值 |
|---|---|---|
list_files | 列出目录下文件 | 'files' 只列文件,不递归子目录 |
tuple_regexp_select | 按正则筛选元组 | 过滤出图像扩展名,'ignore_case' 忽略大小写 |
read_image | 读取图像 | 自动识别格式,返回 Image 对象 |
count_channels | 统计通道数 | 3 通道才转灰度,避免重复转换 |
rgb1_to_gray | 彩色转灰度 | 输出 8 位单通道 |
parse_filename | 拆分路径 | 得到基名、扩展名、目录 |
write_image | 保存图像 | 格式 'png',压缩参数 0 |
运行方式与验证
- 在
D:/halcon_in放入若干张不同格式的图像(如 3 张.bmp、2 张.jpg)。 - 在 HDevelop 中新建程序,粘贴上述代码,按 F5 运行。
- 观察窗口逐张显示灰度图,并显示
Processing n/N: 文件名。 - 运行结束后打开
D:/halcon_out,应看到与输入同名的.png文件,数量与输入图像数一致。 - 用
read_image重新读入任一输出文件,检查count_channels返回 1,确认已转为单通道灰度。
常见问题与处理
- 路径分隔符:HALCON 在 Windows 下同时接受
/和\\,代码统一用/更省心。 - 输出目录不存在:
make_dir只能创建一级目录,若需多级请先确保父目录存在。 - 同名覆盖:若输入目录中同时存在
a.bmp和a.jpg,输出都会写成a.png,后者覆盖前者。需要保留时可在基名后追加原扩展名。 - 大图内存:循环中每轮结束
Image会被下一轮覆盖,无需手动释放;若图像极大,可在endfor前加clear_obj (ImageGray)及时释放。