2015-10-05 6 views
5

У меня есть образец изображения, как этотКак извлечь белую область в изображении

enter image description here

Я искал способ затемнить шум от изображения, так что я в конечном итоге с изображением который имеет черный текст на белом фоне, чтобы я мог отправить его в tesseract.

Я попытался морфинг с

kernel = np.ones((4,4),np.uint8) 
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel) 
cv2.imshow("opening", opening) 

, но это не похоже на работу.

Я также попытался найти контуры

img = cv2.cvtColor(rotated, cv2.COLOR_BGR2GRAY) 
(cnts, _) = cv2.findContours(img, cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) 
cnts = sorted(cnts, key = cv2.contourArea, reverse = True)[:1] 
for c in cnts: 
    x,y,w,h = cv2.boundingRect(c) 
    roi=rotated[y:y+h,x:x+w].copy() 
    cv2.imwrite("roi.png", roi) 

С кода выше, я получаю следующие контуры:

enter image description here

, который ведет к этому изображению, когда неожиданно возникли:

enter image description here

, который все еще недостаточно хорош. Я хочу черный текст на белом фоне, так что я могу отправить его в Tesseract OCR и иметь хороший шанс успеха.

Есть ли что-нибудь еще, что я могу попробовать?

Update

Вот дополнительный Сходный образ. Это один немного легче, потому что он имеет гладкий прямоугольник в нем

enter image description here

+1

избирателя, который сказал вопрос слишком-широко. Пожалуйста, дайте мне знать, как сузить его дальше. Я не думаю, что вопрос широк. – Anthony

+0

Вам нужно сделать некоторые адаптивные пороговые значения, а также открыть и закрыть операции. http://docs.opencv.org/doc/tutorials/imgproc/opening_closing_hats/opening_closing_hats.html Вы также можете выполнять обычную эрозию или расширение (что является основным, что делают открытые и закрытые операции). –

+0

Это входное изображение? Или результат какого-то порога? – ZdaR

ответ

3

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

import numpy as np 
import cv2 

image_src = cv2.imread("input.png") 
gray = cv2.cvtColor(image_src, cv2.COLOR_BGR2GRAY) 
ret, gray = cv2.threshold(gray, 250,255,0) 

image, contours, hierarchy = cv2.findContours(gray, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) 
largest_area = sorted(contours, key=cv2.contourArea)[-1] 
mask = np.zeros(image_src.shape, np.uint8) 
cv2.drawContours(mask, [largest_area], 0, (255,255,255,255), -1) 
dst = cv2.bitwise_and(image_src, mask) 
mask = 255 - mask 
roi = cv2.add(dst, mask) 

roi_gray = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY) 
ret, gray = cv2.threshold(roi_gray, 250,255,0) 
image, contours, hierarchy = cv2.findContours(gray, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) 

max_x = 0 
max_y = 0 
min_x = image_src.shape[1] 
min_y = image_src.shape[0] 

for c in contours: 
    if 150 < cv2.contourArea(c) < 100000: 
     x, y, w, h = cv2.boundingRect(c) 
     min_x = min(x, min_x) 
     min_y = min(y, min_y) 
     max_x = max(x+w, max_x) 
     max_y = max(y+h, max_y) 

roi = roi[min_y:max_y, min_x:max_x] 
cv2.imwrite("roi.png", roi) 

Давать вам следующий тип вывода изображения:

enter image description here

И ...

enter image description here

код работает на первом поиске наибольшую площадь контура. Из этого создается маска, которая используется для первого выбора только области внутри, то есть текста. Затем обратная сторона маски добавляется к изображению для преобразования области вне маски в белый.

Последние контуры найдены снова для этого нового изображения. Любые области контура за пределами подходящего диапазона размеров отбрасываются (это используется для игнорирования любых небольших зон шума), и для каждого из них определяется ограничивающий прямоугольник. С каждым из этих прямоугольников вычисляется ограничивающий прямоугольник для всех оставшихся контуров, и обрезка производится с использованием этих значений для получения окончательного изображения.

Обновления - Чтобы получить оставшуюся часть изображения, то есть с вышеуказанной областью удалены, может быть использовано следующее:

