Почему iplRotate () не дает правильных результатов? - PullRequest
4 голосов
/ 16 мая 2009

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

  1. У меня есть исходное изображение. Он имеет размер (ш, ч) , который не обязательно является квадратным.
  2. Он будет вращаться на угол тета .
  3. Я рассчитал выходной размер, необходимый для размещения изображения размером (ш, ч) , повернутым на угол тета . Этот размер (dw, dh) . Я выделил целевой буфер с таким размером.
  4. Я хочу повернуть исходное изображение на угол theta относительно центра исходного изображения (w / 2, h / 2) и иметь , что повернутое изображение быть в центре моего буфера назначения.

iplRotate () принимает 2 параметра сдвига, xShift и yShift , которые указывают расстояние, на которое изображение должно быть смещено вдоль осей x и y после поворот выполняется.

Проблема в том, что я не могу заставить iplRotate центрировать повернутое изображение на целевом изображении. Это всегда не в центре.

Мое лучшее предположение о том, что xShift и yShift должны быть , выглядит следующим образом:

  • xShift = dw - w
  • yShift = dh - h

Но это не работает, и я не уверен, что еще нужно сделать, чтобы вычислить xShift и yShift . У кого-нибудь есть предложения по использованию iplRotate для того, что я хочу?

Последний бит информации: Я попытался использовать iplGetRotateShift () для вычисления xShift и yShift, опять же, безрезультатно. Я полагаю, что это будет работать:

iplGetRotateShift(dw / 2.0, dh / 2.0, theta, &xShift, &yShift);

Но это не так.


Edit: Я переписал код, используя Intel IPP 6.0 вместо IPL, и вижу идентичные неверные результаты. Я не могу себе представить, что Intel неправильно вращалась в 2 разных библиотеках, поэтому я, должно быть, делаю что-то неправильно.


Edit: Я попробовал следующий (IPP) код, который предложил Дани ван дер Меер:

xShift = (dw - w) / 2.0;
yShift = (dh - h) / 2.0;
ippiAddRotateShift(w / 2.0, h / 2.0, angle, &xShift, &yShift);

К сожалению, до сих пор не повезло. Это тоже не работает.

Ответы [ 4 ]

5 голосов
/ 20 мая 2009

При использовании iplGetRotateShift вам необходимо указать центр поворота в исходном изображении. Это будет хорошо работать, если размер исходного и конечного изображения одинаков.

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

xShift = (dw - w) / 2.0;
yShift = (dh - h) / 2.0;

Чтобы объединить две смены, вам нужно использовать ippiAddRotateShift вместо ippiGetRotateShift.

Примечание : Эти функции относятся к библиотеке 5.3 IPP (версия, которая у меня есть). Я не уверен, что AddRotateShift доступен в IPL. Но вы упомянули в вопросе, что вы пытались сделать то же самое с использованием IPP, так что, надеюсь, вы можете использовать IPP вместо IPL.

Вы получаете что-то вроде этого

xShift = (dw - w) / 2.0;
yShift = (dh - h) / 2.0;
ippiAddRotateShift(w / 2.0, h / 2.0, angle, &xShift, &yShift);

Если вы используете эти сдвиги в вызове ippiRotate, изображение должно быть центрировано на целевом изображении.

Надеюсь, это поможет.

EDIT: Вот код, который я использовал для проверки (изменение с w на dw и h на dh и угол поворота является случайным):

//Ipp8u* dst_p; Initialized somewhere else in the code
//Ipp8u* src_p; Initialized somewhere else in the code
int w = 1032;
int h = 778;
int dw = w - 40; // -40 is just a random change
int dh = h + 200; // 200 is just a random change
int src_step = w * 3;
int dst_step = dw * 3;
IppiSize src_size = { w, h };
IppiRect src_roi  = { 0, 0, w, h };
IppiRect dst_rect = { 0, 0, dw, dh };
double xShift = ((double)dw - (double)w) / 2.0;
double yShift = ((double)dh - (double)h) / 2.0;
ippiAddRotateShift((double)w / 2, (double)h / 2, 37.0, &xShift, &yShift);
ippiRotate_8u_C3R(src_p, src_size, src_step, src_roi, 
          dst_p, dst_step, dst_rect, 37.0, xShift, yShift, IPPI_INTER_NN);
1 голос
/ 26 мая 2009

Если он все еще не работает для вас, можем ли мы подтвердить, что предположения верны? В частности, пункт 3. где вы рассчитываете dw и dh.

Математически

dw = w * | cos (тета) | + h * | sin (тета) |
дх = ч * | соз (тета) | + w * | sin (тэта) |

так что если theta = pi / 6 скажем, то если w = 100 и h = 150, то предположительно dw = 162?

Меняется ли неверная позиция, которую вы получаете, с тета? Предположительно это работает с тета = 0? А как насчет тета = пи / 2 и тета = пи / 4?

1 голос
/ 19 мая 2009

Судя по тому, что я прочитал документацию, я думаю, что вы неправильно используете iplGetRotateShift. В частности, я думаю, что вам нужно указать центр вращения на исходном изображении, а не на конечном изображении, таким образом:

iplGetRotateShift( w / 2.0,  h / 2.0, angle, &xShift, &yShift );
1 голос
/ 19 мая 2009

Я никогда не использовал (или не слышал о) IPL раньше, поэтому я просто догадываюсь, что делает API. Но если iplRotate вращается примерно на (0, 0) и если iplGetRotateShift работает аналогично, почему бы не попробовать повернуть остальные 3 угла вашего исходного «ящика» (игнорируя (0, 0), поскольку он остается на месте): (w, 0), ( 0, h) и (w, h).

Ваш результат будет новым окном с некоторыми отрицательными значениями. Вы хотите «сдвинуть назад», чтобы все ваши отрицательные значения стали равны нулю, если вы поймете, что я имею в виду.

...