{{ message }}

Instantly share code, notes, and snippets.

# endolith/output.png

Last active Sep 4, 2020
Detecting rotation and line spacing of image of page of text using Radon transform # -*- coding: utf-8 -*- """ Automatically detect rotation and line spacing of an image of text using Radon transform If image is rotated by the inverse of the output, the lines will be horizontal (though they may be upside-down depending on the original image) It doesn't work with black borders """ from __future__ import division, print_function from skimage.transform import radon from PIL import Image from numpy import asarray, mean, array, blackman import numpy from numpy.fft import rfft import matplotlib.pyplot as plt from matplotlib.mlab import rms_flat try: # More accurate peak finding from # https://gist.github.com/endolith/255291#file-parabolic-py from parabolic import parabolic def argmax(x): return parabolic(x, numpy.argmax(x)) except ImportError: from numpy import argmax filename = 'skew-linedetection.png' # Load file, converting to grayscale I = asarray(Image.open(filename).convert('L')) I = I - mean(I) # Demean; make the brightness extend above and below zero plt.subplot(2, 2, 1) plt.imshow(I) # Do the radon transform and display the result sinogram = radon(I) plt.subplot(2, 2, 2) plt.imshow(sinogram.T, aspect='auto') plt.gray() # Find the RMS value of each row and find "busiest" rotation, # where the transform is lined up perfectly with the alternating dark # text and white lines r = array([rms_flat(line) for line in sinogram.transpose()]) rotation = argmax(r) print('Rotation: {:.2f} degrees'.format(90 - rotation)) plt.axhline(rotation, color='r') # Plot the busy row row = sinogram[:, rotation] N = len(row) plt.subplot(2, 2, 3) plt.plot(row) # Take spectrum of busy row and find line spacing window = blackman(N) spectrum = rfft(row * window) plt.plot(row * window) frequency = argmax(abs(spectrum)) line_spacing = N / frequency # pixels print('Line spacing: {:.2f} pixels'.format(line_spacing)) plt.subplot(2, 2, 4) plt.plot(abs(spectrum)) plt.axvline(frequency, color='r') plt.yscale('log') plt.show() ### endolith commented May 24, 2014 • edited

 http://tpgit.github.io/Leptonica/skew_8c_source.html has a probably faster algorithm that shears and then sums along raster lines, scoring based on "the square of the DIFFERENCE between adjacent line sums, summed over all lines" but would be limited to finding only angles that can be produced by shearing. The rotation method can find any angle, including 90 degrees, but can't distinguish that text is upside-down.

### yasinrawther commented Feb 8, 2017

 Hi endolith, I have tried with my billing image to skew correction. But it is too slow to processing the image. And it is take around 230 seconds. How can I resolve this issue? Thanks

### tangshao0804 commented May 6, 2019

 It's help for me, thank you very much.

### endolith commented May 6, 2019

 https://scantailor.org/ can do this very easily