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

运行方式与验证

  1. 在 D:/halcon_in 放入若干张不同格式的图像(如 3 张 .bmp、2 张 .jpg)。
  2. 在 HDevelop 中新建程序,粘贴上述代码,按 F5 运行。
  3. 观察窗口逐张显示灰度图,并显示 Processing n/N: 文件名。
  4. 运行结束后打开 D:/halcon_out,应看到与输入同名的 .png 文件,数量与输入图像数一致。
  5. 用 read_image 重新读入任一输出文件,检查 count_channels 返回 1,确认已转为单通道灰度。

常见问题与处理

  • 路径分隔符:HALCON 在 Windows 下同时接受 / 和 \\,代码统一用 / 更省心。
  • 输出目录不存在:make_dir 只能创建一级目录,若需多级请先确保父目录存在。
  • 同名覆盖:若输入目录中同时存在 a.bmp 和 a.jpg,输出都会写成 a.png,后者覆盖前者。需要保留时可在基名后追加原扩展名。
  • 大图内存:循环中每轮结束 Image 会被下一轮覆盖,无需手动释放;若图像极大,可在 endfor 前加 clear_obj (ImageGray) 及时释放。