目录

Millow

MillowM(代表 MoonBit)+ illow(致敬 Python 的 Pillow)。

一个零 FFI、跨平台的 MoonBit 图像处理库。millow 完全基于内存中的 RGBA8 缓冲区(Array[Byte],布局为 H × W × 4)工作,支持所有后端: wasm-gcwasmjsnative

English | 中文

演示

输入 to_grayscale tint(100,150,200) gaussian_blur(σ=2)
sharpen(1.0) sobel equalize_histogram threshold_otsu
rotate_any(45°) find_contours pipeline

cmd/main 包含轻量级演示,生成合成渐变图像并应用 30+ 种 millow 操作 — 无需外部依赖:

moon run cmd/main

完整演示(PNG/JPEG I/O,30 张输出图像)位于独立的 examples/ 项目中:

cd examples
moon run .

功能特性

  • 核心图像类型Image,支持构造、像素访问、克隆、通道分离/合并、子图像。
  • 颜色 — 灰度(平坦与加权)、反色、色调、BGR、Alpha 展平、HSV/YCbCr 转换、 LUT 应用、Alpha 合成。
  • 几何变换 — 裁剪、翻转、90/180/270 旋转、任意角度旋转、平移、仿射变换、 错切、缩放(最近邻/双线性/双三次)、等比缩放、适配/覆盖、缩略图、填充。
  • 增强 — 亮度、对比度、伽马、归一化、自动对比度、标准化、锐化、Unsharp Mask。
  • 阈值与直方图 — 固定阈值、Otsu、Sauvola、直方图(灰度与彩色)、均衡化、 CLAHE、直方图匹配。
  • 滤波与边缘 — 卷积、均值/高斯模糊、中值/最小/最大值滤波、双边滤波、 Sobel、Scharr、Prewitt、Laplacian、Canny。
  • 形态学 — 腐蚀、膨胀、开运算、闭运算、形态学梯度、Top-hat、Black-hat、 骨架化、击中击不中。
  • 特征检测 — LBP、HOG、Harris 角点、Shi-Tomasi 角点。
  • 测量 — 连通域、轮廓提取、矩、Hu 矩、区域属性、像素计数。
  • 数据增强 — 随机裁剪、翻转、旋转、亮度/对比度/伽马调整、高斯/椒盐噪声、 色彩抖动、可组合的增强管线与加权随机选择。
  • 度量 — MSE、PSNR、SSIM。
  • 绘图 — 像素、直线、矩形、圆、椭圆、多边形、泛洪填充。
  • I/O — PPM/PGM 序列化,可插拔的 Encoder/Decoder 注册表。
  • 边界处理Replicate(复制)、Reflect(镜像)、Wrap(平铺)、 Constant(常量填充)四种模式,用于仿射变换和插值。

项目结构

millow/
├── src/              # 实现包(megemini/millow/src)
├── millow.mbt        # 根门面:重新导出公共 API(megemini/millow)
├── test/             # 黑盒测试包,测试公共 API
├── test_alignment/   # 与 Python(skimage/Pillow)参考实现对齐测试
├── cmd/main/         # 轻量级合成图像演示(仅依赖 millow)
└── examples/         # 独立完整演示(通过 mizchi/image 进行 PNG/JPEG I/O)

根包是 src 的薄门面,下游用户只需 import "megemini/millow", 即可通过 @millow 访问全部 API。

安装

moon add megemini/millow

然后在包的 moon.pkg 中导入:

import {
  "megemini/millow" @millow,
}

快速开始

///|
test "构建、变换并检查图像" {
  // 64×64 画布上绘制一个填充矩形
  let base = Image::from_pixel(64, 64, 30, 60, 90, 255)
  let canvas = draw_rect(base, 8, 8, 40, 40, 220, 40, 40, 255, true, 1)

  // 灰度 → 模糊 → 边缘检测
  let gray = to_grayscale(canvas)
  let blurred = gaussian_blur(gray, 1.5)
  let edges = sobel(blurred)
  assert_eq(edges.shape(), (64, 64))

  // Otsu 自适应阈值
  let (_, binary) = threshold_otsu(blurred)
  assert_eq(binary.shape(), (64, 64))

  // 缩小并序列化为 PPM
  let thumb = resize(canvas, 16, 16, Nearest)
  let ppm = to_ppm(thumb)
  assert_eq(ppm[0], 'P'.to_int().to_byte())
}

上面的示例中 API 以非限定名调用,因为它们在 millow 包内部运行。 从其他模块调用时,需加上导入别名前缀,例如 @millow.to_grayscale(img)

增强管线

使用 augment_pipeline 将多个增强操作组合成一次调用,按顺序依次应用每个 Augmentation 变体:

///|
test "augment_pipeline 示例" {
  let img = Image::from_pixel(64, 64, 30, 60, 90, 255)
  let out = augment_pipeline(img, [
    FlipHorizontal,
    Rotate(15.0),
    Brightness(1.2),
    Contrast(1.3),
    NoiseGaussian(8.0),
  ])
  assert_true(out.h > 0 && out.w > 0)
}

