Преобразование декартова изображения в полярное, отличия внешнего вида

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

Целевое изображение

Цель

Мое преобразование

  radius = sqrt(width**2 + height**2)
  nheight = int(ceil(radius)/2)
  nwidth = int(ceil(radius/2))
 for y in range(0, height):
   for x in range(0, width):
     t =  int(atan(y/x))
     r = int(sqrt(x**2+y**2)/2)
     color = getColor(getPixel(pic, x, y))
     setColor( getPixel(radial,r,t), color)

person Bob R    schedule 22.11.2014    source источник


Ответы (1)


Есть несколько отличий/ошибок:

  1. Они используют центр изображения в качестве источника
  2. Они масштабируют ось соответствующим образом. В вашем примере вы строите свой угол (от 0 до, в вашем случае, пи) вместо того, чтобы использовать полную высоту изображения.
  3. Вы используете неправильную функцию atan (atan2 работает намного лучше в этой ситуации :))
  4. Не удивительно важно, но вы слишком много округляете, что немного снижает точность и может замедлить работу.

Это код, объединяющий предложенные мной улучшения. Это не очень эффективно, но, надеюсь, должно сработать :)

  maxradius = sqrt(width**2 + height**2)/2
  rscale = width / maxradius
  tscale = height / (2*math.pi)
  for y in range(0, height):
   dy = y - height/2
   for x in range(0, width):
     dx = x - width/2
     t =  atan2(dy,dx)%(2*math.pi)
     r = sqrt(dx**2+dy**2)
     color = getColor(getPixel(pic, x, y))
     setColor( getPixel(radial,int(r*rscale),int(t*tscale)), color)

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

  1. Мы используем dx = x - width / 2 как меру расстояния от центра, и аналогично с dy. Затем мы используем их вместо x, y на протяжении всего вычисления.
  2. У нас будет r, удовлетворяющий 0 <= r <= sqrt( (width/2)^2 +(height/2)^2 ), и наш t, в конечном итоге удовлетворяющий 0 < t <= 2 pi, поэтому я создаю соответствующие коэффициенты масштабирования, чтобы расположить r и t по осям x и y соответственно.
  3. Обычный atan может различать только на основе градиентов и вычислительно нестабилен вблизи вертикальных линий... Вместо этого atan2 (см. http://en.wikipedia.org/wiki/Atan2) решает обе проблемы и принимает (y,x) пар для определения угла. atan2 возвращает угол -pi < t <= pi, поэтому мы можем найти остаток по модулю 2 * math.pi, чтобы получить его в диапазоне 0 < t <= 2pi, готовым к масштабированию.
  4. Я округляю только в конце, когда устанавливаются новые пиксели.

Любые вопросы, просто спросите!

person David E    schedule 22.11.2014
comment
Без проблем, рад помочь! - person David E; 22.11.2014
comment
Рад, что это сработало. Кстати, я только что понял, что строка, в которой я создал r в цикле, имеет неправильное деление на 2. Сейчас я это исправил! - person David E; 22.11.2014
comment
:D Я это заметил. Еще одна вещь, которую я заметил, это то, что, кажется, отсутствуют пиксели. Это из-за округления или они применили второй процесс для их заполнения? - person Bob R; 22.11.2014
comment
Да, это будет потому, что карта не 1-к-1... Некоторые области нового изображения взяты из гораздо меньших областей исходного изображения (так что это будет особенно верно в верхней части нового изображения, где радиус мал). К сожалению, вам придется заполнить их после прохода. Возможно, более простым решением является вычисление обратной карты... т.е. цикл по t и r и вычисление x = round(r cos(t)) + width/2 , y = round(r sin(t)) + height /2, и если эти x и y лежат на старом изображении, мы копируем значение в соответствующую позицию r* rscale, t* tscale на новом изображении... Если это имеет смысл? - person David E; 22.11.2014
comment
Да, это абсолютно имеет смысл. - person Bob R; 26.11.2014