diff --git a/CamScanner.cs b/CamScanner.cs index cce66e9..2d0b19c 100644 --- a/CamScanner.cs +++ b/CamScanner.cs @@ -374,28 +374,6 @@ public static class DocumentScanner } } - // 墨迹映射 - for (int i = 0; i < grayData.Length; i++) - { - int ink = bgData[i] - grayData[i]; - if (ink < 0) ink = 0; - - double inkNorm = (double)ink / ink95; - if (inkNorm > 1.0) inkNorm = 1.0; - - double darkness = Math.Pow(inkNorm, 0.45); - - int val = (int)(255.0 * (1.0 - darkness)); - if (val < 0) val = 0; - if (val > 255) val = 255; - resultData[i] = (byte)val; - } - - // --- 阴影修复:从边缘向内扫描,把连续暗像素区域设为白色 --- - // 阴影只出现在文档四周边缘(拍照翘边/光照不均) - // 从上下左右四个方向向内扫描原始灰度,遇到连续暗区域就标记为阴影 - byte[] shadowFlag = new byte[w * h]; // 0=正常, 1=阴影 - // 计算"正常纸面亮度":取灰度图中心区域的均值 int cx1 = w / 4; int cx2 = w * 3 / 4; @@ -412,11 +390,45 @@ public static class DocumentScanner } } int paperBright = (int)(centerSum / Math.Max(centerCount, 1)); - // 阴影判定:原始灰度低于纸面亮度的55% - int darkThresh = (int)(paperBright * 0.55); - // 从四个边缘向内扫描 - int maxScanDepth = Math.Max(w, h) / 8; // 最多扫描图像尺寸的1/8 + // 墨迹映射(带阴影/折痕保护) + // 文字特征:背景亮(接近paperBright),gray比背景低 → ink大 + // 折痕/阴影特征:gray本身就暗,背景估计也被拉低 → ink也可能大 + // 区分方法:看背景估计值是否接近正常纸面亮度 + // 如果 bgData[i] 接近 paperBright → 正常文字区域,正常处理 + // 如果 bgData[i] 远低于 paperBright → 阴影/折痕区域,抑制墨迹深度 + double bgThreshRatio = 0.75; // 背景低于纸面亮度75%就开始抑制 + + for (int i = 0; i < grayData.Length; i++) + { + int ink = bgData[i] - grayData[i]; + if (ink < 0) ink = 0; + + double inkNorm = (double)ink / ink95; + if (inkNorm > 1.0) inkNorm = 1.0; + + double darkness = Math.Pow(inkNorm, 0.45); + + // 阴影/折痕抑制:背景越暗,墨迹输出越浅 + double bgRatio = (double)bgData[i] / Math.Max(paperBright, 1); + if (bgRatio < bgThreshRatio) + { + // 背景很暗 → 阴影区域,大幅抑制 + // 线性衰减:bgRatio从0.75→0时,darkness从原值→0 + double suppress = bgRatio / bgThreshRatio; + darkness = darkness * suppress * suppress; // 平方衰减,更激进 + } + + int val = (int)(255.0 * (1.0 - darkness)); + if (val < 0) val = 0; + if (val > 255) val = 255; + resultData[i] = (byte)val; + } + + // --- 边缘阴影修复:从边缘向内扫描连续暗像素 --- + byte[] shadowFlag = new byte[w * h]; + int darkThresh = (int)(paperBright * 0.55); + int maxScanDepth = Math.Max(w, h) / 8; // 上边缘 for (int x = 0; x < w; x++)