Нарисуйте круг с определенным количеством пикселей - PullRequest
5 голосов
/ 21 апреля 2011

Я работаю над проектом, который требует от меня точного контроля количества пикселей, которые используются для рисования (приблизительно) круговых стимулов, и хотя алгоритмы Брезенхэма хороши, они не рисуют круги произвольной области (длямои знания).Я пробовал сценарии, которые прерывают алгоритм Брезенхэма, когда намечается желаемая область, но результаты решительно достигнуты.Кто-нибудь знает способ построить «лучший» круг (несколько субъективно, я знаю), используя заданное количество пикселей?Большое спасибо!

Ответы [ 6 ]

5 голосов
/ 21 апреля 2011

Грубый способ сделать это, например:

Радиус круга площадью 1000 кв. Пикс. Равен sqrt (1000 / pi) = 17,8 ... Этот круг должен вписаться в матрицу 35x35. Если вы сделаете «индексы» для той матрицы, где центральный пиксель равен (0,0), вы можете легко проверить, попадает ли пиксель в окружность или нет, подставив в уравнение окружности x ^ 2 + y ^ 2 = r ^ 2. Или вы можете использовать альтернативное уравнение для круга с центром в (a, b). Если он оценивается как ИСТИНА, то, если нет, он находится вне круга.

В качестве псевдокода / примера в Python я бы сделал оптимизированную версию:

import numpy, math

target_area = 1000.0

r = (target_area / math.pi) ** 0.5
m = numpy.zeros((2*r+2,2*r+2))

a, b = r, r

for row in range(0, m.shape[0]):
    for col in range(0, m.shape[1]):
        if (col-a)**2 + (row-b)**2 <= r**2:
            m[row,col] = 1

numpy.sum(m)
#>>> 999

Вот результат, когда целевая область составляет 100 000 пикселей (фактический сгенерированный круг равен 99988.0): circle

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

1 голос
/ 22 апреля 2011

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

1 голос
/ 21 апреля 2011

Площадь круга A = Pi * r 2 . Вы начинаете с области и (очевидно) хотите радиус, поэтому мы делим обе стороны на Pi, чтобы получить: r 2 = A / pi. Взяв квадратный корень с обеих сторон, мы получим: r=sqrt(A/pi). Когда у вас есть радиус, рисование с использованием большинства обычных алгоритмов должно быть простым.

0 голосов
/ 22 апреля 2011

Давайте на секунду забудем о пикселях и проработаем основную математику / геометрию.

Все мы знаем, что

Площадь круга = Pi * Радиус ^ 2

, что означает

Площадь круга = Pi * (Диаметр / 2) ^ 2

Все мы знаем, что

Площадь квадрата, окружающего круг (т.е. каждая сторона квадрата касается окружности) = Диаметр * Диаметр

Таким образом

Отношение площади круга к площади квадрата = площадь круга / площадь квадрата = (Pi * (диаметр / 2) ^ 2) / (диаметр * диаметр) = Pi / 4

Теперь давайтепредположим, что у нас есть круг и квадрат с количеством пикселей, достаточно большим, чтобы нам не приходилось беспокоиться о проблемных краях вокруг границы круга.На самом деле, давайте на секунду предположим, что у нас очень большой диаметр (может быть, 10000 или даже бесконечный)С этим предположением справедливо следующее:

Количество пикселей в круге = (Количество пикселей в квадрате) * (Отношение площади круга к квадратной площади)

Другими словами, для достаточно большого количества пикселей отношение областей идеально нарисованного круга к идеально нарисованному квадрату будет приблизительно соответствовать отношению числа пикселей в пикселизованном круге к количеству пикселей во вмещающем пикселе.квадрат.

Теперь в пикселированном квадрате количество пикселей в этом квадрате - это количество пикселей, умноженное на количество пикселей в высоту.Или, другими словами, это квадрат квадрата (в пикселях).Назовем диаметр пикселя квадрата d .Таким образом, заменив вышеприведенными формулами, мы имеем:

Количество пикселей в круге = (d * d) * (Pi / 4)

Так что теперь давайте решим для d

d = Sqrt (4 * (количество пикселей в круге) / Pi)

Ну, мы уже говорили ранее, что d был диаметр квадрата.Ну, это также бывает диаметр круга.Поэтому, если вы хотите нарисовать круг с определенным количеством пикселей, вы рисуете круг диаметром:

Диаметр круга = Sqrt (4 * (Требуемое количество пикселей вПлощадь круга) / Пи)

Теперь, очевидно, вы должны сделать некоторые выборы в отношении округления и т. Д. (Не существует такого понятия, как дробный пиксель), но вы получите точку.Кроме того, эта формула является более точной, так как желаемое количество пикселей для области круга увеличивается.Для небольших количеств пикселей ошибка округления может не дать правильного количества пикселей.

0 голосов
/ 21 апреля 2011

Предположительно у вас есть 2000 пикселей, которые должны составить ваш полный круг.Под полным я подразумеваю, что в пикселях не должно быть разрыва, и они должны быть связаны друг с другом.Поскольку 2Pi * R = длина окружности, длина хода диаметра круга, это общее количество пикселей, которое у вас есть.Теперь просто напишите R = 2000/2 * Pi, и это даст вам радиус.Теперь вы должны нарисовать круг, состоящий из 2000 пикселей.Я надеюсь, что это то, что вы хотели.

0 голосов
/ 21 апреля 2011

Моя первая мысль - использовать алгоритм с точностью до субпикселя. Подумайте, что происходит, если ваш центр имеет иррациональные координаты и вы постепенно увеличиваете радиус. Это будет заполнять кажущиеся случайными пиксели по периметру, когда они будут включены в круг. Вы хотите избежать симметрии, которая приводит к тому, что 4 квадранта круга добавляют пиксели одновременно, чтобы вы были ближе к добавлению отдельных пикселей. Как что-то подобное может быть реализовано, я понятия не имею.

Мне пришлось один раз решить один экземпляр 3d-версии. Мне нужно, чтобы набор точек решетки внутри сферы был меньше или равен 255. IIRC, если r * r = 15, то внутри сферы 240 точек. Я не был заинтересован в том, чтобы получить 255 точно.

...