Автоматическое улучшение изображения отсканированного документа

Я разрабатываю автоматическое улучшение изображения на основе документа Microsoft Сканирование белой доски и улучшение изображения

в разделе «Баланс белого и улучшение изображения» приведены шаги по улучшению:

Во-первых: они оценивают фон отсканированного документа или обнаруженной белой доски:

1. "Разделите область доски на прямоугольные ячейки. Размер ячейки должен быть примерно таким же, как мы ожидаем, размер одного символа на доске (15 на 15 пикселей в нашей реализации)".

потом

2. "Отсортируйте пиксели в каждой ячейке по значениям их яркости. Поскольку чернила поглощают падающий свет, яркость пикселей доски выше, чем пикселей обводки". Цвет доски внутри ячейки: следовательно, цвет с наибольшей яркостью. На практике мы усредняем цвета пикселей в верхних 25 процентилях, чтобы уменьшить ошибку, вносимую шумом сенсора».

потом

3. "Отфильтруйте цвета ячеек, локально подобрав плоскость в пространстве RGB. Иногда встречаются ячейки, полностью покрытые штрихами пера, следовательно, цвет ячейки, вычисленный на шаге 2, неверен. Эти цвета отбрасываются локально подобранной плоскостью как выбросы и заменяются интерполированными значениями от ее соседей».

Моя проблема связана со вторым и третьим шагами:

Как они получают значение яркости, следует ли преобразовать входное изображение в цветовое пространство YUV и получить значение яркости из канала Y или просто работать с цветовым пространством RGB?

Как разместить локальную плоскость в пространстве RGB?

Вот мой код Python, который я пытался сделать из входного изображения, получить значение яркости из цветового пространства YUV и простой результат, который кажется неверным по сравнению с результатом, который они получают в документе.

Код Python:

import cv2
import numpy as np



## Return List of cells from a given Image
def SubImage(image):
    Cells = []
    CellRows = []
    for i in range(0,rows/CellSize):
        subIm = image[i*CellSize:(i+1)*CellSize,:]
        CellRows.append(subIm)
    for img in CellRows:
        for i in range(0,cols/CellSize):
            subIm = img[:,i*CellSize:(i+1)*CellSize]
            Cells.append(subIm)
    return Cells


## Sort luminosity Value
def GetLuminance(Cells):
    luminance = []
    for cel in Cells:
        luminance.append(cel.max())
    return luminance


## Estimate the background color of the white board
def UniformBackground(CelImage,img,luminance):
    a = 0

    for c in range(0,len(CelImage)):
        cel = CelImage[c]
        for i in range(0,cel.shape[0]):
            for j in range(0, cel.shape[1]):
                cel[i,j] = min(1,cel[i,j]/ luminance[c])
    for i in range(0,rows/CellSize):
        for j in range(0,cols/CellSize):
            img[i*CellSize:(i+1)*CellSize,j*CellSize:(j+1)*CellSize] = CelImage[a]
            a = a + 1

if __name__ == '__main__':
    img = cv2.imread('4.png')
    CellSize = 15
    rows,cols,depth = img.shape


    if (rows%CellSize !=0):
        rows = rows - rows%CellSize

    if (cols%CellSize !=0):
        cols = cols - cols%CellSize

    yuvImg = cv2.cvtColor(img, cv2.COLOR_BGR2YUV)
    # Get cells from Y channel
    CellsY = SubImage(yuvImg[:,:,0])
    CellsB = SubImage(img[:,:,0])
    CellsG = SubImage(img[:,:,1])
    CellsR = SubImage(img[:,:,2])

    # Get Luminance From Y cells
    LuminanceY = GetLuminance(CellsY)

    # Uniform Background
    UniformBackground(CellsB, img[:,:,0], LuminanceY)
    UniformBackground(CellsG, img[:,:,1], LuminanceY)
    UniformBackground(CellsR,img[:,:,2], LuminanceY)

    #bgrImg = cv2.cvtColor(imgB, cv2.COLOR_GRAY2BGR)
    #print imgB
    cv2.imwrite('unifrom.jpg',img)

Введите изображение белой доски:

белое изображение доски

выходное изображение:

Выходное изображение

Ожидаемый результат:

ожидаемый результат


person Raid Lafi    schedule 12.07.2018    source источник
comment
Я предполагаю, что ваше выходное изображение имеет тип float из этой строки cel[i,j] = min(255,cel[i,j]/ luminance[c]). Преобразуйте его в тип int.   -  person Jeru Luke    schedule 12.07.2018
comment
хорошо сейчас попробую   -  person Raid Lafi    schedule 12.07.2018
comment
я конвертирую вот так img = np.uint8(img) все тот же результат, но это не мой вопрос   -  person Raid Lafi    schedule 12.07.2018


Ответы (2)


Давайте разберемся с этим шаг за шагом:

  1. «Сортировать пиксели в каждой ячейке по их значениям яркости»

Да, вы должны преобразовать изображение в какое-либо другое цветовое пространство с компонентом яркости, например, в цветовое пространство Lab.

... На практике мы усредняем цвета пикселей в верхних 25 процентилях, чтобы уменьшить ошибку, вносимую шумом сенсора.

Это означает, что после того, как вы получите, скажем, LAB-изображение, вам нужно разбить его на каналы, что изображение L-канала, взять его гистограмму, скажем, со 100 бинами (я преувеличиваю) и взять только пиксели, которые попадают в самые белые бины (скажем, от 75 до 100). Теперь, после того, как вы нашли белые пиксели в каждой ячейке - например, запомните их!!!, вы можете создать изображение маски, которое равно 0 для всех пикселей, кроме тех, которые были выбраны как "белые".

Отфильтруйте цвета ячеек, локально подобрав плоскость в пространстве RGB.

Теперь вернитесь в пространство RBG. как вы видите, доска становится темнее по мере удаления. если вы изобразите цвета RGB пикселей доски в виде трехмерных точек в трехмерном мире с осями R, G и B, вы получите разброс, который является приблизительно плоскостью (поскольку все эти цвета доски имеют серый оттенок) . Теперь возьмите точки, которые вы отметили как «белую доску» на предыдущем шаге, и подгоните к ним плоскость. Как посадить самолет? вы можете использовать наименьшие квадраты, такие как this, но от того, как они Я написал это в статье, я думаю, что они имели в виду RANSAC.

person Shmuel Fine    schedule 13.08.2018

temp = cel[i,j]/luminance[c]
if temp > thresh : ##Let thresh be 0.7
   cel[i,j] = 255 

Cels с большим значением яркости преобразуется в белый, другие cels остаются как есть. Вывод изображения с однородным фоном

person bindu    schedule 13.08.2018