Очищаем скан листа от линеек с помощью фурье-преобразования.

На рисунке ниже пример скана тетрадного листа в линейку с цифрами, которые мы хотим распознать. Линейки нам довольно сильно мешают, особенно когда перечеркивают цифры. Хотелось бы их убрать, а цифры оставить. К счастью, это возможно.

Воспользуемся тем фактом, что линейки нарисованы через равный интервал, поэтому в частотном пространстве они будут представлены как одна очень яркая линия.

В данном случае она почти вертикальна, но может быть и слегка наклонной. Наша задача в том, чтобы обнаружить и закрасить эту линию в частотном пространстве, после чего преобразовать изображение в исходный вид. В результате получим примерно следующее:

А после дополнительной очистки, даже такое:

Ну, к коду. Импортируем все, что понадобится:

    import numpy as np
    from scipy.misc import imshow, imsave, imread, imresize
    from scipy.ndimage import filters, morphology
    from skimage import filter
    from skimage.draw import line
    from scipy import ndimage, spatial

Вспомогательная функция HoughLines, возвращающая самую яркую линию, проходящую через центр, в виде бинарной маски:

    def houghLines(img):
        w,h = img.shape
        acc=[]
        for i in range(h):
            rr,cc = line(0, i, w-1, h-i-1)
            acc.append(np.sum(img[rr, cc]))
        mi = np.argmax(acc)
        ret = np.zeros(img.shape, dtype=np.bool)
        rr,cc = line(0, mi, w-1, h-mi-1)
        ret[rr,cc]=True
        return ret

И основная функция:

def removeLines(img):
    imfft = np.fft.fft2(imggray)
    imffts = np.fft.fftshift(imfft)

    mags = np.abs(imffts)
    angles = np.angle(imffts)

    visual = np.log(mags)


    visual3 = np.abs(visual.astype(np.int16) - np.mean(visual))

    ret = houghLines(visual3)
    ret = morphology.binary_dilation(ret )
    ret = morphology.binary_dilation(ret )
    ret = morphology.binary_dilation(ret )
    ret = morphology.binary_dilation(ret )
    ret = morphology.binary_dilation(ret )
    w,h=ret.shape
    ret[w/2-3:w/2+3, h/2-3:h/2+3]=False


    delta = np.mean(visual[ret]) - np.mean(visual)


    visual_blured = ndimage.gaussian_filter(visual, sigma=5)



    visual[ret] =visual_blured[ret]


    newmagsshift = np.exp(visual)

    newffts = newmagsshift * np.exp(1j*angles)

    newfft = np.fft.ifftshift(newffts)

    imrev = np.fft.ifft2(newfft)

    newim2 =  np.abs(imrev).astype(np.uint8)


    newim2 = np.maximum(newim2, img)

    return newim2
Written on May 8, 2015