protected virtual void CheckCenterLine(Bitmap image) { var tmpImage = image.Copy(new Rectangle(0, 0, image.Width, image.Height)); var tmpImageData = tmpImage.LockBits(new Rectangle(new System.Drawing.Point(0, 0), tmpImage.Size), ImageLockMode.ReadWrite, tmpImage.PixelFormat); Drawing.Line(tmpImageData, new IntPoint(0, 0), new IntPoint(0, tmpImageData.Height), Color.White); tmpImage.UnlockBits(tmpImageData); OCRLessonReport.Imaging.HoughLineTransformation lineTransform = new OCRLessonReport.Imaging.HoughLineTransformation(); HoughLineRequestSettings vSettings = new HoughLineRequestSettings { HorizontalLines = false, VerticalLines = true }; var hWidth = tmpImage.Width / 2; var hHeight = tmpImage.Height / 2; lineTransform.ProcessImage(tmpImage, vSettings); HoughLine[] vLines = lineTransform.GetLinesByRelativeIntensity(0.9); var vLineCoordinates = vLines.Select(line => hWidth + line.Radius).Where(x => x > 1).OrderBy(x => x).ToArray(); if (vLineCoordinates.Length > 0) { var x0 = vLineCoordinates.FirstOrDefault() - 1; var x1 = vLineCoordinates.LastOrDefault() + 2; if (x1 - x0 > 10) { return; } var imageData = image.LockBits(new Rectangle(new System.Drawing.Point(0, 0), image.Size), ImageLockMode.ReadWrite, image.PixelFormat); Drawing.FillRectangle(imageData, new Rectangle(x0, 0, x1 - x0, image.Height), Color.Black); image.UnlockBits(imageData); } }
protected virtual double DetectRotation(Bitmap image) { //Hough line transformation OCRLessonReport.Imaging.HoughLineTransformation lineTransform = new OCRLessonReport.Imaging.HoughLineTransformation(); HoughLineRequestSettings settings = new HoughLineRequestSettings { HorizontalLines = false, VerticalLines = true, VerticalDeviation = Settings.SheetEdgeVerticalMaxAngle }; lineTransform.ProcessImage(image, settings); HoughLine[] lines = lineTransform.GetLinesByRelativeIntensity(Settings.SheetEdgeSensitivity); if (lines.Length < 1) { throw new Exception("Can't detect left edge"); } Func <HoughLine, double> getAngle = line => { double angle = 0; if (line.Theta > 90 && line.Radius > 0) { angle = 180 - line.Theta; } else if (line.Theta > 90 && line.Radius < 0) { angle = 180 - line.Theta; } else if (line.Theta < 90 && line.Radius > 0) { angle = -line.Theta; } else if (line.Theta < 90 && line.Radius < 0) { angle = -line.Theta; } return(angle); }; double avgAngle = lines.Select(l => getAngle(l)).Average(); return(avgAngle); }
protected virtual Bitmap ProcessCell(Bitmap cellImg, bool check = false) { //Build horizontal hough lines OCRLessonReport.Imaging.HoughLineTransformation lineTransform = new OCRLessonReport.Imaging.HoughLineTransformation(); HoughLineRequestSettings vSettings = new HoughLineRequestSettings { HorizontalLines = false, VerticalLines = true }; HoughLineRequestSettings hSettings = new HoughLineRequestSettings { HorizontalLines = true, VerticalLines = false }; lineTransform.ProcessImage(cellImg, vSettings); HoughLine[] vLines = lineTransform.GetLinesByRelativeIntensity(Settings.CellSensitivity); lineTransform.ProcessImage(cellImg, hSettings); HoughLine[] hLines = lineTransform.GetLinesByRelativeIntensity(Settings.CellSensitivity); var hWidth = cellImg.Width / 2; var hHeight = cellImg.Height / 2; var vLineCoordinates = vLines.Select(line => hWidth + line.Radius); var hLineCoordinates = hLines.Select(line => hHeight - line.Radius); var xEdges = GetCellEdges(vLineCoordinates, cellImg.Width, Settings.CellXEdgeWith, Settings.CellEdgeCutting); var yEdges = GetCellEdges(hLineCoordinates, cellImg.Height, Settings.CellYEdgeWith, Settings.CellEdgeCutting); cellImg = cellImg.Copy(new Rectangle(xEdges.Item1, yEdges.Item1, xEdges.Item2 - xEdges.Item1, yEdges.Item2 - yEdges.Item1)); //Check central line if (check) { CheckCenterLine(cellImg); } return(cellImg); }
public virtual void ProccessImage(BackgroundWorker worker) { this.worker = worker; UpdateProgress(3); //Brightness and sharpen filters BrightnessCorrection cfilter = new BrightnessCorrection(Settings.Brightness); GaussianSharpen filter = new GaussianSharpen(4, 11); //Apply filters cfilter.ApplyInPlace(sourceBitmap); UpdateProgress(15); filter.ApplyInPlace(sourceBitmap); UpdateProgress(30); //Convert to gray var tmpImage = ConvertToGrayScale(sourceBitmap); UpdateProgress(35); //Cut edges tmpImage = CutEdgesAndInvert(tmpImage); UpdateProgress(40); //Get angle for rotating image var rotateAngle = DetectRotation(tmpImage); UpdateProgress(45); if (rotateAngle != 0) { RotateBilinear rotate = new RotateBilinear(rotateAngle, true); tmpImage = rotate.Apply(tmpImage); } //Build horizontal hough lines OCRLessonReport.Imaging.HoughLineTransformation lineTransform = new OCRLessonReport.Imaging.HoughLineTransformation(); HoughLineRequestSettings settings = new HoughLineRequestSettings { HorizontalLines = true, VerticalLines = false, HorizontalDeviation = 2 }; lineTransform.ProcessImage(tmpImage, settings); //Get horizontal line HoughLine[] lines = lineTransform.GetLinesByRelativeIntensity(Settings.HorizontalSensitivity); //Get half width and height for future calculations int hWidth = tmpImage.Width / 2; int hHeight = tmpImage.Height / 2; //Get line coordinates (Y axis only - horizontal lines) var lineCoordinates = lines.Select(line => hHeight - line.Radius); //Grouping coords by delta var groupedCoordinates = ImagingHelper.GroupingCoordinates(lineCoordinates, Settings.LineGroupingDelta); if (groupedCoordinates.Count <= Settings.HeaderStartLine) { throw new Exception("Invalid source. Can't be recognized"); } int headerLineY0 = groupedCoordinates[Settings.HeaderStartLine]; int headerLineY1 = groupedCoordinates[Settings.HeaderStartLine + 1]; //Copy header to new image var headerImage = tmpImage.Copy(new Rectangle(0, headerLineY0, tmpImage.Width, headerLineY1 - headerLineY0)); //Parse header to get header lines HoughLineRequestSettings headerSettings = new HoughLineRequestSettings { HorizontalLines = false, VerticalLines = true, VerticalDeviation = 1 }; lineTransform.ProcessImage(headerImage, headerSettings); Func <HoughLine, int, int> getRadius = (l, w) => { if (l.Theta > 90 && l.Theta < 180) { return(w - l.Radius); } else { return(w + l.Radius); } }; HoughLine[] headerLines = lineTransform.GetLinesByRelativeIntensity(Settings.VerticalSensitivity); //Get header vertical lines var headerLineCoordinates = headerLines.Select(line => getRadius(line, hWidth)); //Grouped lines var groupedheaderLineCoordinates = ImagingHelper.GroupingCoordinates(headerLineCoordinates, Settings.LineGroupingDelta); //Build cell map List <TableCell> cellMap = new List <TableCell>(); UpdateProgress(50); //Use tess engine for ocr using (TesseractEngine engine = new TesseractEngine(Settings.TessdataPath, Settings.TessdataLanguage)) { //Parse top header var x0 = groupedheaderLineCoordinates.FirstOrDefault(); var x1 = groupedheaderLineCoordinates.LastOrDefault(); var y0 = groupedCoordinates[0]; var y1 = groupedCoordinates[1]; int fullProgress = (groupedheaderLineCoordinates.Count - 1) * (groupedCoordinates.Count - Settings.BottomStartLine - 1 - Settings.HeaderStartLine); int curProgress = 0; var hImage = tmpImage.Copy(new Rectangle(x0, y0, x1 - x0, y1 - y0)); hImage = ProcessCell(hImage); using (var page = engine.Process(hImage, PageSegMode.SingleBlock)) { cellMap.Add(new TableCell(0, 0, TableCellType.MainHeader, hImage, page.GetText(), false)); } //Parse table for (int i = 0; i < groupedheaderLineCoordinates.Count - 1; i++) { int subjectArea = (i < Settings.ColumnSubjectStart - 1) ? 0 : 1; for (int j = Settings.HeaderStartLine; j < groupedCoordinates.Count - Settings.BottomStartLine - 1; j++) { int headerArea = (j == Settings.HeaderStartLine) ? 2 : 0; TableCellType cellType = (TableCellType)(subjectArea + headerArea); var cellImg = tmpImage.Copy(new Rectangle(groupedheaderLineCoordinates[i], groupedCoordinates[j], groupedheaderLineCoordinates[i + 1] - groupedheaderLineCoordinates[i], groupedCoordinates[j + 1] - groupedCoordinates[j])); if (cellType == TableCellType.Text || cellType == TableCellType.Header || cellType == TableCellType.HeaderRotated) { cellImg = ProcessCell(cellImg, i == Settings.NameStartLine); string text = String.Empty; if (cellType == TableCellType.HeaderRotated) { cellImg.RotateFlip(RotateFlipType.Rotate90FlipNone); } using (var page = engine.Process(cellImg, PageSegMode.SingleBlock)) { text = page.GetText(); } cellMap.Add(new TableCell(i, j, cellType, cellImg, text, false)); } else { cellImg = ProcessCell(cellImg); BilateralSmoothing bfilter = new BilateralSmoothing(); bfilter.KernelSize = 7; bfilter.SpatialFactor = 10; bfilter.ColorFactor = 60; bfilter.ColorPower = 0.5; bfilter.ApplyInPlace(cellImg); cellImg = FilterColors(cellImg, Settings.FilteringColor, ByteColor.Black, ByteColor.White); BlobCounter bcounter = new BlobCounter(); bcounter.ProcessImage(cellImg); var blobs = bcounter.GetObjects(cellImg, false); if (blobs.Length < 1) { continue; } var biggestBlob = blobs.OrderBy(b => b.Area).LastOrDefault(); var biggestBlobsImage = biggestBlob.Image.ToManagedImage(); cellMap.Add(new TableCell(i, j, cellType, biggestBlobsImage, GetMask(biggestBlobsImage).ToString(), GetMask(biggestBlobsImage))); } curProgress++; double reportProgress = (double)curProgress / (double)fullProgress * 50 + 50; UpdateProgress((int)reportProgress); } } } this.Cells = cellMap; UpdateProgress(100); }