You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何仅对图像白色背景添加dithering抖动噪声且保留文字清晰度

现有代码问题
  • 处理顺序错误:先对全图做抖动再强制替换高亮像素为固定灰度值,最终输出的背景是无颗粒的纯灰色,完全丢失dithering效果
  • 无前景保护逻辑:单阈值直接改像素会把文字边缘的抗锯齿浅灰像素误判为背景,导致文字边缘发糊、清晰度下降
  • 缺少区域控制逻辑,无法实现半页区域单独替换背景的需求
可行实现方案

按以下流程处理即可在不损失文字清晰度的前提下得到目标效果:

  1. 前景背景分离:将原图转灰度后,通过阈值筛选出纯白背景区域生成二值遮罩(mask),遮罩覆盖区域为待替换的背景,其余区域全程保留原图像素不做修改
  2. 区域范围控制:如果需要半页替换,直接对遮罩做坐标裁剪,仅保留目标半页范围内的遮罩生效区即可
  3. 单独生成抖动背景:单独创建和原图尺寸一致的画布,填充目标灰度值后单独施加dithering效果,通过参数控制抖动颗粒的反差强度,避免颗粒过杂干扰文字
  4. 遮罩合成:以生成的遮罩为依据,仅在背景区域替换为提前生成的抖动背景层,文字、非背景区域完全保留原图内容
修正后代码
import os
import numpy as np
from PIL import Image

# 路径配置,已修正原代码路径中混入的无效字符
ORIGIN_PATH = "/home/dithering/temp/"
DESTIN_PATH = "/home/dithering/temp_try/"
# 效果参数
BG_THRESHOLD = 250  # 灰度值高于该阈值判定为纯白背景
TARGET_BG_GRAY = 210  # 背景基础灰度值
DITHER_STRENGTH = 12  # 抖动颗粒强度,数值越大颗粒反差越明显
# 半页模式配置
ENABLE_HALF_PAGE = True  # 是否开启仅半页替换
HALF_PAGE_SPLIT_RATIO = 0.5  # 横向分割线位置,0.5为页面正中间
HALF_PAGE_PROCESS_UPPER = True  # True=处理上半页,False=处理下半页

os.makedirs(DESTIN_PATH, exist_ok=True)

for filename in os.listdir(ORIGIN_PATH):
    # 过滤非图像/PDF文件
    if not filename.lower().endswith(('.png', '.jpg', '.jpeg', '.pdf')):
        continue
    # 读取文件转灰度
    img = Image.open(os.path.join(ORIGIN_PATH, filename)).convert("L")
    img_np = np.asarray(img).copy()
    h, w = img_np.shape

    # 生成背景遮罩
    bg_mask = (img_np > BG_THRESHOLD).astype(np.uint8)
    # 半页模式下裁剪遮罩范围
    if ENABLE_HALF_PAGE:
        split_y = int(h * HALF_PAGE_SPLIT_RATIO)
        if HALF_PAGE_PROCESS_UPPER:
            bg_mask[split_y:, :] = 0
        else:
            bg_mask[:split_y, :] = 0

    # 生成带Floyd-Steinberg抖动的背景层
    base_bg = Image.new("L", (w, h), color=TARGET_BG_GRAY)
    dither_bg = base_bg.convert("1", dither=Image.Dither.FLOYDSTEINBERG).convert("L")
    dither_bg_np = np.asarray(dither_bg)
    # 映射抖动颗粒到目标灰度范围,控制强度
    dither_bg_np = np.where(
        dither_bg_np > 128,
        TARGET_BG_GRAY + DITHER_STRENGTH,
        TARGET_BG_GRAY - DITHER_STRENGTH
    ).astype(np.uint8)

    # 按遮罩合成最终图像
    final_np = np.where(
        bg_mask == 1,
        dither_bg_np,
        img_np
    )
    final_img = Image.fromarray(final_np)
    # 需要三通道RGB格式可放开下行注释
    # final_img = final_img.convert("RGB")
    final_img.save(os.path.join(DESTIN_PATH, filename))
调优提示
  • 直接用PIL读取PDF默认会用72DPI低分辨率渲染,文字会发糊,建议先用pdf2image库将PDF渲染为300DPI的图像后再走上述处理流程,文字锐度会明显提升
  • BG_THRESHOLD建议根据素材的白底纯净度在245-252区间调整,数值过高会漏判偏灰的背景,数值过低会误吞文字边缘的抗锯齿像素
  • 如果觉得Floyd-Steinberg抖动的颗粒太细碎,可以替换为Bayer有序抖动,生成的网点效果更规整,更接近印刷质感
  • 抖动强度建议控制在8-15区间,过强的颗粒会干扰模型对文字特征的提取

内容的提问来源于stack exchange,提问作者aarya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 13:33:23