SkewCorrector implements ImageProcessor<FImage> { @Override public void processImage(final FImage image) { final CannyEdgeDetector cad = new CannyEdgeDetector(); final FImage edgeImage = image.process(cad).inverse(); final HoughLines hl = new HoughLines(360 * this.accuracy); edgeImage.analyseWith(hl); if (SkewCorrector.DEBUG) this.debugLines(edgeImage, Matrix.identity(3, 3), "Detection of Horizontal Lines", hl.getBestLines(2)); double rotationAngle = hl.calculatePrevailingAngle(); FImage rotImg = null; FImage outImg = null; if (rotationAngle == Double.MIN_VALUE) { System.out.println("WARNING: Detection of rotation angle failed."); rotImg = edgeImage.clone(); outImg = image.clone(); } else { rotationAngle -= 90; rotationAngle %= 360; if (SkewCorrector.DEBUG) System.out.println("Rotational angle: " + rotationAngle); rotationAngle *= 0.0174532925; final Matrix rotationMatrix = new Matrix(new double[][] { { Math.cos(-rotationAngle), -Math.sin(-rotationAngle), 0 }, { Math.sin(-rotationAngle), Math.cos(-rotationAngle), 0 }, { 0, 0, 1 } }); rotImg = ProjectionProcessor.project(edgeImage, rotationMatrix, 1f). process(new OtsuThreshold()); outImg = ProjectionProcessor.project(image, rotationMatrix, 0f); } if (SkewCorrector.DEBUG) DisplayUtilities.display(outImg, "Rotated Image"); rotImg.analyseWith(hl); final float shearAngleRange = 20; if (SkewCorrector.DEBUG) this.debugLines(rotImg, Matrix.identity(3, 3), "Detection of Vertical Lines", hl.getBestLines(2, -shearAngleRange, shearAngleRange)); double shearAngle = hl.calculatePrevailingAngle(-shearAngleRange, shearAngleRange); if (shearAngle == Double.MIN_VALUE) { System.out.println("WARNING: Detection of shear angle failed."); } else { shearAngle %= 360; if (SkewCorrector.DEBUG) System.out.println("Shear angle = " + shearAngle); shearAngle *= 0.0174532925; final Matrix shearMatrix = new Matrix(new double[][] { { 1, Math.tan(shearAngle), 0 }, { 0, 1, 0 }, { 0, 0, 1 } }); outImg = outImg.transform(shearMatrix); } if (SkewCorrector.DEBUG) DisplayUtilities.display(outImg, "Final Image"); image.internalAssign(outImg); }  @Override void processImage(final FImage image); void setAccuracy(final int accuracy);  }
@Test public void testSkewCorrector() { try { final FImage testImage = ImageUtilities.readF( getClass().getResource("italic--20.png")).normalise(); final SkewCorrector sc = new SkewCorrector(); sc.processImage(testImage); } catch (final IOException e) { e.printStackTrace(); } }