Поиск единого пути для заполнения всех затененных областей изображения в C#

У меня есть черно-белое (бинарное) изображение. Он содержит набор черных пятен, окруженных белыми. Я пытаюсь написать программу на С#, которая найдет единственный путь, пересекающий всю затененную область, оставляя при этом как можно больше белой области. Это очень похоже на поиск траектории головки инструмента для 3D-принтера для любого заданного слоя; ему нужно заполнить твердые части, а переходить в пустое пространство только тогда, когда ему нужно добраться до другого отдельного шарика.

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

пример больших двоичных объектов

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

Моя программа написана на C#, и я уже использую AForge для обработки изображений до этого момента, так что у меня уже есть это.

До сих пор самое близкое, что я получил, было с алгоритмом, похожим на заливку. Он начнется с угла и найдет ближайший пиксель (сначала по горизонтали, затем по вертикали), чтобы продолжить путь. Но пути не всегда вели повсюду, и пересечение обычно создавало длинный и в значительной степени посторонний путь. Я также пытался отслеживать края и двигаться внутрь, но это все еще не очень хорошо работало, когда у капли был непрямой путь. Поиск тоже ничего не дал; Я пытался искать что-то, связанное с алгоритмами 3D-печати, заливкой и т. д., но ничего не нашел.

Итак, как мне решить эту проблему?


person Wasabi Fan    schedule 01.09.2014    source источник


Ответы (2)


  1. заполнение капель

    • they are just filled polygon
    • преобразовать их в набор замкнутых выпуклых многоугольников
    • или триангулировать его
    • затем визуализируйте как заполнение замкнутого многоугольника + растеризация треугольных/выпуклых многоугольников
    • стенд использует ту же растеризацию
    • так что вы получите набор горизонтальных/или вертикальных линий (зависит от того, как вы его кодируете)
    • поэтому просто соедините их вместе в одну полилинию введите здесь описание изображения
    • есть и другие способы заполнить поля, но этот самый простой и подвержен ошибкам.
  2. движения между каплями

    • this is indeed TSP which is NP complete (see mcdowella answer)
    • обрабатывать все замкнутые полигоны как отдельные капли
    • использовать эвристику (присоединять капли в непосредственной близости)
    • ограничить длину движения как критерий решения
person Spektre    schedule 01.09.2014
comment
Я так понимаю, ваше предложение состоит в том, чтобы разбить его на треугольники и решать каждый по отдельности? Это означало бы, что путь будет возвращаться назад и в противном случае отклоняться от прямой линии на каждом участке, что сделает его намного длиннее, чем нужно. Любые идеи о том, как присоединиться к разделенным путям? - person Wasabi Fan; 02.09.2014
comment
@WasabiFan разбивается на выпуклые многоугольники, а не на треугольники (рендеринг выпуклого многоугольника аналогичен рендерингу треугольника, вы просто заполняете граничные буферы более чем 3 полилиниями перед рендерингом). это только первый шаг, вы можете, например, удерживать все горизонтальные линии в каком-то списке и попытаться присоединиться к некоторым позже... - person Spektre; 02.09.2014
comment
@WasabiFan, кстати, вам нужно выполнить какое-то особое условие? например, выращивание на предыдущем слое или рендеринг рядом с уже визуализированными линиями, если это возможно (например, для некоторых процессов 3D-принтера), или предпочтение определенной формы/шаблона заполнения (это обычно для гравировальных машин), или вам нужно просто меньшее расстояние (векторные дисплеи) - person Spektre; 02.09.2014
comment
Моя установка очень похожа на что-то вроде алгоритма гравировального станка. Я бы предпочел что-то вроде того, что вы проиллюстрировали на своей диаграмме (систематический рисунок горизонтальных или вертикальных линий). - person Wasabi Fan; 06.09.2014
comment
@WasabiFan это легко, просто начните с растеризации треугольника / выпуклого многоугольника (вы можете начать с заполнения пикселей на экране), когда вы заработаете правильно, тогда вы измените его на вывод геометрии вместо горизонтальных линий ... это довольно прямолинейно . этот вид заливки создает специальное наложение на гравируемой поверхности, вы можете изменить его, изменив расстояние между линиями по отношению к ширине инструмента +/- некоторое перекрытие/зазор. Я экспериментировал со спиральным заполнением, которое было необходимо для некоторых эффектов алиасинга при гравировке, но это чрезвычайно сложно... - person Spektre; 06.09.2014

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

Это наводит меня на мысль, что вы вычисляете ближайшее расстояние между всеми парами черных областей, а затем используете какое-то приближенное решение задачи коммивояжера на этой матрице расстояний. Поиск находит алгоритм ближайшего расстояния, описанный на http://cgm.cs.mcgill.ca/~orm/mind2p.html. На ум приходят алгоритмы аппроксимации TSP, основанные на http://en.wikipedia.org/wiki/Minimum_spanning_tree и в битонических турах, например в http://www.cs.helsinki.fi/u/jwkangas/daaa2013/sol-II.pdf.

person mcdowella    schedule 01.09.2014
comment
Как насчет заполнения самих черных областей, если мы забудем о путешествии между ними? Я имею в виду, как мне лучше всего найти путь, чтобы заполнить любое заданное черное пятно? - person Wasabi Fan; 01.09.2014
comment
Ответ Spektre кажется вполне разумным для заполнения черных областей. Вы могли бы добиться большего успеха, если бы имели гораздо более четкое представление о стоимости заполнения небольшой области или рисования растровой линии, и если бы вы были готовы решить TSP, чтобы выяснить, как лучше всего соединить соседние выпуклые компоненты или треугольники. но это выглядит хорошо вписывается в то, что вы сказали до сих пор. - person mcdowella; 01.09.2014