public static unsafe Mat NormalizeTextImage( Mat input, TextImageHistStats stats, Size size, double noiseStdevFactor = 1) { var x0 = stats.X0; var x1 = stats.X1; using var inverse_ = x1 < x0 ? ~input : null; using var inverse = inverse_ != null ? (Mat)inverse_ : null; if (x1 < x0) { x0 = 255 - x0; x1 = 255 - x1; } var background = (byte)Math.Max((int)(x1 - stats.Stdev1 * noiseStdevFactor), 0); var src = inverse ?? input; using var mean = src.Blur(size); var meanIndex = mean.GetUnsafeGenericIndexer <byte>(); var index = src.GetUnsafeGenericIndexer <byte>(); var normalized = new Mat(input.Size(), MatType.CV_8UC1); normalized.ForEachAsByte((value, position) => { var y = position[0]; var x = position[1]; var invalue = index[y, x]; var mean = meanIndex[y, x]; *value = mean < background ? invalue : background; }); var k = 255.0 / (background - x0); var lookup = new byte[256]; for (var i = 0; i < lookup.Length; ++i) { lookup[i] = i <= x0 ? (byte)0 : i >= x1 ? (byte)255 : (byte)Math.Min((i - x0) * k, 255); } using var lut = InputArray.Create(lookup); return(normalized.LUT(lut)); }
public static void Run() { using var scope = new Scope(); var ocrEngine = new TesseractEngine( @"C:\projects\git\Cheques\Cheques\ChequeOCR\traindata\", "eng+heb").In(scope); using var input = Cv2.ImRead(@"C:\temp\images\cheque1.jpg", ImreadModes.Grayscale); //using var input = Cv2.ImRead(@"C:\temp\images\cheque3.jpg", ImreadModes.Grayscale); // using var input = Cv2.ImRead(@"C:\temp\images\cheque1-rotated15.jpg", ImreadModes.Grayscale); //using var input = Cv2.ImRead(@"C:\projects\git\Cheques\Cheques\ChequeOCR\Lenna.png", ImreadModes.Grayscale); //using var input = Cv2.ImRead(@"C:\temp\images\cheque1.jpg"); //using var filtered = input.PyrMeanShiftFiltering(10, 32); //input.Dispose(); //using var src = filtered.CvtColor(ColorConversionCodes.RGB2GRAY); //filtered.Dispose(); var src = input; using var scaled = Scale(src, 1600); //using var bilateral = scaled.BilateralFilter(7, 50, 50); var background = GetBackground(scaled, .9); TextImageHistStats stats = GetTextImageHistStats(scaled); Console.WriteLine("Background: " + background); //using var masked = //RemoveWatermark(scaled, background, new Size(3, 3)); //NormalizeTextImage(scaled, stats, new Size(7, 7)); NormalizeTextImage2(scaled, new Size(5, 5)); //var otsu = NormalizeTextImage2(scaled, new Size(5, 5)); //using(new Window("Otsu", WindowMode.Normal | WindowMode.KeepRatio, otsu)) //{ // Cv2.WaitKey(); //} //using var clahe = Cv2.CreateCLAHE(); //var normalized = new Mat(); //clahe.Apply(masked, normalized); //masked = normalized; using var smooth = Smooth(masked, background, .1); var stopwatch = new Stopwatch(); stopwatch.Start(); using var sharpened = Sharpen(smooth, new Size(13, 13)); //using var sharpened = Sharpen(scaled, new Size(10, 10)); stopwatch.Stop(); Console.WriteLine("Sharpen: " + stopwatch.ElapsedMilliseconds); //using var blured = masked.GaussianBlur(new Size(25, 25), 0); var featureInfo = Features(ocrEngine, masked, new Size(18, 18), background); var features = sharpened.Clone(); features.DrawContours(featureInfo.Contours, -1, 64, 2); //features.DrawContours(points3, -1, Scalar.WhiteSmoke, 2); //foreach(var node in featureInfo.Nodes) //{ // if (node?.Contours != null) // { // features.DrawContours( // node.Contours, // -1, // 64, // 2, // LineTypes.Link4, // null, // int.MaxValue, // new Point(node.Left, node.Top)); // } //} //sharpened.SaveImage(@"C:\temp\images\cheque1\cheque1-sharpened.jpg"); //var page = OCR(ocrEngine, sharpened, 225); var nodes = featureInfo.Nodes. Where(node => node != null). OrderBy(node => node.Top). ThenBy(node => node.Left). ToList(); using (var ocrFile = File.CreateText(@"C:\temp\images\cheque1\cheque1-sharpened-ocr.json")) { var json = JsonSerializer.Serialize( nodes, new JsonSerializerOptions { IgnoreNullValues = true, WriteIndented = true, Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping }); ocrFile.WriteLine(json); } //using var binaryMask = input. // Threshold(100, 255, ThresholdTypes.BinaryInv | ThresholdTypes.Otsu). // Dilate(Mat.Ones(18, 18, MatType.CV_8SC1)); using (new Window("Image", WindowMode.Normal | WindowMode.KeepRatio, scaled)) using (new Window("Masked", WindowMode.Normal | WindowMode.KeepRatio, masked)) //using(new Window("BinaryMask", WindowMode.Normal | WindowMode.KeepRatio, binaryMask)) using (new Window("Sharpened", WindowMode.Normal | WindowMode.KeepRatio, sharpened)) using (new Window("Features", WindowMode.Normal | WindowMode.KeepRatio, features)) { Cv2.WaitKey(); } }