修复折痕/阴影变纯黑:在墨迹映射中加入背景亮度抑制
折痕处背景估计被拉低但bg-gray差值仍大,被误判为深墨迹。 现在通过比较背景估计值与纸面中心亮度的比值来判断: 背景低于纸面亮度75%时开始抑制墨迹输出(平方衰减), 越暗的区域抑制越强,阴影/折痕变浅灰或白色而非纯黑。 同时保留边缘扫描法处理四周连续暗边框。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -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 cx1 = w / 4;
|
||||||
int cx2 = w * 3 / 4;
|
int cx2 = w * 3 / 4;
|
||||||
@@ -412,11 +390,45 @@ public static class DocumentScanner
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
int paperBright = (int)(centerSum / Math.Max(centerCount, 1));
|
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++)
|
for (int x = 0; x < w; x++)
|
||||||
|
|||||||
Reference in New Issue
Block a user