可用的 Augmentation 变体:Crop(y, x, h, w)Resize(dst_h, dst_w)FlipHorizontalFlipVerticalRotate(angle)Brightness(factor)Contrast(factor)Gamma(g)NoiseGaussian(std)NoiseSaltPepper(prob)ColorJitter(b, c, s, h)。当裁剪/缩放参数无效时 augment_pipeline 会抛出异常。

使用 augment_random_choice 从加权分布中采样一个增强操作:

///|
test "augment_random_choice 示例" {
  let img = Image::from_pixel(64, 64, 30, 60, 90, 255)
  let out = augment_random_choice(img, [
    (0.4, FlipVertical),
    (0.4, Gamma(0.8)),
    (0.2, ColorJitter(0.2, 0.2, 0.0, 0.0)),
  ])
  assert_eq(out.shape(), img.shape())
}

API 说明

坐标系

millow 在整个 API 中使用统一的坐标约定:

  • 维度顺序(h, w) — 高度优先,宽度次之。 Image::new(h, w)resize(img, dst_h, dst_w, interp)crop(img, y, x, h, w)Image::shape() -> (h, w)

  • 坐标顺序(y, x) — 行优先,列次之。 y 是垂直轴(向下递增),x 是水平轴(向右递增)。原点 (0, 0)左上角

  • 绘图中心draw_circle(img, cy, cx, radius, ...)draw_ellipse(img, cy, cx, ry, rx, ...)

  • 平移translate(img, dy, dx, interp)

  • 轮廓find_contours 返回 (y, x) 元组。

亮度调整

adjust_brightness(img, factor) 使用乘法因子:

  • factor = 1.0 返回原图
  • factor = 0.0 返回全黑图像
  • 大于 1.0 的值提亮图像
  • 小于 1.0 的值压暗图像

对比度调整

adjust_contrast(img, factor) 相对于图像平均亮度调整对比度:

  • factor = 1.0 返回原图
  • factor = 0.0 返回等于图像平均亮度的纯灰图像
  • 大于 1.0 的值增加对比度
  • 小于 1.0 的值降低对比度

Alpha 合成

flatten_alpha(img, r, g, b) 将图像合成到指定纯色背景上,使用浮点混合以获得平滑效果。

边界处理

部分操作支持 mode 参数,控制边界像素的处理方式:

  • Replicate — 将最近的边缘像素向外延伸
  • Reflect — 沿边缘镜像像素
  • Wrap — 周期性平铺图像
  • Constant(r, g, b, a) — 用指定颜色填充边界区域

支持可选 mode 参数的函数包括 affine_transformshear。 大多数其他操作内部使用 replicate(钳位)边界处理。

双边滤波

bilateral_filter(img, d, sigma_color, sigma_space) 应用保边平滑:

  • d 为像素邻域直径(传 0 则根据 sigma_space 自动计算)
  • sigma_color 控制颜色相似度阈值(越大平滑越多)
  • sigma_space 控制空间邻近度阈值(越大邻域越宽)

仿射变换

affine_transform(img, matrix, dst_h, dst_w, interp, mode) 使用 6 元素矩阵 [a, b, c, d, e, f] 应用通用仿射变换,表示:

x' = a*x + b*y + c
y' = d*x + e*y + f

常用变换可使用 rotate_anytranslate

随机噪声

random_noise_gaussian(img, std) 添加指定标准差的高斯噪声。

random_noise_salt_pepper(img, amount) 添加指定比例(受影响像素占比)的椒盐噪声。

后端

millow 不包含任何外部函数调用。已在 wasm-gcwasmjsnative 上 验证构建,测试套件在所有后端均通过。

测试

moon test                 # 运行所有测试
moon test --target native # 指定后端
moon run cmd/main         # 运行合成演示(无外部依赖)
cd examples && moon run . # 运行完整演示(含 JPEG I/O)

对齐测试

test_alignment/ 验证 millow 的输出与 Python 参考实现(numpy / skimage / Pillow) 一致。工作流程如下:

  1. test_alignment/generate_fixtures.py 为小测试图像计算期望输出字节, 写入 fixtures_test.mbt 作为 Array[Int] 字面量。
  2. MoonBit 测试从这些 fixture 构造 Image,运行每个 millow 操作, 然后逐字节比较(整数操作精确匹配,浮点操作 ±1 容差)。

修改算法后重新生成 fixture:

source $HOME/venv310/bin/activate
python test_alignment/generate_fixtures.py
moon test

路线图

完整的版本规划与未来计划请参见 docs/roadmap.md

许可证

Apache-2.0。详见 LICENSE

关于

A **zero-FFI, cross-platform image-processing library** for MoonBit.

3.1 MB
邀请码
    Gitlink(确实开源)
  • 加入我们
  • 官网邮箱:gitlink@ccf.org.cn
  • QQ群
  • QQ群
  • 公众号
  • 公众号

版权所有:中国计算机学会技术支持:开源发展技术委员会
京ICP备13000930号-9 京公网安备 11010802047560号