Пиксельное перекрытие с полигоном: эффективный алгоритм (тип линии сканирования)

Постановка задачи: у меня есть прямоугольное и равномерно распределенное изображение пикселей с координатами вершины (i,j), (i+1,j), (i, j+1), (i+1, j+1) [i=0,..., м-1; j=0,...,n-1] и многоугольник P с координатами вершины (x_1,y_1), ..., (x_n, y_n). Теперь я хочу эффективно рассчитать процент каждого пикселя, перекрывающегося с P. P может быть невыпуклым или даже самопересечением.

По сути, это "мягкое" обобщение алгоритмов растеризации линий сканирования, которые эффективно проверяют, лежат ли центры пикселей внутри / снаружи многоугольника.

Я могу думать о следующих подходах:

(1) Повторите выборку изображения (например, в 10 × 10 раз), посчитайте, сколько субпиксельных центров находится внутри многоугольника, и разделите на 100. Проблемы: экономия времени, эффективность памяти, точность.

(2) Используйте алгоритм линии сканирования на немного большей и (0,5,0,5) переведенной сетке, чтобы вычислить пиксели, которые полностью лежат внутри / снаружи, создать список "пограничных" пикселей, пройти против часовой стрелки вдоль краев и вычислить области пересечения со всеми пикселями вдоль пути. Проблемы: требует тонкого кодирования, легко вносить ошибки.

Мой вопрос: кто-нибудь уже сталкивался с этой проблемой, и знаете ли вы третий, превосходящий подход? А если нет, то сделали ли вы лучший опыт с (1) или с (2)? Я предполагаю, что эта проблема может возникнуть в контексте сглаживания?

2 ответа

Решение

Выполнение точного геометрического анализа может быть не слишком сложным.

Сначала разберитесь с пикселями, которые частично покрыты многоугольником: вы можете использовать метод трассировки лучей, чтобы быстро найти все пиксели, которые пересекаются с краями многоугольника. Затем вы можете использовать алгоритм Коэна-Сазерленда, чтобы эффективно найти точки пересечения между краем и пикселем, и, следовательно, вы можете вычислить зону покрытия для этого пикселя.

Обратите внимание, что вы можете избежать одной из двух операций отсечения, связанных с Коэном-Сазерлендом, поскольку смежные пиксели будут иметь общую точку пересечения сегмента. Например, если у вас есть два смежных пикселя, A а также B которые пересекаются с сегментом p->q в точках a1, a2, b1 а также b2, затем a2 а также b1 будет таким же. Проходящий сегмент a2->q в рутине при стрижке B следует избегать повторения работы.

Вы должны будете обработать пиксели, которые содержат вершины многоугольника, особенно, но опять же это не должно быть слишком хитрым: Коэн-Сазерленд также поможет здесь.

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

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

редактировать: На самом деле, теперь, когда я думаю об этом больше, вы можете полностью пропустить шаг Коэн-Сазерленд. Алгоритм в связанной статье может быть легко расширен, чтобы вернуть точки пересечения между сегментом и сеткой пикселей. Сегмент оставит данный пиксель в min( tMaxX, tMaxY ), Отслеживайте последнюю точку выхода для повторного использования в качестве точки входа для следующего пикселя.

Я бы сделал

1a) Upsample, когда пиксель частично перекрывается:

но не все изображение, только текущий пиксель, который нужно проверить, или все пиксели в текущей строке развертки, если это поможет.

Чем нет аргумента памяти.

скорость? до 16x16 я не думаю, что скорость это проблема.

Другие вопросы по тегам