Текущая ситуация : я пытаюсь извлечь сегменты из изображения.Благодаря findContours()
методу openCV, у меня теперь есть список из 8 связанных точек для каждого контура.Однако эти списки нельзя использовать напрямую, поскольку они содержат много дубликатов.
Проблема : Учитывая список из 8 связанных точек, который может содержать дубликаты, извлекитесегменты от него.
Возможные решения:
- Сначала я использовал метод openCV
approxPolyDP()
.Однако результаты довольно плохие ... Вот увеличенные контуры:
Вот результат approxPolyDP()
: (9 сегментов! Некоторые перекрываются)
но то, что я хочу, больше похоже на:
Это плохо, потому что approxPolyDP()
может преобразовать то, что "выглядит"как несколько сегментов "в" несколько сегментов ".Тем не менее, у меня есть список точек, которые имеют тенденцию повторяться несколько раз над собой.
Например, если мои точки:
0 1 2 3 4 5 6 7 8
9
Тогда список точек будет0 1 2 3 4 5 6 7 8 7 6 5 4 3 2 1 9
... И если количество точек становится большим (> 100), то сегменты, извлеченные с помощью approxPolyDP()
, к сожалению, не являются дубликатами (то есть: они перекрывают друг друга, но не являются строго равными, поэтому я не могу простоскажем "удалить дубликаты", в отличие от пикселей, например)
- Возможно, у меня есть решение, но оно довольно длинное (хотя и интересное).Прежде всего, для всего 8-связного списка, я создаю разреженную матрицу (для эффективности) и устанавливаю значения матрицы равными 1, если пиксель принадлежит списку.Затем я создаю график , с узлами, соответствующими пикселям, и ребрами между соседними пикселями.Это также означает, что я добавляю все недостающие края между пикселями (сложность мала, возможна из-за разреженной матрицы).Затем я удаляю все возможные "квадраты" (4 соседних узла), и это возможно, потому что я уже работаю над довольно тонкими контурами.Затем я могу запустить алгоритм минимального связующего дерева 1053 *.И, наконец, я могу аппроксимировать каждую ветвь дерева с помощью openCV
approxPolyDP()
сегментация http://img197.imageshack.us/img197/4488/segmentation.png
Вот фантастические фотографии (спасибо Paint!) Оригиналасписок и связанный граф.Затем, когда я добавляю ребра между соседями.И, наконец, когда я удаляю ребра и создаю минимальное остовное дерево (здесь бесполезно)
Подводя итог: у меня есть утомительный метод, который я еще не реализовал, так как кажется подверженным ошибкам.Тем не менее, я спрашиваю вас , людей из StackOverflow: существуют ли другие существующие методы, возможно, с хорошими реализациями?
Редактировать: Чтобы уточнить, если у меня есть дерево, я могу извлечь«ветви» (ветви начинаются на листьях или узлах, связанных с 3 или более другими узлами). Затем, алгоритм в approxPolyDP()
в openCV - это алгоритм Рамера – Дугласа – Пекера , и вот википедия:он делает:
С этим рисунком легко понять, почему он терпит неудачу, когда точки могут быть дубликатами друг друга
Другое редактирование:В моем методе есть кое-что, что может быть интересно отметить.Когда вы рассматриваете точки, расположенные в сетке (например, пиксели), то, как правило, алгоритм минимального связующего дерева бесполезен, потому что существует множество возможных минимальных деревьев
X-X-X-X
|
X-X-X-X
фундаментально очень отличается от
X-X-X-X
| | | |
X X X X
но оба являются минимальными связующими деревьями
Однако, в моем случае, мои узлы редко образуют кластеры, потому что они должны быть контурами, и уже есть алгоритм прореживания, который выполняется заранее в findContours()
.
Ответ на комментарий Томалака:
Если алгоритм DP возвращает 4 сегмента (сегмент от точки 2
до центра, находящегося там дважды), я был бы счастлив! Конечно, с хорошими параметрами я могу добраться до состояния, когда «случайно» у меня есть идентичные сегменты, и я могу удалить дубликаты. Однако, очевидно, алгоритм не предназначен для этого.
Вот реальный пример со слишком большим количеством сегментов: