Обнаружение горизонтальной линии с OpenCV

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

Я пытался OpenCV для работы. Реализация преобразования Hough в OpenCV казалась полезной для работы, но я не мог найти никакой комбинации параметров, которая позволила бы ей чисто найти вертикальные и горизонтальные линии. Я пытался с и без обнаружения края. Не повезло. Если кто-то сделал что-то подобное, мне интересно знать, как это сделать.

см. здесь изображение моего до и после экспериментов с HoughP в OpenCV. Это лучшее, что я мог сделать,http://dl.dropbox.com/u/3787481/Untitled%201.png

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

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

спасибо! Патрик.

4 ответов


вы видели пример кода HoughLinesP документация по функциям?

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

обновление:

Как я вижу, вам нужно найти не линии, а горизонтальные вертикальные края на странице. Для этой задачи вам нужно объединить несколько этапов обработки, чтобы получить хорошее результаты.

для вашего изображения я могу получить хорошие результаты, объединив Canny edge detection с HoughLinesP. Вот мой код (я использовал Python, но я думаю, что вы видите идею):

img = cv2.imread("C:/temp/1.png")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 80, 120)
lines = cv2.HoughLinesP(edges, 1, math.pi/2, 2, None, 30, 1);
for line in lines[0]:
    pt1 = (line[0],line[1])
    pt2 = (line[2],line[3])
    cv2.line(img, pt1, pt2, (0,0,255), 3)
cv2.imwrite("C:/temp/2.png", img)

результат выглядит так:


Если вы просто хотите "линии", а не" сегменты линии", я бы избегал использования Canny, Hough, FindContours или любой другой такой функции, если вы хотите больше скорости в своем коде. Если ваши изображения не вращаются и то, что вы хотите найти, всегда вертикально или горизонтально, я бы просто использовал cv::Sobel (один для вертикали, а другой для горизонтали) и создавал массивы накопления для столбцов и строк. Затем вы можете искать максимумы в таких накоплениях или профилях, например, установив порог, и вы будете знать строку или столбец, в котором есть вертикальные или горизонтальные линии ребра.


вы можете оставить обнаружение линии Hough, так как этот метод ищет "глобальные" линии, не обязательно сегменты линии. Недавно я реализовал приложение, которое определило "параллелограммы" -по существу квадраты, которые могут быть повернуты и перспектива вперед-укорочены из-за угла обзора. Вы могли бы подумать о чем-то подобном. Мой трубопровод был:

  1. конвертировать из RGB в оттенки серого (cvCvtColor)
  2. гладкая (cvSmooth)
  3. порог (cvThreshold)
  4. обнаружение ребер (cvCanny)
  5. найти контуры (cvFindContours)
  6. приблизительные контуры с линейными характеристиками (cvApproxPoly)

в вашем приложении результирующий список контуров, вероятно, будет большим (в зависимости от "агрессивности" сглаживания и улучшения функции детектора Canny edge. Этот список можно обрезать по различным параметрам: количество точек, возвращаемых из контурного искателя, площадь контура (cvContourArea), etc. По моему опыту, я ожидал бы, что" допустимые " строки в вашем приложении будут иметь четко определенные свойства area и vertex count. Кроме того, можно отфильтровать Контуры на основе расстояния между конечными точками, угла, определенного линией, соединяющей конечные точки, и т. д.

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


Не преобразовывайте RGB в оттенки серого. Иногда разные цвета в RGB могут быть объединены в одно и то же значение оттенков серого, поэтому он может пропустить некоторые контуры. Вы должны проанализировать каждый из каналов RGB отдельно.