拍照文档有阴影、页面弯曲?我做了一个 C# + Vulkan 文档修复工具箱

0 阅读10分钟

拍一页孩子的作业,手机和手挡住了光,纸上多了一大片阴影。

拍一本摊开的书,靠近装订线的位置弯了起来,文字也跟着变形。

整理讲义和笔记,照片倒是拍了不少,但有的偏暗、有的发灰,放到一起看,实在不够舒服。

这些事情都不大,却经常遇到。所以这次,我把之前做文档去阴影的想法往前推进了一步,做了一款可以直接在 Windows 上使用的桌面软件:

文档修复工具箱 · DocRes Vulkan。

它把弯曲展平、去阴影、去模糊、外观增强、黑白二值化放在了一个界面里,支持单张处理、文件夹批量处理,还能把结果整理成多页 PDF。

界面用 C# WinForms 编写,神经网络通过 C++ Vulkan 在本机 GPU 上运行。同时整理了可直接运行的部署包和完整的 VS2022 源码工程,方便使用,也方便继续研究。

图片

软件实际运行界面:左侧原图,右侧修复结果

先看一个实际效果

下面这张图片来自 DocRes 官方项目的示例。原图纸面上有很明显的阴影,左侧和中间部分较暗。

图片

DocRes 官方去阴影示例原图

使用本工具的 Vulkan 后端,选择“去阴影”,处理上限设为 512,得到下面的结果:

图片

本工具实际生成的 Vulkan 去阴影结果

可以看到,大块阴影得到了明显改善,纸面的明暗更均匀,彩色笔迹也保留了下来。

这组图片是实际处理结果。不同照片的阴影、曝光和文字大小不同,效果也会有差异,大家可以先拿自己的图片试一张,再决定批量处理的参数。

五种功能,可以单独用,也可以组合

软件基于 DocRes 官方开源项目(github.com/ZZZHANG-jx/… 是 CVPR 2024 的文档图像修复研究,官方实现支持展平、去阴影、外观增强、去模糊和二值化等任务。

在桌面工具里,这些能力对应五个选项:

功能适合的情况
弯曲展平书页弯曲、页面内容随纸张发生变形
去阴影手、手机或环境光造成纸面局部发暗
外观增强纸面颜色和整体观感需要进一步整理
去模糊尝试改善模糊文档中的文字与边缘
二值化把页面转换成黑白图,方便打印或后续处理

如果只是光照不好,可以单独去阴影;如果希望保留彩色批注,就先看去阴影和外观增强的结果。

软件也提供了官方组合:

弯曲展平 → 去阴影 → 外观增强。

对于问题比较多的页面,还可以自定义勾选步骤。界面会按“展平 → 去阴影 → 去模糊 → 外观增强 → 二值化”的顺序执行,二值化放在最后。

建议先选最需要的一两项。每增加一个步骤,都会增加计算量,处理效果也需要结合原图判断。

普通用户怎么使用?

完整解压部署包,双击 Run.cmd 或 DocRes.WinForms.exe 就能打开。

运行环境是 Windows x64、.NET Framework 4.8,以及支持 Vulkan 的显卡和驱动。部署包带有模型和运行库,无需配置 Python、CUDA、OnnxRuntime 或 Vulkan SDK。精简版 Windows、N 版或 Server 系统还需具备 OpenCV 运行所依赖的 Media Foundation 等系统组件。

模型和图像处理都在本机执行,运行时不需要在线下载模型,也不需要把文档上传到服务器。

第一次使用,可以按下面的流程操作:

  1. 选择“单张图片”,导入一张照片。
  2. 选择修复任务,比如“去阴影”。
  3. 选择 GPU,处理上限先保留默认的 512。
  4. 点击“开始修复”,在界面中查看原图和结果。
  5. 到输出目录查看图片和 PDF,确认效果后再处理整批资料。

处理上限会影响速度、显存和细节。对于小字很多的页面,降低上限可能损失细线和文字细节;增加上限则会增加计算量和显存需求。

输出图片保留原图宽高,并不代表网络始终按原图分辨率进行修复。  例如,去阴影会在设定尺寸预测校正信息,再恢复到原图;去模糊和二值化超过上限时,会先按比例缩小处理,再恢复尺寸。

所以这个参数最好结合自己的资料试一下,不必一上来就调到最大。

几十张照片,也能一起整理

单张确认效果后,切换到文件夹模式,就可以批量处理。需要时可以勾选“包含子目录”。

批量模式会保留子目录结构,记录每张图片的完成或失败状态。输出名带有原图内容和任务参数的摘要,修改原图或处理配置后,会生成对应的新结果。

勾选“跳过已有结果”,再次执行相同任务时,就能复用已经完成的图片,适合分几次整理一大批资料。

默认目录也做得比较直接:

./输出      修复图片和 PDF
./工作区    任务记录,可选的中间图片和提示图
./cache     GPU 管线缓存

这些路径都相对软件 exe 所在目录解析。整个软件文件夹换个位置,内置模型和默认目录依然可以按相对路径找到。

图片可以保存为 PNG 或 JPEG。准备打印黑白文档时,建议二值化结果使用 PNG,避免 JPEG 压缩重新引入灰阶和边缘杂点。

从图片到 PDF,少一步来回折腾

处理完成后,软件可以同时生成多页 A4 PDF,一张图片对应一页,保持宽高比,并根据图片方向选择横页或竖页。

也可以使用“另选图片合成 PDF”,把已经整理好的图片按文件名顺序合并。建议提前用 001、002、003 这样的名称整理页码。

PDF 按页面逐张写入,不需要把整批图片都长期留在内存里。独立的 PNG/JPEG 结果也会保留。

当前导出的是图片型 PDF,适合阅读、归档和打印,暂未加入 OCR 文字层,因此不能直接搜索或复制页面中的文字。

背后的技术:任务提示 + Vulkan 推理

这部分留给喜欢看实现的朋友。

DocRes 的一个特点,是把原图和不同任务的提示图一起送入网络。本版主网络的输入由三通道 BGR 图像和三通道任务提示组成,总共六个通道。

这里的提示是图像信息。例如,去阴影使用背景相关提示,去模糊使用边缘相关提示。程序根据用户选择的任务准备输入,再按该任务解释网络输出。

一次完整处理大致是:

读取图片、校正 EXIF 方向
          ↓
按任务生成提示图、调整处理尺寸
          ↓
上传张量,执行 Vulkan 神经网络
          ↓
取回输出,重建原尺寸结果
          ↓
保存图片、生成 PDF、记录任务

神经网络算子由 C++ Vulkan 后端执行;提示图生成、形态学处理、坐标平滑和图像重采样由 CPU 上的 OpenCV 完成。

其中,“弯曲展平”还会先使用 MBD 模型取得页面分割信息,再通过 DocRes 预测坐标变化,把原图重新采样到展平后的页面。

当前实现采用 FP32 推理,并对同一输入做过官方 PyTorch FP32 数值对照。DocRes 在所测 256×256 输入上的最大绝对误差约为 1.43×10⁻⁶。这是网络数值对齐检查,实际文件的最终结果还会受到解码、缩放和前后处理的影响。

Vulkan 提供了跨厂商 GPU 计算的基础,但不同显卡仍需分别验证。目前的功能与耗时记录来自本机 RTX 4060 Laptop GPU,不把这个结果直接当作所有设备的表现。

实际运行要多久?

下面是本机 RTX 4060 Laptop GPU、Vulkan FP32 的短测记录,使用各任务对应的官方示例,连续运行两次,取第二次会话已准备好的数据。

任务网络处理尺寸网络 Run 耗时阶段总耗时
去阴影DocRes 512×512约 686 ms约 930 ms
外观增强DocRes 512×512约 686 ms约 1002 ms
去模糊DocRes 200×200约 110 ms约 111 ms
二值化DocRes 512×280约 378 ms约 392 ms
弯曲展平DocRes 256×256 + MBD 448×448约 169 + 42 ms约 426 ms

这里的 Run 包含数据上传、网络执行、同步和下载;阶段总耗时还包含提示生成与结果重建。表中不包含最终图片编码、落盘、PDF 和界面预览,且各行图片和任务不同,不适合互相比较快慢。

首次处理某个尺寸还需要准备 GPU 管线,可能等待几十秒。已有记录中,DocRes 256×256 首次无缓存准备约为 42 秒;同进程后续同尺寸处理会复用,重新启动时也会尝试使用磁盘缓存。

显存方面,512×512 DocRes 的中间张量工作区约为 1544 MiB,还要加上权重、传输缓冲、其他模型和驱动开销。这个数字是其中一部分内存,并非整卡显存占用。

日常使用可以先选“均衡”资源模式。资源模式通过在图片之间安排等待来调节连续处理节奏,单次 GPU 推理仍可能满负荷执行。

最近也补上了手机照片的小细节

有些手机照片看起来是竖图,文件内部保存的却是横向像素,查看器通过 EXIF 方向标记把它转正。如果软件只读取像素而忽略标记,选图后就会横过来。

最新 r1.1 已统一处理 EXIF 的旋转和镜像方向,让预览、推理和 PDF 使用一致的方向。同时修复了部分照片受 DPI 标记影响而放大裁切的问题。

这些细节未必显眼,但会直接影响软件拿到手之后是否好用。

想继续开发,也准备好了完整工程

源码提供完整 VS2022 解决方案,包含 C# WinForms 和 C++ Vulkan 核心项目。

WinForms 使用  .NET Framework 4.8,界面保留标准 .Designer.cs,可以继续在设计器里调整布局。安装对应的 .NET 桌面开发、C++ 桌面开发组件和 .NET 4.8 目标包后,打开解决方案,选择 Release | x64,将 DocRes.WinForms 设为启动项目即可编译运行。

工程带有正常构建所需的 Vulkan/OpenCV 头文件、库和离线模型。普通编译无需配置 Python 或重新导出模型;修改模型导出流程或重新编译 Shader 时,再使用相应开发工具。

目前整理的 r1.1 部署包约 226 MiB,完整源码包约 229 MiB。模型、上游代码和第三方组件的来源与许可声明也随工程保留。

如果你也喜欢折腾 C# 桌面程序、图像处理和 GPU 推理,欢迎一起交流:

QQ群:天天代码码天天
群号:264292622

最后也说一下使用预期:严重模糊、过曝或被遮挡的内容,无法保证恢复正确。处理作业、公式和重要资料时,建议保留原图,放大核对文字细节。

我希望这样的工具,既能方便整理一份讲义、一本笔记,也能让开源模型更容易被普通人用起来。