image_src = cv2.imread("input.png") 
gray = cv2.cvtColor(image_src, cv2.COLOR_BGR2GRAY) 
ret, gray = cv2.threshold(gray, 10, 255,0) 
image, contours, hierarchy = cv2.findContours(gray, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) 
largest_area = sorted(contours, key=cv2.contourArea)[-1] 
mask = np.zeros(image_src.shape, np.uint8) 
cv2.drawContours(mask, [largest_area], 0, (255,255,255,255), -1) 
image_remainder = cv2.bitwise_and(image_src, 255 - mask) 

cv2.imwrite("remainder.png", image_remainder) 
+0

Если возможно, не могли бы вы объяснить свой подход. Спасибо за ответ! – Anthony

+0

Нет проблем, я обновил объяснение. –

+0

спасибо. hmm Я получаю сообщение об ошибке в строке 8 'image, contours, hierarchy = cv2.findContours (gray, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) ValueError: требуется больше, чем 2 значения для распаковки – Anthony

0

Основная идея этого ответа является использование границы вокруг текста.

1) Иродагоризонтально с очень большим ядром, скажем, размером 100 пикселей или 8 раз размер одного ожидаемого характера, что-то подобное. Это должно быть сделано по-разному. Крайняя ордината даст y-расположение границ вокруг текста.

2) Процесс по вертикали так же, как получить x-расположение границ вокруг текста. Затем используйте эти места, чтобы вырезать нужное изображение.

- Одно из преимуществ этого метода - вы получите каждое предложение/слово с пометкой в ​​отдельности, что, я полагаю, полезно для OCR.

Счастливый Coding :)

Отредактировано в Марк Setchell

Вот демо 1)

enter image description here

Вот демо 2)

enter image description here

+1

Надеюсь, вы не возражаете против добавления анимации - не стесняйтесь удалять его, если вы это сделаете. –

+0

Привет @MarkSetchell, ничего себе, это действительно здорово :) Спасибо –

+0

Я попробую этот подход, поскольку он может быть более применим к другим подобным изображениям. Я обновлю свой прогресс здесь. Надеюсь, у opencv есть способ сделать горизонтальное и вертикальное размывание. – Anthony

0

я получаю это: Result

Исходный код:

if __name__ == '__main__': 
    SrcImg = cv2.imread('./Yahi9.png', cv2.CV_LOAD_IMAGE_GRAYSCALE) 
    _, BinImg = cv2.threshold(SrcImg, 80, 255, cv2.THRESH_OTSU) 

    Contours, Hierarchy = cv2.findContours(image=copy.deepcopy(SrcImg), 
             mode=cv2.cv.CV_RETR_EXTERNAL, 
             method=cv2.cv.CV_CHAIN_APPROX_NONE) 
    MaxContour, _ = getMaxContour(Contours) 
    Canvas = np.ones(SrcImg.shape, np.uint8) 
    cv2.drawContours(image=Canvas, contours=[MaxContour], contourIdx=0, color=(255), thickness=-1) 
    mask = (Canvas != 255) 
    RoiImg = copy.deepcopy(BinImg) 
    RoiImg[mask] = 255 
    RoiImg = cv2.morphologyEx(src=RoiImg, op=cv2.MORPH_CLOSE, kernel=np.ones((3,3)), iterations=4) 
    cv2.imshow('RoiImg', RoiImg) 
    cv2.waitKey(0) 

Функция:

def getMaxContour(contours): 
    MaxArea = 0 
    Location = 0 
    for idx in range(0, len(contours)): 
     Area = cv2.contourArea(contours[idx]) 
     if Area > MaxArea: 
      MaxArea = Area 
      Location = idx 
    MaxContour = np.array(contours[Location]) 
    return MaxContour, MaxArea 

Эхх, это питон код. Он работает только тогда, когда белая область является максимальным контуром.

+0

Если возможно, не могли бы вы объяснить свой подход. Спасибо за ответ! – Anthony

+0

Прости, я так устал, что заснул, как только вернулся домой. –

+0

Мартин Эванс использовал тот же способ для извлечения, это довольно хорошо. –

Смежные вопросы