diff --git a/CamScanner.cs b/CamScanner.cs index 551dccf..f8ad70e 100644 --- a/CamScanner.cs +++ b/CamScanner.cs @@ -418,6 +418,77 @@ public static class DocumentScanner whiteLutMat.Dispose(); sharpened.Dispose(); + // --- g: 边缘阴影清除 --- + // 从四边向内扫描原始灰度图,连续暗像素区域标记为阴影→纯白 + // 除法归一化对均匀阴影免疫,但边缘深色阴影bg也被拉低, + // 除法后比值偏低变成灰色,需要额外清除 + int cx1 = w / 4; + int cx2 = w * 3 / 4; + int cy1 = h / 4; + int cy2 = h * 3 / 4; + long centerSum = 0; + int centerCount = 0; + for (int py = cy1; py < cy2; py++) + { + for (int px = cx1; px < cx2; px++) + { + centerSum += grayData[py * w + px]; + centerCount++; + } + } + int paperBright = (int)(centerSum / Math.Max(centerCount, 1)); + int darkThresh = (int)(paperBright * 0.6); + int maxScanDepth = Math.Max(w, h) / 4; // 最多扫描1/4深度 + + byte[] cleanedData = new byte[w * h]; + Marshal.Copy(cleaned.Data, cleanedData, 0, cleanedData.Length); + + // 上边缘 + for (int x = 0; x < w; x++) + { + for (int y = 0; y < Math.Min(maxScanDepth, h); y++) + { + if (grayData[y * w + x] < darkThresh) + cleanedData[y * w + x] = 255; + else + break; + } + } + // 下边缘 + for (int x = 0; x < w; x++) + { + for (int y = h - 1; y >= Math.Max(0, h - maxScanDepth); y--) + { + if (grayData[y * w + x] < darkThresh) + cleanedData[y * w + x] = 255; + else + break; + } + } + // 左边缘 + for (int py = 0; py < h; py++) + { + for (int x = 0; x < Math.Min(maxScanDepth, w); x++) + { + if (grayData[py * w + x] < darkThresh) + cleanedData[py * w + x] = 255; + else + break; + } + } + // 右边缘 + for (int py = 0; py < h; py++) + { + for (int x = w - 1; x >= Math.Max(0, w - maxScanDepth); x--) + { + if (grayData[py * w + x] < darkThresh) + cleanedData[py * w + x] = 255; + else + break; + } + } + Marshal.Copy(cleanedData, 0, cleaned.Data, cleanedData.Length); + // 转回3通道 Mat output = new Mat(); Cv2.CvtColor(cleaned, output, ColorConversionCodes.GRAY2BGR);