/// <summary> /// Get borders of meaning part of image /// </summary> /// <param name="angle">Skew angle of image</param> /// <param name="completedWidth">Width to which the image was completed</param> /// /// <param name="resultWidth">Width of result (deskewed) image</param> /// <param name="resultHeight">Height of result (deskewed) image</param> /// <param name="projectedImage">Projected image</param> /// <param name="originalWidth">Width of original image</param> /// <param name="originalHeight">Height of original image</param> /// <returns>Rectangle which bounds meaning part of image</returns> private static Rectangle GetImageBordersWithoutWhiteSpaces(double angle, int completedWidth, int resultWidth, int resultHeight, KrecImage projectedImage, int originalWidth, int originalHeight) { var smallImage = BitmapProcessor.RotateGrayscaleImage(projectedImage, -angle); // Для скорости, границы обрезки ищем на уменьшенном изображении var smallBinary = BitmapProcessor.BinarizeGrayscaleImage(smallImage); var cutBorders = ImagePartitioner.GetImageWithoutBorders(smallBinary); var k = (double)originalWidth / completedWidth; var preComplementWidth = (int)(originalWidth / k); var preComplementHeight = (int)(originalHeight / k); var scaleRect = GetUnprojectedRectangle(cutBorders, projectionSideWidth, projectionSideWidth, preComplementWidth, preComplementHeight, originalWidth, originalHeight, angle); int scaleXError = resultWidth / projectionSideWidth; //Увеличиваем с учетом погрешности int scaleYError = resultHeight / projectionSideWidth; scaleRect.X = Math.Max(scaleRect.X - scaleXError, 0); scaleRect.Y = Math.Max(scaleRect.Y - scaleYError, 0); scaleRect.Width = Math.Min(scaleRect.Width + scaleXError, resultWidth - scaleRect.X); scaleRect.Height = Math.Min(scaleRect.Height + scaleYError, resultHeight - scaleRect.Y); return(scaleRect); }
/// <summary> /// Fixing orientiation before returning scew angle /// </summary> /// <param name="originalImage">Original image</param> /// <param name="preparedImage">Prepared for deskewing image</param> /// <param name="angle">Calculated scew angle</param> /// <param name="preComplementWidth">Width used when resizing</param> /// <returns>Fixed descew angle</returns> private static double FixDocumentOrientation(KrecImage originalImage, KrecImage preparedImage, double angle, int preComplementWidth) { var deskewedImage = BitmapProcessor.RotateGrayscaleImage(originalImage, -angle); // TODO: бинаризацию можно сделать в этой точке, а не выполнять ее дважды в // TODO: GetImageBordersWithoutWhiteSpaces и GetAngleToRightOrientation var borders = GetImageBordersWithoutWhiteSpaces(angle, preComplementWidth, deskewedImage.Width, deskewedImage.Height, preparedImage, originalImage.Width, originalImage.Height); var imagePart = deskewedImage.GetSubregion(borders); var orientationResult = OrientationDeterminer.GetAngleToRightOrientation(imagePart); double orientAngle = orientationResult; double result = angle - orientAngle; if (result > Math.PI) { result -= 2 * Math.PI; } else if (result < -Math.PI) { result += 2 * Math.PI; } return(result); }