From 2dcfcda850a930c25d606675a4e7e58a34c89b41 Mon Sep 17 00:00:00 2001 From: sinvo Date: Thu, 19 Mar 2026 16:34:37 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=96=87=E6=A1=A3=E8=BE=B9?= =?UTF-8?q?=E7=BC=98=E9=98=B4=E5=BD=B1=E5=8F=98=E7=BA=AF=E9=BB=91=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 通过背景亮度中位数计算阴影阈值,背景估计值低于中位数60%的区域 识别为拍照阴影,直接输出白色而非当作墨迹处理成黑色。 Co-Authored-By: Claude Opus 4.6 --- CamScanner.cs | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/CamScanner.cs b/CamScanner.cs index 271df07..00b2d70 100644 --- a/CamScanner.cs +++ b/CamScanner.cs @@ -376,8 +376,43 @@ public static class DocumentScanner // 增益:让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++) { + // 阴影检测:背景估计值很低 → 阴影区域 → 输出白色 + if (bgData[i] < shadowThresh) + { + resultData[i] = 255; + continue; + } + int ink = bgData[i] - grayData[i]; if (ink < 0) ink = 0;