Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Алгоритмы интерполяции, помогите кто чем может (рус англ) 
:(
    Опции темы
Deniskkk
Дата 27.2.2007, 11:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 27.2.2007

Репутация: нет
Всего: нет



Кто может помочь информацией?
Требуется: 
1 картинку в BMP крутить на угол Alpha относительно центра
2 изменять её размер в N (от 0 до 10 поримерно) раз
Собираюсь програмировать это на Jave .
На скока понимаю без интерполяции не обойтись.
PM MAIL   Вверх
SoWa
Дата 27.2.2007, 21:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Харекришна
****


Профиль
Группа: Комодератор
Сообщений: 2422
Регистрация: 18.10.2004

Репутация: 6
Всего: 74



Чтоооо smile 
А накой тут интерполяция?!
Интерполяция- это получение функции по заданным значениям нескольких точек на отрезке.(Примитивное объяснение).
И зачем она в повороте/уменьшении картинки?!


--------------------
Всем добра smile
PM MAIL ICQ   Вверх
maxim1000
Дата 27.2.2007, 21:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: 33
Всего: 110



Цитата(SoWa @  27.2.2007,  20:22 Найти цитируемый пост)
А накой тут интерполяция?!

когда картинка поворачивается, пикселы повёрнутой не всегда (а точнее, почти никогда) совпадают с пикселами исходной
т.е. для того, чтобы узнать цвет, например, пиксела (13,10) повёрнутой картинки, нужно узнать цвет исходной (опять же например) в (10.5,11.5), а это уже вполне обычная задача интерполяции
с масштабированием ситуация похожая...

в принципе в голову приходят такие мысли:
1. выбирать ближайший пиксель (по сути, округлять)
2. брать усреднённое значение соседних символов
3. вообще построить какую-то модель изображения (например, взять его Фурье-образ, а потом исходя из него получать значения в промежутках, или перевести его в векторный вид, там повернуть и вернуть в растр)

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

Добавлено @ 21:55 
в общем, всё зависит от требуемого качества поворота
если требования не очень жёсткие, то можно останоситься, например, на выборе ближайшего пиксела, как самом простом

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

1. если повернуть на какой-то угол в одну сторону, а потом на него же в другую - получим то же самое изображение, при использовании большинства других методов картинка будет размазываться (правда, если повернуть два раза в одну сторону на 10 градусов, а потом в другую на 20, то уже и этот алгоритм не даст исходного изображения)

2. он только переставляет пикселы, т.е.:
--- никаких новых цветов на изображении не появляется, т.е. на чёрно-белом не появится серого
--- распределение тоже не меняется, т.е. сколько было пикселей (123,60,200), столько же их и останется (конечно, за исключением тех, которые выйдут за границу)

такие свойства тоже иногда могут пригодиться...


--------------------
qqq
PM WWW   Вверх
SoWa
Дата 27.2.2007, 22:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Харекришна
****


Профиль
Группа: Комодератор
Сообщений: 2422
Регистрация: 18.10.2004

Репутация: 6
Всего: 74



А если пиксели поворачивать синусом/косинусом smile 


--------------------
Всем добра smile
PM MAIL ICQ   Вверх
Bitter
Дата 27.2.2007, 23:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный лентяй
***


Профиль
Группа: Завсегдатай
Сообщений: 1209
Регистрация: 15.8.2004
Где: Харьков, Ukraine

Репутация: 4
Всего: 27



maxim1000, круто парня загрузил... Приведу код из книги "DirectX. Графика в проектах Delphi" М. Краснова (понятно, что код на делфи, однако напишу коментарии):

Код

type
  // этот массив используется при повороте. Он хранит в себе изображение
 // В примере изображение 255х255 пикселей
 TByteArray = Array [0..255, 0..255] of Byte;
...
    function Rotating : HRESULT;

    function Rotate (const pictOriginal : TByteArray;
                     const iRotationAxis, jRotationAxis: Integer;
                     const ug : Single) : TByteArray;
...
var 
  Pict  : TByteArray;
  Angle : Single = 0.0;

// Эта функция непосредственно связана с DirectX. В ней вызывается функция 
//поворота изображения (Rotate), а затем полученный массив 
//переписывается на поверхность (в DirectX это типа BitMap).
function TfrmDD.Rotating : HRESULT;
var   desc : TDDSURFACEDESC2; // свойства поверхности
        i, j : Byte;
        Image : TByteArray;            // Результирующее изображение      
        hRet : HRESULT;
begin
   ZeroMemory (@desc, SizeOf(desc));
   desc.dwSize := SizeOf(desc);

     // Поворачиваем изображение
     // Тут Pict - массив, в который загнали BitMap
     // 127, 127 - точка, вокруг которой поворачивать
     // Angle - угол поворота
   Image := Rotate (Pict, 127, 127, Angle);  

 // Следующие строки переписывают полученный массив в поверхность
 // Для BitMap'а они не подходят
 hRet := FDDSPrimary.Lock (nil, desc, DDLOCK_WAIT, 0);

 for i := 0 to 255 do
  for j := 0 to 255 do
    PByte (Integer (desc.lpSurface)+(j + 113)*desc.lPitch+i+193)^ := Image [i, j];

 Result := FDDSPrimary.Unlock (nil);
end;


// Эта функция собственно поворот изображения, хранящегося в массиве
function TfrmDD.Rotate (const pictOriginal : TByteArray; // исходное изобр.
                                      const iRotationAxis, jRotationAxis: Integer; // точка
                                      const ug : Single): TByteArray; // угол поворота
type
  wrkByteArray = Array [0..255] of Byte; // Вспомогательная строка
var
  i, j        : Integer;
  iOriginal   : Integer;
  iPrime      : Integer;
  jOriginal   : Integer;
  jPrime      : Integer;
  RowOriginal : ^wrkByteArray;
  RowRotated  : ^wrkByteArray; 
  sinTheta    : Single;
  cosTheta    : Single;
begin
  sinTheta := sin(ug);  // синус угла
  cosTheta := cos(ug); // косинус угла

  for j := 255 downto 0 do begin
    // Переменная Result в делфи - результат работы функции
    // Если Вы пишете на С++, прийдется объявить 
    // переменную Result типа TByteArray
    RowRotated := @Result [j, 0]; // Указатель на очередную строку изобр.
    jPrime := j - jRotationAxis;       // Смещение от оси по Y

    // Тут, короче, всякие вычисления
    for i := 255 downto 0 do begin // Цикл по столбцам
      iPrime := i - iRotationAxis;       // Смещение от оси по Х
      // Координаты нужной точки по Х и Y:
      iOriginal := iRotationAxis + trunc(iPrime * cosTheta - jPrime * sinTheta);
      jOriginal := jRotationAxis + trunc(iPrime * sinTheta + jPrime * cosTheta);

      // После поворота некоторые точки не имеют аналога в старом растре
      if (iOriginal >= 0) and (iOriginal <= 255) and   // Не границы
         (jOriginal >= 0) and (jOriginal <= 255) then 
      begin
          // Копируем в новый растр точку
          RowOriginal := @pictOriginal[jOriginal, 0];
          RowRotated^[i] := RowOriginal^[iOriginal]
      end
      else RowRotated[i] := 0;  // Иначе границы - черным цветом
    end
end;
end;



Добавлено @ 23:43 
Забыл сказать, что перед поворотом (32-я строка в листиге), необходимо заполнить массив Pict из BitMap'a. А после вызова функции, заполнить BitMap из массива.
PM MAIL ICQ Skype   Вверх
maxim1000
Дата 27.2.2007, 23:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: 33
Всего: 110



Цитата(SoWa @  27.2.2007,  21:08 Найти цитируемый пост)
А если пиксели поворачивать синусом/косинусом

тогда координаты получатся нецелые и возникает вопрос, куда их записывать


--------------------
qqq
PM WWW   Вверх
Bitter
Дата 28.2.2007, 00:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный лентяй
***


Профиль
Группа: Завсегдатай
Сообщений: 1209
Регистрация: 15.8.2004
Где: Харьков, Ukraine

Репутация: 4
Всего: 27



а тут вроде про масштаб:
http://forum.vingrad.ru/index.php?showtopi...st&p=589550
PM MAIL ICQ Skype   Вверх
nickless
Дата 28.2.2007, 00:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Гентозавр
****


Профиль
Группа: Участник Клуба
Сообщений: 2976
Регистрация: 29.8.2005
Где: Germany

Репутация: нет
Всего: 181



Если нужно качественно и не сильно медленно, можно взять например cubic b-spline алгоритм, описание и имплементацию см. в google или www.koders.com


--------------------
user posted image

Real men don't use backups, they post their stuff on a public ftp server and let the rest of the world make copies
- Linus Torvalds
PM MAIL   Вверх
skyboy
Дата 28.2.2007, 02:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


неОпытный
****


Профиль
Группа: Модератор
Сообщений: 9820
Регистрация: 18.5.2006
Где: Днепропетровск

Репутация: нет
Всего: 260



в принципе, при "чистом" повороте(без масштабирования) можно вести маску - хранить список "заполненных"  ячеек, чтоб не получилось, будто мы в одно место переместили две точки, а в другую - ни одной. тогда можно - либо округлять нецелые координаты, либо отбрасывать дробную часть. ещё можно пройтись дважды: один раз отбрасывая дробную часть у нецелых координат, второй раз - обрасывая дробную часть и прибавляя единицу. ясен пень, что теоретически точки могут поменять взаимное расположение, но это можно проконтролировать дополнительно. в некоторых случаях такой метод будет намного быстрее интерполяции для всех точек. 
PM MAIL   Вверх
Deniskkk
Дата 9.3.2007, 15:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 27.2.2007

Репутация: нет
Всего: нет



Спасибо за стоко ответов.
Писал - писал и всё не засейвилось. А ещё я на русском плохо печатаю.
Так что в крацце постараюсь ответить на свой вопрос...

В алгоритме описанном Bitter если считать в обратную сторону (искать цвет для каждого нового пикселя) и вместо truncate брать дробные результаты и смешивать близлежащие пиксели в определённом отношении.
Мои мысли:
Я было подумал по площади... но как её посчитать? Или может по функции какой? Если есть у кого мысли на эту тему поделитесь. Желательно чтоб формулы были попроще (ну всмысле чтоб для этого дифы не пришлось решать =] )
PM MAIL   Вверх
Earnest
Дата 13.3.2007, 09:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 7
Всего: 183



