Russian Qt Forum
Октябрь 01, 2024, 02:32 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: [РЕШЕНО] Как применить матрицу поворота к изображению?  (Прочитано 5081 раз)
Hrundel
Гость
« : Май 14, 2013, 20:38 »

Всем привет!

Будьте добры объясните как применять матрицу поворота к массиву.
Массив, конечно, одномерный:

rgbQuad* bmp[];

где размер width*hight;

Как считать поворот пикселей для такого массива? Желательно без потерь!

Всем спасибо!
« Последнее редактирование: Май 15, 2013, 15:16 от Hrundel » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #1 : Май 15, 2013, 08:11 »

Массив, конечно, одномерный:

rgbQuad* bmp[];
Это двумерный Улыбающийся Проще всего создать QImage (можно и не копируя исходный массив) и использовать его удобные методы для поворота
Записан
Disa
Гость
« Ответ #2 : Май 15, 2013, 09:41 »

Если вдруг нужно написать самому, то что-то в духе (воспринимайте это как псевдокод навеянный С++ и Qt, сам код не проверял):

Код
C++ (Qt)
void RotateImage(const int angle, const rgbQuad & bmp[][], const int widget, const int height, rgbQuad  * outRGB[]) {
 double rad = 180.0f * angle / 3.141592f; // или M_PI
 double rotateMat[2][2] = {cos(rad), -sin(rad),
                           sin(rad),  cos(rad)} // или QMatrix2x2, но думаю и так ясно;
 
 // вычисление размеров результирующего изображения  (координаты 3х углов)
 int x1 = height * rotateMat[1][0];  // sin(rad)
 int y1 = height * rotateMat[0][0];  // cos(rad)
 int x2 = width  * rotateMat[0][0] + height * rotateMat[1][0];
 int y2 = height * rotateMat[1][1] + width  * rotateMat[0][1];
 int x3 = width  * rotateMat[1][1];
 int y3 = width  * rotateMat[0][1];
 
 int minX = min(0, min(x1, min(x2, x3)));
 int minY = min(0, min(y1, min(y2, y3)));
 int maxX = max(0, max(x1, max(x2 ,x3)));
 int maxY = max(0, max(y1, max(y2, y3)));
 
 int newWidth  = maxX - minX;
 int newHeight = maxY - minY;
 
 // нужно чтоб размеры outRGB стали newWidth x newHeight и чем-то залить
 // что-то типа resize(outRGB, newWidth, newHeight), fill(outRGB, Qt::gray);
 
 // применяем матрицу поворота
 for(int y = 0; y < height; ++y) {
   for(int x = 0; x < height; ++x) {
      int tx = x * rotateMat[0][0] + y * rotateMat[0][1];
      int ty = x * rotateMat[1][0] + y * rotateMat[1][1];
      outRGB[tx][ty] = bmp[x][y];
  }
 }
}

Т.е. вектор итогового положение точки - это матрица поворота, умноженная слева на исходное (ну как всегда при трансформации) + предварительное вычисление нового размера. Поправьте если где ошибся!
« Последнее редактирование: Май 15, 2013, 09:44 от Disa » Записан
Hrundel
Гость
« Ответ #3 : Май 15, 2013, 09:54 »

Привет Игорь,

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

1. Определиться с центром изображения и взять его для основания координат вращения.
2. Проходя циклом по каждой точке формировать из ее координат вектор.
3. Умножать вектор на матрицу поворота

Код:
void RotateImage (int angle) 
{
       double rad = 180*angle/3.1415;
       double rmtrx[2][2] =
       {
           {qcos(rad),(-1)*qsin(rad)},
           {qsin(rad),qcos(rad}
       };

       for (int x=0; x< ...  ; x++)
       {
            newx = (altx)*rmtrx[0][0] + (alty)*rmtrx[0][1] + offsetX;
            newy = (altx)*rmtrx[1][0] + (alty)*rmtrx[1][1] + offsetY;
       }
}
Записан
Hrundel
Гость
« Ответ #4 : Май 15, 2013, 09:55 »

Disa, Спасибо!

Я тоже к такому решению пришел.   Веселый
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #5 : Май 15, 2013, 11:53 »

Код
C++ (Qt)
 // вычисление размеров результирующего изображения  (координаты 3х углов)
 int x1 = height * rotateMat[1][0];  // sin(rad)
 int y1 = height * rotateMat[0][0];  // cos(rad)
 int x2 = width  * rotateMat[0][0] + height * rotateMat[1][0];
 int y2 = height * rotateMat[1][1] + width  * rotateMat[0][1];
 int x3 = width  * rotateMat[1][1];
 int y3 = width  * rotateMat[0][1];
 
В использовании своей структуры матрицы нет ничего плохого, но метод/ф-цию transform (или оператор *) надо писать. А то получается "дамское программирование"  Улыбающийся
  
Код
C++ (Qt)
 // применяем матрицу поворота
 for(int y = 0; y < height; ++y) {
   for(int x = 0; x < height; ++x) {
      int tx = x * rotateMat[0][0] + y * rotateMat[0][1];
      int ty = x * rotateMat[1][0] + y * rotateMat[1][1];
      outRGB[tx][ty] = bmp[x][y];
  }
 }
}
Так некоторые пиксели останутся незаполненными (за счет округления int). Надо наоборот, бежать по выходному имеджу и, применяя обратную матрицу, подставлять пыксели исходного имеджа. Причем не 1 (будет рванина) а неск с осреднением

По заданию, профессор хочет, чтобы мы считали сами через матрицу.
Респект Вашему профессору, правильно, хорошо учит
Записан
Disa
Гость
« Ответ #6 : Май 15, 2013, 15:09 »

Цитировать
Так некоторые пиксели останутся незаполненными (за счет округления int)
Спасибо за поправку, с ходу это не бросается в глаза. 
Записан
Hrundel
Гость
« Ответ #7 : Май 15, 2013, 15:15 »

Всем спасибо! Удачи!
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.189 секунд. Запросов: 23.