private void RunOCR(Bitmap sourceImage) { this.sourceImagePV.Image = sourceImage; Bitmap bw = ImageUtil.ToBlackAndWhite(sourceImage); this.bwImagePV.Image = bw; Bitmap rotBw = ImageUtil.RotateCounterClockwise(bw); this.rotBwImagePV.Image = rotBw; var horizOptions = RecognitionOptions.HorizontalOptions(); horizOptions.imageWidth = bw.Width; horizOptions.imageHeight = bw.Height; var vertOptions = RecognitionOptions.VerticalOptions(); vertOptions.imageWidth = rotBw.Width; vertOptions.imageHeight = rotBw.Height; List <Point> horizEdgePoints = EdgePointExtraction.ExtractEdgePoints(bw); this.edgePointsPV.Image = EdgePointExtraction.DrawPoints(bw, horizEdgePoints); int[,] horizHough = PseudoHoughTransform.HoughTransform(horizEdgePoints, horizOptions); List <Point> horizHoughPeaks = PseudoHoughTransform.FindHoughPeaks(horizHough, horizOptions); Bitmap horizHoughPlainImage = PseudoHoughTransform.HoughTransformImage(horizHough); Bitmap horizHoughImage = PseudoHoughTransform.HoughTransformImageWithPeaks(horizHough, horizHoughPeaks); List <RawLine> horizRawLines = PseudoHoughTransform.ExtractRawLines(horizHoughPeaks, horizOptions); List <Line> horizLines = LineFilter.FilterLines(horizEdgePoints, horizRawLines, horizOptions); List <Point> vertEdgePoints = EdgePointExtraction.ExtractEdgePoints(rotBw); this.rotEdgePointsPV.Image = EdgePointExtraction.DrawPoints(rotBw, vertEdgePoints); int[,] vertHough = PseudoHoughTransform.HoughTransform(vertEdgePoints, vertOptions); List <Point> vertHoughPeaks = PseudoHoughTransform.FindHoughPeaks(vertHough, vertOptions); Bitmap vertHoughPlainImage = PseudoHoughTransform.HoughTransformImage(vertHough); Bitmap vertHoughImage = PseudoHoughTransform.HoughTransformImageWithPeaks(vertHough, vertHoughPeaks); List <RawLine> vertRawLines = PseudoHoughTransform.ExtractRawLines(vertHoughPeaks, vertOptions); this.cyclicPatternsPV.Image = CyclicPatternDetector.CyclicPatternsInLines(vertEdgePoints, vertRawLines, vertOptions); RecognitionOptions vertNoFilterOptions = vertOptions; vertNoFilterOptions.detectCyclicPatterns = false; List <Line> vertUnfilteredLines = LineFilter.FilterLines(vertEdgePoints, vertRawLines, vertNoFilterOptions); List <Line> vertLines = LineFilter.FilterLines(vertEdgePoints, vertRawLines, vertOptions); Bitmap rawLinesImage = DrawLines(bw, horizLines, vertUnfilteredLines, 2); Bitmap filteredLinesImage = DrawLines(bw, horizLines, vertLines, 4); this.filteredLinesPV.Image = filteredLinesImage; this.houghPV.Image = ImageUtil.VerticalConcat(new List <Bitmap> { ImageUtil.HorizontalConcat(new List <Bitmap> { rawLinesImage, horizHoughImage, horizHoughPlainImage }), ImageUtil.RotateClockwise(vertHoughImage), ImageUtil.RotateClockwise(vertHoughPlainImage) }); var lnorm = new LineNormalization(horizLines, vertLines, sourceImage); Bitmap normalizedLinesImage = DrawLines(bw, lnorm.normHorizLines, lnorm.normVertLines, 2); this.normalizedLinesPV.Image = normalizedLinesImage; var tb = TableBuilder.NewBuilder(lnorm, new None <List <double> >()); Bitmap tableRecognitionImage = tb.DebugImage(bw); this.tableRecognitionPV.Image = tableRecognitionImage; Option <Table> recognizedTable = tb.table; recognizedTable.ForEach(table => { Bitmap recognizedTableImage = new Bitmap(bw); Graphics g = Graphics.FromImage(recognizedTableImage); table.DrawTable(g, new Pen(Color.Red, 2)); g.Dispose(); this.recognizedTablePV.Image = recognizedTableImage; }); if (recognizedTable.IsEmpty()) { Console.WriteLine("no table was recognized"); } this.recognizedTablePV.AddDoubleClickListener((pt, e) => { recognizedTable.ForEach(table => { table.GetCellAtPoint(pt.X, pt.Y).ForEach(cell => { table.GetCellImage(bw, cell.X, cell.Y).ForEach(cellImage => { new GradeRecognitionDebugView(cellImage, "<gen>").ShowDialog(); }); }); }); }); }