Deniskkk, самая простая интерполяция - билинейная (по 4 ближайшим пикселам). Однако она слегка размывает изображение. Формулы вот:

Код

// билинейная интерполяция
CRgb GetBilinear (const CPointD& ptD) const 
{
    // Координаты точки с вещественными координатами приводится к целым; 
    // учитывается то, насколько исходная точка "заползает" на одного из
    // своих собратьев
    CPoint pt ((long)floor(ptD.x), (long)floor(ptD.y));

    double IntPart;
    double Fx2 = modf (ptD.x, &IntPart),
             Fx1 = 1 - Fx2,
             Fy2 = modf (ptD.y, &IntPart),
             Fy1 = 1 - Fy2;

    double k1 = Fx1 * Fy1,
             k2 = Fx2 * Fy1,
             k3 = Fx2 * Fy2,
             k4 = Fx1 * Fy2;

    // Цвета четырех точек
    CRgb c1 = GetRGBPixel (pt); pt.x += 1;
    CRgb c2 = GetRGBPixel (pt); pt.y += 1;
    CRgb c3 = GetRGBPixel (pt); pt.x -= 1;
    CRgb c4 = GetRGBPixel (pt);

    // Цвет результирующей точки
    CRgb res    (Round (k1 * c1.m_r + k2 * c2.m_r + k3 * c3.m_r + k4 * c4.m_r),
                 Round (k1 * c1.m_g + k2 * c2.m_g + k3 * c3.m_g + k4 * c4.m_g),
                 Round (k1 * c1.m_b + k2 * c2.m_b + k3 * c3.m_b + k4 * c4.m_b));
    return res;
}


Использованные типы данных, надеюсь, прозрачны.
Кубическая интерполяция чуть сложнее (но никаких диффуров) и  дольше работает,  но результаты лучше. Надо?


--------------------
...
PM   Вверх
Deniskkk
Дата 13.3.2007, 10:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 27.2.2007

Репутация: нет
Всего: нет



спасибо. Удовлетворён =]
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Алгоритмы"

maxim1000

Форум "Алгоритмы" предназначен для обсуждения вопросов, связанных только с алгоритмами и структурами данных, без привязки к конкретному языку программирования и/или программному продукту.


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, maxim1000.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Алгоритмы | Следующая тема »


 




[ Время генерации скрипта: 0.2228 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.