public static void FindTextOfTextBlocks(GrayImage grayImage, List <TextBlock> textBlocks, bool isHorizontalTextLayout) { blocks = textBlocks; image = grayImage; isHorizontalText = isHorizontalTextLayout; ProcessFirstBlock(); int i; for (i = 1; i < blocks.Count - 1; i++) { if (blocks[i].IsNeedOCRProcess) { ProcessPotentialMergeBlock(ref i); } else { ClassifyTextBlock(blocks[i]); isPreviousMerge = false; } } if (i < blocks.Count) { ProcessFinalBlock(); } PostProcess.Start(blocks, isHorizontalText); }
public static void LinearNormalization(GrayImage img, TextBlock block) { FindAspectRatioAdaptiveNormalization(block.Height, block.Width, FeatureExtaction.SHAPE_NORM_TARGET_LENGTH); float width = (float)block.Width / NormWidth; float height = (float)block.Height / NormHeigth; int maxColumnIndex = block.Right; int maxRowIndex = block.Bottom; int shiftLeft = block.Left; int shiftTop = block.Top; int imgWidth = img.Width; int length = NormWidth * NormHeigth; Parallel.For(0, length, (index) => { int j = index % NormWidth; int i = index / NormWidth; int x0 = (int)Math.Floor(width * j) + shiftLeft; int y0 = (int)Math.Floor(height * i) + shiftTop; int imgIndex = imgWidth * y0 + x0; if (imgIndex < img.Pixels.Length) { Pixels[index] = img.Pixels[imgIndex]; } else { Pixels[index] = 0; } }); }
private static void CorrectBlockWidth(GrayImage image, TextBlock block) { int right = 0; int left = HorizontalTextProjection.MAX_INT; int width = image.Width; int topIndex = block.Top; int bottomIndex = block.Bottom + 1; int startIndex = block.Left; int stopIndex = block.Right + 1; for (int rowIndx = topIndex; rowIndx < bottomIndex; rowIndx++) { int index = rowIndx * width + startIndex; for (int j = startIndex; j < stopIndex; j++) { if (image.Pixels[index] > 0) { if (j < left) { left = j; } if (j > right) { right = j; } } index++; } } block.Width = right - left + 1; block.Left = left; block.Right = right; }
private static bool SplitMultiBlock(List <TextBlock> blocks, uint[] density, GrayImage image, int i) { int splitIndex = GetSplitIndexOfBlock(blocks[i], density); if (splitIndex < blocks[i].Top + 2 || splitIndex > blocks[i].Bottom - 2) { return(false); } TextBlock bottomHalf = new TextBlock() { Left = blocks[i].Left, Right = blocks[i].Right, Top = splitIndex, Bottom = blocks[i].Bottom, Height = blocks[i].Bottom - splitIndex + 1, Type = TextBlockType.Multi }; CorrectBlockWidth(image, bottomHalf); blocks.Insert(i + 1, bottomHalf); blocks[i].Bottom = splitIndex; blocks[i].Height = blocks[i].Bottom - blocks[i].Top + 1; CorrectBlockWidth(image, blocks[i]); return(true); }
public static bool IsWhiteOnBlack(GrayImage image, int threshold) { int width = image.Width; int height = image.Height; int temp = 0; int lastRow = (height - 1) * width; for (int j = 0; j < width; j++) { temp += image.Pixels[j]; temp += image.Pixels[lastRow + j]; } int lastCol = width - 1; for (int i = 0; i < height; i++) { temp += image.Pixels[i * width]; temp += image.Pixels[i * width + lastCol]; } double avgDen = (double)(temp) / ((width + height) * 2); if (avgDen < threshold) { return(true); } else { return(false); } }
public static void StartBinarized(GrayImage image) { var otsu = GetOtsuBinarizedParams(image); bool isWhiteOnBlack = IsWhiteOnBlack(image, otsu.Threshold); OtsuBinarizedImage(image, otsu, isWhiteOnBlack); }
private static void DebugTextExtract(GrayImage image, List <TextBlock> textBlocks, ShowImageHandle showImageFunction) { var displayImage = image.Clone(); Helper.DrawTextBlockBox(displayImage, textBlocks); showImageFunction(displayImage); }
private static long GetRawMoment00(GrayImage img, TextBlock block) { int shiftTop = block.Top; int shiftLeft = block.Left; int width = img.Width; long moment = 0; int start = shiftTop * width + shiftLeft; int textBlockWidth = block.Width; int textBlockHeight = block.Height; int skipWidth = width - textBlockWidth; for (int i = 0; i < textBlockHeight; i++) { for (int j = 0; j < textBlockWidth; j++) { if (img.Pixels[start] > 0) { moment++; } start++; } start += skipWidth; } return(moment); }
public static void DrawTextBlockBox(GrayImage image, List <TextBlock> blocks) { foreach (var block in blocks) { int start = block.Top * image.Width + block.Left; for (int i = start; i < start + block.Width; i++) { image.Pixels[i] = 255; } start = block.Bottom * image.Width + block.Left; for (int i = start; i < start + block.Width; i++) { image.Pixels[i] = 255; } for (int i = block.Top * image.Width + block.Left; i < block.Bottom * image.Width; i += image.Width) { image.Pixels[i] = 255; } for (int i = block.Top * image.Width + block.Right; i < block.Bottom * image.Width; i += image.Width) { image.Pixels[i] = 255; } } }
public GrayImage Clone() { GrayImage cloneImg = new GrayImage(Width, Height); cloneImg.Pixels = new byte[Pixels.Length]; Pixels.CopyTo(cloneImg.Pixels, 0); return(cloneImg); }
private static int[] GetImageHistogram(GrayImage image) { int[] hist = new int[NUMBER_OF_GRAY_LEVELS]; for (int i = 0; i < image.Pixels.Length; i++) { hist[image.Pixels[i]] = hist[image.Pixels[i]] + 1; } return(hist); }
private static void DebugShapNormilization(GrayImage image, List <TextBlock> textBlocks, ShowImageHandle showImageFunction) { foreach (var b in textBlocks) { ShapeNormalization.LinearNormalization(image, b); GrayImage bImag = new GrayImage(ShapeNormalization.NormWidth, ShapeNormalization.NormHeigth); bImag.Pixels = ShapeNormalization.Pixels; showImageFunction(bImag); } }
public static List <TextBlock> RecognizeOneWord(GrayImage image) { ColorConverter.StartBinarized(image); var textBlock = Classifier.ClassifyOneText(image); var blocks = new List <TextBlock>(1); blocks.Add(textBlock); return(blocks); }
public static List <TextBlock> RecognizeSentences(GrayImage image) { ColorConverter.StartBinarized(image); var textBlocks = TextExtraction.FindTextBlocks(image); if (textBlocks.Count > 0) { Classifier.FindTextOfTextBlocks(image, textBlocks, TextExtraction.IsHorizontalText); } return(textBlocks); }
private static List <TextBlock> ProcessHorizontalLines(GrayImage image, uint[] vertical) { List <TextBlock> textBlocks = new List <TextBlock>(); List <SplitMultiLines.Line> textLines = SplitMultiLines.SplitProjectDensity(vertical); for (int i = 0; i < textLines.Count; i++) { var density = Projection.ProjectSubImageOnHorizontalLine(image, textLines[i]); textBlocks.AddRange(HorizontalTextProjection.FindAllTextBlock(image, density, textLines[i], i)); } return(textBlocks); }
private static List <TextBlock> ProcessVerticalLines(GrayImage image, uint[] horizontal) { List <TextBlock> textBlocks = new List <TextBlock>(); List <SplitMultiLines.Line> textLines = SplitMultiLines.SplitProjectDensity(horizontal); textLines.Reverse(); //Japanese column is going from right to left for (int i = 0; i < textLines.Count; i++) { var density = Projection.ProjectSubImageOnVerticalLine(image, textLines[i]); textBlocks.AddRange(VerticalTextProjection.FindAllTextBlock(image, density, textLines[i], i)); } return(textBlocks); }
public static TextBlock ClassifyOneText(GrayImage grayImage) { isHorizontalText = true; image = grayImage; TextBlock block = InitOneTextBlock(); block.Type = TextBlockType.Single; block.IsNeedOCRProcess = false; block.Ratio = 1; block.HeighRatio = 1; ClassifyTextBlock(block); return(block); }
/// <summary> /// Get sub images from the results returned by SplitProjectDensity() /// </summary> /// <param name="image">Image that has been analyzed and split by Split(uint[] density)</param> /// <param name="space">A split block</param> /// <param name="isHorizontal">True if text layout is horizontal</param> /// <returns></returns> public static GrayImage GetSubImage(GrayImage image, Line block, bool isHorizontal) { GrayImage subImage; if (isHorizontal) { subImage = GetHorizontalSplitImage(image, block); } else { subImage = GetVerticalSplitImage(image, block); } return(subImage); }
private static List <TextBlock> ExtractTextBlocks(GrayImage image, bool isHorizontalText) { IsHorizontalText = isHorizontalText; if (isHorizontalText) { var vertical = Projection.ProjectOnVerticalLine(image); return(ProcessHorizontalLines(image, vertical)); } else { var horizontal = Projection.ProjectOnHorizontalLine(image); return(ProcessVerticalLines(image, horizontal)); } }
/// <summary> /// This function is for debugging purposes only /// </summary> /// <param name="image"></param> /// <param name="showImageFunction"></param> /// <returns></returns> public static List <TextBlock> Start(GrayImage image, ShowImageHandle showImageFunction) { ColorConverter.StartBinarized(image); var textBlocks = TextExtraction.FindTextBlocks(image); DebugTextExtract(image, textBlocks, showImageFunction); //DebugShapNormilization(image, textBlocks, showImageFunction); if (textBlocks.Count > 0) { Classifier.FindTextOfTextBlocks(image, textBlocks, TextExtraction.IsHorizontalText); } return(textBlocks); }
public static GrayImage ConvertFloatToByteImage(float[] img, int height, int width) { GrayImage imageOut = new GrayImage(width, height); imageOut.Pixels = new byte[width * height]; float max = float.MinValue; float min = float.MaxValue; for (int i = 0; i < img.Length; i++) { if (img[i] > max) { max = img[i]; } if (img[i] < min) { min = img[i]; } } for (int i = 0; i < img.Length; i++) { img[i] += -min; } float maxRange = max - min; float scale = 255 / maxRange; float value; for (int i = 0; i < img.Length; i++) { value = img[i] * scale; if (value > 255) { value = 255; } else if (value < 0) { value = 0; } imageOut.Pixels[i] = (byte)value; } return(imageOut); }
public static void MomentNormalization(GrayImage img, TextBlock block) { var M10 = GetRawMoment10(img, block); var M01 = GetRawMoment01(img, block); var M00 = GetRawMoment00(img, block); if (M00 == 0) { LinearNormalization(img, block); } var cX = M10 / M00; var cY = M01 / M00; var u20 = GetRawMoment20(img, block) - cX * M10; var u02 = GetRawMoment02(img, block) - cY * M01; if (u20 <= 0 || u02 <= 0) { LinearNormalization(img, block); } double deltaX2 = u20 * 16.0; double deltaY2 = u02 * 16.0; double deltaX = Math.Sqrt(deltaX2); double deltaY = Math.Sqrt(deltaY2); FindAspectRatioAdaptiveNormalization(deltaY, deltaX, FeatureExtaction.SHAPE_NORM_TARGET_LENGTH); double halfWidth = NormWidth / 2; double halfHeight = NormHeigth / 2; int shiftTop = block.Top; int shiftLeft = block.Left; int imgWidth = img.Width; int textWidth = block.Width; int textHeight = block.Height; int length = NormWidth * NormHeigth; Parallel.For(0, length, (index) => { int i = index / NormWidth; int j = index % NormWidth; double xs = deltaX * (j - halfWidth) / NormWidth + cX; double ys = deltaY * (i - halfHeight) / NormHeigth + cY; int x0 = GetOriginalPixelCoordinate(xs, cX, deltaX, deltaX2, textWidth); int y0 = GetOriginalPixelCoordinate(ys, cY, deltaY, deltaY2, textHeight); int originalIndex = (y0 + shiftTop) * imgWidth + x0 + shiftLeft; Pixels[index] = img.Pixels[originalIndex]; }); }
private static List <TextBlock> ExtractTextBlocks(GrayImage image) { var vertical = Projection.ProjectAndFindVarianceOnVerticalLine(image); var horizontal = Projection.ProjectAndFindVarianceOnHorizontalLine(image); IsHorizontalText = Projection.IsHorizontalTextLayout(vertical.Vtheta, horizontal.Vtheta); if (IsHorizontalText) { return(ProcessHorizontalLines(image, vertical.Density)); } else { return(ProcessVerticalLines(image, horizontal.Density)); } }
public static List <TextBlock> FindTextBlocks(GrayImage image, bool?isHorizontal = null) { List <TextBlock> textBlocks; if (isHorizontal == null) { textBlocks = ExtractTextBlocks(image); } else { textBlocks = ExtractTextBlocks(image, (bool)isHorizontal); } RemoveNoiseTextBlocks(textBlocks); return(textBlocks); }
public static void OtsuBinarizedImage(GrayImage image, Otsu otsu, bool isWhiteOnBlack) { if (isWhiteOnBlack) { Parallel.For(0, image.Pixels.Length, (i) => { image.Pixels[i] = image.Pixels[i] > otsu.Threshold ? image.Pixels[i] : MIN_BINARY; }); } else { Parallel.For(0, image.Pixels.Length, (i) => { image.Pixels[i] = image.Pixels[i] > otsu.Threshold ? MIN_BINARY : (byte)(MAX_BINARY - image.Pixels[i]); }); } }
private static List <TextBlock> InitTextBlocks(GrayImage image, uint[] density, int lineIndex) { sumBlockWidth = 0; sumBlockHeight = 0; List <TextBlock> blocks = new List <TextBlock>(); bool isStartBlock = false; TextBlock block; int top = 0; for (int j = 1; j < density.Length; j++) { if (density[j] > 0) { if (!isStartBlock) { isStartBlock = true; top = j; } } else { if (isStartBlock) { block = GetBlock(image, top, j); block.LineIndex = lineIndex; blocks.Add(block); sumBlockHeight += block.Height; sumBlockWidth += block.Width; } isStartBlock = false; } } if (isStartBlock) { block = GetBlock(image, top, image.Height); block.LineIndex = lineIndex; blocks.Add(block); sumBlockHeight += block.Height; sumBlockWidth += block.Width; } return(blocks); }
private static void GetOutLinePixelsPosition(GrayImage image, ref int left, ref int right, ref int top, ref int bottom) { if (left > 0) { left--; } if (right < image.Width - 1) { right++; } if (top > 0) { top--; } if (bottom < image.Height - 1) { bottom++; } }
public static uint[] ProjectOnHorizontalLine(GrayImage image) { int width = image.Width; var density = new uint[width]; Parallel.For(0, density.Length, (j) => { uint lineProject = 0; for (int index = j; index < image.Pixels.Length; index += width) { if (image.Pixels[index] > 0) { lineProject++; } } density[j] = lineProject; }); return(density); }
public static uint[] ProjectOnVerticalLine(GrayImage image) { int width = image.Width; var density = new uint[image.Height]; Parallel.For(0, density.Length, (i) => { int index = i * width; uint lineProject = 0; for (int j = 0; j < width; j++) { if (image.Pixels[index] > 0) { lineProject++; } index++; } density[i] = lineProject; }); return(density); }
public static uint[] ProjectSubImageOnHorizontalLine(GrayImage image, SplitMultiLines.Line line) { int width = image.Width; var density = new uint[width]; int stop = line.StartSpace * width; Parallel.For(0, width, (j) => { int start = width * line.StartText + j; uint lineProject = 0; for (int index = start; index < stop; index += width) { if (image.Pixels[index] > 0) { lineProject++; } } density[j] = lineProject; }); return(density); }