Обнаружение горизонтальной линии с 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, так как этот метод ищет "глобальные" линии, не обязательно сегменты линии. Недавно я реализовал приложение, которое определило "параллелограммы" -по существу квадраты, которые могут быть повернуты и перспектива вперед-укорочены из-за угла обзора. Вы могли бы подумать о чем-то подобном. Мой трубопровод был:
- конвертировать из RGB в оттенки серого (cvCvtColor)
- гладкая (cvSmooth)
- порог (cvThreshold)
- обнаружение ребер (cvCanny)
- найти контуры (cvFindContours)
- приблизительные контуры с линейными характеристиками (cvApproxPoly)
в вашем приложении результирующий список контуров, вероятно, будет большим (в зависимости от "агрессивности" сглаживания и улучшения функции детектора Canny edge. Этот список можно обрезать по различным параметрам: количество точек, возвращаемых из контурного искателя, площадь контура (cvContourArea), etc. По моему опыту, я ожидал бы, что" допустимые " строки в вашем приложении будут иметь четко определенные свойства area и vertex count. Кроме того, можно отфильтровать Контуры на основе расстояния между конечными точками, угла, определенного линией, соединяющей конечные точки, и т. д.
в зависимости от того, сколько времени процессора у вас есть, вы всегда можете связать алгоритм Хоу с алгоритмом, подобным приведенному выше, чтобы надежно идентифицировать горизонтальные и вертикальные линии.
Не преобразовывайте RGB в оттенки серого. Иногда разные цвета в RGB могут быть объединены в одно и то же значение оттенков серого, поэтому он может пропустить некоторые контуры. Вы должны проанализировать каждый из каналов RGB отдельно.