Алгоритм для вычисления множества ячеек, ограниченных дискретным контуром

#algorithm #opencv #computational-geometry #discrete-mathematics #cgal

#алгоритм #opencv #вычислительная геометрия #дискретная математика #cgal

Вопрос:

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

  • набор 2D точек (x1,y1);(x2,y2);(x3,y3);...
  • или 4-связный код Фримена с начальной точкой: (x1,y1) 00001112...

Я знаю, как переключаться с одного на другое из этих представлений. Это будут входные данные.

Я хочу получить набор координат сетки, ограниченных контуром. Рассмотрим этот пример, где красные координаты — это контур, а серая — начальная точка:

Пример контура

Если серая координата, скажем, равна (0,0), то мне нужен вектор, содержащий: (1,1),(2,1),(3,1),(3,2)

Порядок не важен, и выходной вектор также может содержать сам контур.

Язык выбора — C , но я открыт для любого существующего кода, алгоритма, библиотеки, указателя, чего угодно…

Я подумал, что, возможно, у CGAL будет что-то подобное, но я не знаком с этим и не смог найти свой путь в руководстве, поэтому я даже не уверен. Я также посмотрел в сторону Opencv, но я думаю, что он не предоставляет этот алгоритм (но я могу ошибаться?).

Я думал о том, чтобы найти ограничивающий прямоугольник, затем проверить каждую из точек в прямоугольнике, чтобы увидеть, находятся ли они внутри / снаружи, но это кажется неоптимальным. Есть идеи?

Комментарии:

1. Все, что вам нужно сделать, это найти единственную точку внутри границы, а затем заполнить заливкой. Это простой рекурсивный алгоритм.

2. Вы должны проверить, действительно ли «поиск ограничивающего прямоугольника» является медленным. Если ваш контур не очень большой, вероятно, быстрее всего преобразовать счетчик в 2D-массив, а затем заполнить заливкой, как предлагает j_random_hacker. В противном случае вам будет сложно определить, какая позиция сетки принадлежит контуру.

3. @j_random_hacker Спасибо, я действительно не думал об этом, но это кажется хорошей идеей. Возможно, это не рекурсивная реализация, хотя, боюсь, она может быть не самой быстрой. Я проведу расследование.

4. @DrV Проблема с ограничивающим прямоугольником заключается в том, что если форма глубоко вогнута (например, подумайте о внешней форме буквы «U»), то может потребоваться некоторое время, чтобы найти точку, которая находится внутри контура.

5. На самом деле, найти «внутри» не так просто, поскольку и «снаружи», и «внутри» находятся рядом с точками контура. Используя код Freeman, вы можете рассчитать количество поворотов влево и поворотов вправо, которые вы делаете во время цикла. Если вы делаете больше поворотов налево, ваш счетчик идет против часовой стрелки, а «внутри» находится слева от вас, если вы идете по счетчику.

Ответ №1:

Одним из способов решения этой проблемы является drawContours, и у вас есть точки contours.

  1. Создайте пустой мат и нарисуйте контур толщиной = 1 (граница).
  2. Создайте еще один пустой мат и нарисуйте контур с толщиной = CV_FILLED(вся область, включая границу).
  3. Теперь bitwise_and между двумя выше (вы получили заполненную область, исключая границу).
  4. Наконец, проверьте ненулевой пиксель.

Комментарии:

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