修复文档边缘阴影变纯黑的问题

通过背景亮度中位数计算阴影阈值,背景估计值低于中位数60%的区域
识别为拍照阴影,直接输出白色而非当作墨迹处理成黑色。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-19 16:34:37 +08:00
parent 7352f55e9e
commit 2dcfcda850

View File

@@ -376,8 +376,43 @@ public static class DocumentScanner
// 增益让95百分位的墨迹深度映射到接近纯黑 // 增益让95百分位的墨迹深度映射到接近纯黑
// 用非线性映射(幂函数)让浅墨迹也能变深 // 用非线性映射(幂函数)让浅墨迹也能变深
//
// 阴影识别:拍照时文档边缘常有阴影,特征是:
// - 原始灰度很低(整体偏暗)
// - 背景估计也偏低(因为阴影区域大面积偏暗)
// - 但 bg - gray 的差值也可能很大
// 区分方法:如果背景估计值本身就很低(< 阈值),说明是阴影区域,
// 应该输出白色而非黑色
//
// 同时计算背景亮度的中位数,作为"正常纸面亮度"参考
int[] bgHist = new int[256];
for (int i = 0; i < bgData.Length; i++)
{
bgHist[bgData[i]]++;
}
int bgCum = 0;
int bgMedian = 128;
for (int i = 0; i < 256; i++)
{
bgCum += bgHist[i];
if (bgCum >= totalPixels / 2)
{
bgMedian = i;
break;
}
}
// 阴影阈值背景亮度低于中位数的60%视为阴影区域
int shadowThresh = (int)(bgMedian * 0.6);
for (int i = 0; i < grayData.Length; i++) for (int i = 0; i < grayData.Length; i++)
{ {
// 阴影检测:背景估计值很低 → 阴影区域 → 输出白色
if (bgData[i] < shadowThresh)
{
resultData[i] = 255;
continue;
}
int ink = bgData[i] - grayData[i]; int ink = bgData[i] - grayData[i];
if (ink < 0) ink = 0; if (ink < 0) ink = 0;