修复文字淡:gamma加到2.5+范围150,白底清理改用LUT分段映射
之前Trunc+拉伸会把文字也放大变淡。改用LUT分段映射: - <60:保持原值(文字深黑不变) - 60-150:平滑过渡到255(灰色渐变区域推白) - >150:纯白(背景) 文字不被拉伸,背景变纯白。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -367,18 +367,14 @@ public static class DocumentScanner
|
|||||||
Marshal.Copy(resultData, 0, normU8.Data, resultData.Length);
|
Marshal.Copy(resultData, 0, normU8.Data, resultData.Length);
|
||||||
|
|
||||||
// --- d: 非线性对比度增强 ---
|
// --- d: 非线性对比度增强 ---
|
||||||
// gamma 曲线压暗 + 线性拉伸加深,两步结合:
|
// gamma 曲线压暗,保留笔画间灰度层次
|
||||||
// gamma 保留笔画间灰度层次
|
// 输出范围压到 0-150,给白底清理留空间
|
||||||
// 线性拉伸让文字整体更黑
|
|
||||||
byte[] lut = new byte[256];
|
byte[] lut = new byte[256];
|
||||||
for (int i = 0; i < 256; i++)
|
for (int i = 0; i < 256; i++)
|
||||||
{
|
{
|
||||||
double x = i / 255.0;
|
double x = i / 255.0;
|
||||||
// gamma=2.2 压暗
|
double y = Math.Pow(x, 2.5);
|
||||||
double y = Math.Pow(x, 2.2);
|
int val = (int)(y * 150.0);
|
||||||
// 再做线性拉伸:输出范围压缩到 0-200,之后白底清理会把200+推白
|
|
||||||
// 这样文字更黑但笔画间差异按比例保留
|
|
||||||
int val = (int)(y * 200.0);
|
|
||||||
if (val > 255) val = 255;
|
if (val > 255) val = 255;
|
||||||
lut[i] = (byte)val;
|
lut[i] = (byte)val;
|
||||||
}
|
}
|
||||||
@@ -397,17 +393,37 @@ public static class DocumentScanner
|
|||||||
contrasted.Dispose();
|
contrasted.Dispose();
|
||||||
|
|
||||||
// --- f: 白底清理 ---
|
// --- f: 白底清理 ---
|
||||||
// gamma后文字大约在 0-80,背景大约在 150-200
|
// 用 LUT:<60 保持原值(文字),60-150 快速过渡到白色,>150 纯白
|
||||||
// 阈值 160:>160 的推白(背景),<160 的保留(文字)
|
byte[] whiteLut = new byte[256];
|
||||||
Cv2.Threshold(sharpened, sharpened, 160, 255, ThresholdTypes.Trunc);
|
for (int i = 0; i < 256; i++)
|
||||||
Cv2.ConvertScaleAbs(sharpened, sharpened, 255.0 / 160.0, 0);
|
{
|
||||||
|
if (i <= 60)
|
||||||
|
{
|
||||||
|
whiteLut[i] = (byte)i; // 文字保持不变
|
||||||
|
}
|
||||||
|
else if (i <= 150)
|
||||||
|
{
|
||||||
|
// 平滑过渡到白色
|
||||||
|
double t = (double)(i - 60) / 90.0;
|
||||||
|
whiteLut[i] = (byte)(60 + (int)(t * t * 195)); // 60→255
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
whiteLut[i] = 255; // 纯白
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Mat whiteLutMat = new Mat(1, 256, MatType.CV_8U, whiteLut);
|
||||||
|
Mat cleaned = new Mat();
|
||||||
|
Cv2.LUT(sharpened, whiteLutMat, cleaned);
|
||||||
|
whiteLutMat.Dispose();
|
||||||
|
sharpened.Dispose();
|
||||||
|
|
||||||
// 转回3通道
|
// 转回3通道
|
||||||
Mat output = new Mat();
|
Mat output = new Mat();
|
||||||
Cv2.CvtColor(sharpened, output, ColorConversionCodes.GRAY2BGR);
|
Cv2.CvtColor(cleaned, output, ColorConversionCodes.GRAY2BGR);
|
||||||
|
|
||||||
gray.Dispose();
|
gray.Dispose();
|
||||||
sharpened.Dispose();
|
cleaned.Dispose();
|
||||||
src.Dispose();
|
src.Dispose();
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
|
|||||||
Reference in New Issue
Block a user