Поиск:

Ответ в темуСоздание новой темы Создание опроса
> определение аффинного преобразования по точкам 
:(
    Опции темы
mrgloom
Дата 24.8.2012, 11:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



возник вопрос насчёт нахождения аффинного преобразования по точкам.
допустим имеем пары точек.
user posted image
user posted image
ну как высчитывается сдвиг понятно, а вот как вычисляется матрица [math]$A$[/math] непонятно.
точнее как составляется матрицы из гомогенных координат.
PM MAIL   Вверх
Earnest
Дата 27.8.2012, 11:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Вот кусок кода, к-й рассчитывает афинное преобразование по набору точек.
Входные параметры - массив опорных точек (просто пары точек scr-dst)
Вычисляется 6 афинных коэффициентов; там есть комментарий откуда видно куда какой
Код

// Определяем преобразование по множеству точек совмещения:
// если точек < 3 или точки коллинеарны, то false, иначе афинное;
bool CAffineParams::Define (const CRefPoint* pRp, size_t nCnt)
{
   if (nCnt < 3) return false;

   m_bInvOk = false;
   ASSERT (AfxIsValidAddress (pRp, sizeof(*pRp)*nCnt));

   // обозначаем: (x,y)<=>Src, (u,v)<=>Dst

   // вычисление средних значений
   double Sx=0,Sy=0,Sv=0,Su=0;
   for (size_t i=0; i < nCnt; ++i) 
   {
      Sx += pRp[i].m_ptSrc.x; Sy += pRp[i].m_ptSrc.y;
      Su += pRp[i].m_ptDst.x; Sv += pRp[i].m_ptDst.y;
   }
   Sx /= nCnt; Sy /= nCnt; Su /= nCnt; Sv /= nCnt;

    // вычисляем суммы
    double Sxx=0,Syy=0,Sxy=0,
          Sxu=0,Syu=0,Sxv=0,Syv=0;
    for (i=0; i < nCnt; ++i)
   {
        double dx = pRp[i].m_ptSrc.x-Sx, 
             dy = pRp[i].m_ptSrc.y-Sy,
                 du = pRp[i].m_ptDst.x-Su, 
             dv = pRp[i].m_ptDst.y-Sv;
        Sxx += dx*dx;    Syy += dy*dy;  Sxy += dx*dy;
      Syv += dy*dv;    Sxv += dx*dv;    Syu += dy*du;    Sxu += dx*du;
    }

    // вычисляем знаменатель
    double Dxy = Syy*Sxx - Sxy*Sxy; 
    if (fabs(Dxy) < EPSILON)
      return false;

    // коэффициенты прямого преобразования: (x,y)->(u,v) (SrcToDst)
   //      u = m_D[0]*x + m_D[1]*y + m_D[2]
   //      v = m_D[3]*x + m_D[4]*y + m_D[5]

   m_D[0] = (Syy*Sxu - Sxy*Syu)/Dxy;
    m_D[1] = (Syu*Sxx - Sxy*Sxu)/Dxy;
    m_D[2] = Su - Sx*m_D[0] - Sy*m_D[1];
    m_D[3] = (Syy*Sxv - Sxy*Syv)/Dxy;
    m_D[4] = (Syv*Sxx - Sxy*Sxv)/Dxy;
    m_D[5] = Sv - Sx*m_D[3] - Sy*m_D[4];

   RecalcDistTrns (m_D);   

   return true;
}



--------------------
...
PM   Вверх
mrgloom
Дата 27.8.2012, 14:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



а математически метод этот как называется?
по коду походу там вычисляется сначала мат.ожидание, потом дисперсия,потом походу определитель матрицы ковариации.
откуда следуют конечные формулы я не смог понять.

может быть система переопределена и содержать шум?

а для перспективного искажения как будет выглядеть? 



PM MAIL   Вверх
Earnest
Дата 27.8.2012, 16:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Да это просто МНК. Т.е. минимизация среднеквадратичной ошибки. Составляем сумму квадратов разностей, дифференцируем, приравниваем к нулю и вот оно. 
Что значит - переопределена? Точек больше чем 3, определяющих афинное преобразование? Так в этом и смысл - ошибка "разбрасывается".
Конечно, выбросы влияют сильно и нехорошо - но это вообще беда МНК. 
Перспективное искажение афинным преобразованием не устраняется, естественно. Афинное - это прямоугольник в параллелограмм. А если у нас трапеция, то получится такой усредненный параллелограмм. От точек зависит, конечно.
У тебя на первой картинке (с буквой А) никакое не афинное изображено, конечно (если отрезки - это вектора переноса точек).


--------------------
...
PM   Вверх
mrgloom
Дата 29.8.2012, 12:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



не очень понимаю как тут применяется МНК, может напишете как поставлена задача?

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

мы знаем (x,y)->(u,v) и хотим найти матрицу перехода M, т.к. афинные это частный случай перспективных, то можно сразу говорить о перспективных.
получается переопредеденная линейная система, вроде она решается как раз через МНК, только я не знаю как.

еще вопрос-рассуждение.
user posted image
вот допустим я взял 2 похожие фигуры, и совместил их центры масс, затем для каждой точки одной фигуры нашел точку которая находится на мин расстоянии, т.е. я получил пары, могу ли я по этим парам найти преобразование которое меня приблизит к тому чтобы фигуры совместились?
PM MAIL   Вверх
mrgloom
Дата 29.8.2012, 13:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



вообщем тут написано, что можно решить переопределенную систему уравнений через вычисление определителей(только причем тут МНК?)
http://helpstat.ru/2012/01/metod-naimenshix-kvadratov/
и опять же у вас в коде в конце какие то странныеформулы.


а вообще кажется понял, попробую переписать для 9 неизвестных.

Это сообщение отредактировал(а) mrgloom - 29.8.2012, 14:03
PM MAIL   Вверх
Earnest
Дата 30.8.2012, 08:02 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(mrgloom @  29.8.2012,  13:54 Найти цитируемый пост)
 вроде она решается как раз через МНК, только я не знаю как.
 Стандартно: задача МНК - это минимизация суммы квадратов ошибок. Параметры (коэффициенты) преобразования являются в данном случае переменными, по которым производится минимизация. Т.е. выражение для ошибки Sum (X - U)^2 дифференцируем по каждому параметру, приравниваем к нулю и получаем 6 линейных уравнений. Метод работает для любых преобразований, линейных по параметрам. Как получились формулы, которые у меня в коде, я уже не помню, дело давно было. Очевидно, там не прямое решение линейной системы из 6 уравнений. Видимо, система за счет преобразований и выражений через моменты была разделена и решена аналитически.
Цитата(mrgloom @  29.8.2012,  13:54 Найти цитируемый пост)
вот допустим я взял 2 похожие фигуры, и совместил их центры масс, затем для каждой точки одной фигуры нашел точку которая находится на мин расстоянии, т.е. я получил пары, могу ли я по этим парам найти преобразование которое меня приблизит к тому чтобы фигуры совместились? 

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


--------------------
...
PM   Вверх
Pavia
Дата 30.8.2012, 09:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



mrgloom
Для решение переопределенной системы применяют метод МНК. 

http://helpstat.ru/2012/01/metod-naimenshix-kvadratov/
В этой статье МНК описан для не переопределённого случая. 
Для решения системы уравнений используется метод Метод Крамера он основан на нахождение определителя.

Для переопределённой системы он не годится.  Для неё надо делать псевдообращение матрицы. 
Достаточно популярный метод нахождения псевдообращение через SVD.  

Но как по мне он плохо работает. 
Лучше взять алгоритм Earnest'а или что-то близкое.  

Про решение переопределенных систем при помощи МНК можно прочитать в 
Каханер,_Моулер,_Наш.-Численные_методы_и_программное_обеспечение-Мир(1998)

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

Так как процесс итерационный, то приблизится. Единственное что в конце мы можем попасть в устойчивую точку. А их может быть несколько.  Так что я бы попробовал 4 или 8   начальных положения. Т.е проверил бы варианты предварительно повернув на 45, 90,135,180,225,270,315. 

К примеру возьми контуры карандашей. Они могут оказаться как коллинеарны, так и сонаправлены.


PM MAIL   Вверх
mrgloom
Дата 30.8.2012, 10:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



помоему там система тоже переопределена, т.к. для нахождения линии надо 2 точки, а там их больше.


ну попробовал я через псевдообратную матрицу(только тут помоему без SVD)
http://opencv.willowgarage.com/documentati...operations.html
по формуле

и у меня получилось, что все нули, что это означает, что нет решения?
хотя может я сами уравнения не правильно составил?
т.е. я взял просто СЛАУ которая получается от перспективных преобразований, а надо было производные от суммы квадратов приравнять нулю и из этого получить СЛАУ?
Код

void perspective_transform(vector<Point>& in_vec,vector<Point>& out_vec)
{
        double m11=0.4;
        double m12=0.1;
        double m13=12;
        double m21=0.5;
        double m22=1.3;
        double m23=10;
        double m31=0.001;
        double m32=0;
        double m33=1;

        //прямое перспективное искажение
        for(int i=0;i<in_vec.size();++i)
        {
                int x= in_vec[i].x;
                int y= in_vec[i].y;
                int u= (m11*x + m12*y + m13)/(m31*x + m32*y + m33);
                int v= (m21*x + m22*y + m23)/(m31*x + m32*y + m33);

                out_vec.push_back(Point(u,v));
        }
}
void get_perspective()
{
        //попробуем по найденным парам точек восстановить аффинное преобразование
        //решаем переопределенную СЛАУ
        //имеем N пар точек, значит 2*N уравнений
        //вида
        //double u= (m11*x + m12*y + m13)/(m31*x + m32*y + m33);
        //double v= (m21*x + m22*y + m23)/(m31*x + m32*y + m33);
        //переписываем как линейную систему относительно m{i,j}
        //m11*(x)+m12*(y)+m13*(1)+m21*(0)+m22*(0)+m23(0)+m31*(-xu)+m32*(-yu)+m33*(-u)=0
        //m11*(0)+m12*(0)+m13*(0)+m21*(x)+m22*(y)+m23(1)+m31*(-xv)+m32*(-yv)+m33*(-v)=0
        //для каждой пары точек (x,y)->(u,v) добавляем в систему 2 уравнения
        Mat A(0,9,CV_32FC1);
        Mat b(0,1,CV_32FC1); 
        Mat t(1,9,CV_32FC1);

        //test
        vec_T.clear();//
        perspective_transform(vec_M,vec_T);//

        //для каждой точки в первом сете найдем ближайшую точку во втором
        for(int i=0;i<vec_M.size();++i)
        {
                double min_dist=INT_MAX;
                int id=-1;
                //для каждой точки проходимся по всему второму массиву ищем минимум
                for(int j=0;j<vec_T.size();++j)
                {
                        double metric= sqrt(double(vec_T[j].x-vec_M[i].x)*(vec_T[j].x-vec_M[i].x)+
                                (vec_T[j].y-vec_M[i].y)*(vec_T[j].y-vec_M[i].y));
                        if(min_dist>metric)
                        {
                                min_dist=metric;
                                id=j;
                        }
                }

                int x= vec_M[i].x;
                int y= vec_M[i].y;
                int u= vec_T[id].x;
                int v= vec_T[id].y;
                //m11*(x)+m12*(y)+m13*(1)+m21*(0)+m22*(0)+m23(0)+m31*(-xu)+m32*(-yu)+m33*(-u)=0
                //m11*(0)+m12*(0)+m13*(0)+m21*(x)+m22*(y)+m23(1)+m31*(-xv)+m32*(-yv)+m33*(-v)=0
                t.at<float>(0,0)= x;
                t.at<float>(0,1)= y;
                t.at<float>(0,2)= 1;
                t.at<float>(0,3)= 0;
                t.at<float>(0,4)= 0;
                t.at<float>(0,5)= 0;
                t.at<float>(0,6)= -x*u;
                t.at<float>(0,7)= -y*u;
                t.at<float>(0,8)= -u;
                A.push_back(t);
                t.at<float>(0,0)= 0;
                t.at<float>(0,1)= 0;
                t.at<float>(0,2)= 0;
                t.at<float>(0,3)= x;
                t.at<float>(0,4)= y;
                t.at<float>(0,5)= 1;
                t.at<float>(0,6)= -x*v;
                t.at<float>(0,7)= -y*v;
                t.at<float>(0,8)= -v;
                A.push_back(t);
        }

        b.resize(2*vec_M.size(),0);

        cout<<A;
        cout<<b;
        Mat m = (A.t()*A).inv()*(A.t()*B); //нули возможно потому, что система не решаема?
        cout<<m;
}




про нахождение пар.
есть вариант использовать shape context  и потом там получается assigment problem которая решается через hungarian algorithm.
(но я еще это не пробовал)
собственно говоря, если мы у каждой точки имеем соответствие, то нам и не надо решать систему-определять перспективное преобразование, а можно варпнуть просто используя точки. 





PM MAIL   Вверх
mrgloom
Дата 30.8.2012, 11:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



кажется понял.

Цитата

double u= (m11*x + m12*y + m13)/(m31*x + m32*y + m33);
double v= (m21*x + m22*y + m23)/(m31*x + m32*y + m33);


для affine  m31=m32=0 m33=1
Цитата

double u= (m11*x + m12*y + m13);
double v= (m21*x + m22*y + m23);

значит S=SUM[ (u(i)-(m11*x(i) + m12*y(i) + m13))^2+(v(i)-(m21*x(i) + m22*y(i) + m23))^2 ]
потом всё это переписываем в СЛАУ относительно 6 переменных.


Цитата

m11*(x*x)+m12*(y*x)+m13*(x)+m21*(0)+m22*(0)+m23(0)=u*x
m11*(x*y)+m12*(y*y)+m13*(y)+m21*(0)+m22*(0)+m23(0)=u*y
m11*(x)+m12*(y)+m13*(1)+m21*(0)+m22*(0)+m23(0)=u
m11*(0)+m12*(0)+m13*(0)+m21*(x*x)+m22*(y*x)+m23(x)=v*x
m11*(0)+m12*(0)+m13*(0)+m21*(x*y)+m22*(y*y)+m23(y)=v*y
m11*(0)+m12*(0)+m13*(0)+m21*(x)+m22*(y)+m23(1)=v


единственное смущает, что 1-3 (4-6) получаются линейно зависимы? т.е. различаются всего лишь на умножение на константу.
PM MAIL   Вверх
mrgloom
Дата 30.8.2012, 14:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



даже при искусственном примере почему то не работает.

Код

//это используется в конце чтобы протестировать полученную матрицу
void affine_transform(vector<Point>& in_vec,vector<Point>& out_vec,Mat& M)
{
        out_vec.clear();
        double m11= M.at<float>(0,0);
        double m12= M.at<float>(0,1);
        double m13= M.at<float>(0,2);
        double m21= M.at<float>(1,0);
        double m22= M.at<float>(1,1);
        double m23= M.at<float>(1,2);
        double m31= 0/*M.at<float>(2,0)*/;
        double m32= 0/*M.at<float>(2,1)*/;
        double m33= 1/*M.at<float>(2,2)*/;

        //прямое перспективное искажение
        for(int i=0;i<in_vec.size();++i)
        {
                int x= in_vec[i].x;
                int y= in_vec[i].y;
                int u= (m11*x + m12*y + m13)/(m31*x + m32*y + m33);
                int v= (m21*x + m22*y + m23)/(m31*x + m32*y + m33);

                out_vec.push_back(Point(u,v));
        }
}
//это я использую чтобы трансформировать исходные точки для теста
void perspective_transform(vector<Point>& in_vec,vector<Point>& out_vec/*,Mat& M*/)
{
        out_vec.clear();
        //вынести в параметры?
        double m11=0.4;
        double m12=0.1;
        double m13=12;
        double m21=0.5;
        double m22=1.3;
        double m23=10;
        double m31=0;
        double m32=0;
        double m33=1;
        //double m11= M.at<float>(0,0);
        //double m12= M.at<float>(0,1);
        //double m13= M.at<float>(0,2);
        //double m21= M.at<float>(1,0);
        //double m22= M.at<float>(1,1);
        //double m23= M.at<float>(1,2);
        //double m31= 0/*M.at<float>(2,0)*/;
        //double m32= 0/*M.at<float>(2,1)*/;
        //double m33= 1/*M.at<float>(2,2)*/;

        //прямое перспективное искажение
        for(int i=0;i<in_vec.size();++i)
        {
                int x= in_vec[i].x;
                int y= in_vec[i].y;
                int u= (m11*x + m12*y + m13)/(m31*x + m32*y + m33);
                int v= (m21*x + m22*y + m23)/(m31*x + m32*y + m33);

                out_vec.push_back(Point(u,v));
        }
}
void get_affine()
{
        //попробуем по найденным парам точек восстановить аффинное преобразование
        //решаем СЛАУ
        //получается сколько параметров столько и уравнений(6 для аффинных)
        //вида
        //double u= (m11*x + m12*y + m13)/(m31*x + m32*y + m33); //m31=m32=0 m33=1
        //double v= (m21*x + m22*y + m23)/(m31*x + m32*y + m33);
        //задача поставлена как производная сумм квадратов по всем переменным =0
        //потом переписываем это всё в СЛАУ от 6 неизвестных

        //а для перспективных получается уже не СЛАУ

        Mat A(6,6,CV_32FC1);
        Mat b(6,1,CV_32FC1);

        ////test
        vec_T.clear();//
        perspective_transform(vec_M,vec_T);//

        int sx=0;
        int sy=0;
        int sxx=0;
        int syy=0;
        int sxy=0;
        int sux=0;
        int suy=0;
        int svx=0;
        int svy=0;
        int sv=0;
        int su=0;
        int k=0;

        //для каждой точки в первом сете найдем ближайшую точку во втором
        for(int i=0;i<vec_M.size();++i)
        {
                //double min_dist=INT_MAX;
                //int id=-1;
                ////для каждой точки проходимся по всему второму массиву ищем минимум
                //for(int j=0;j<vec_T.size();++j)
                //{
                //      //метрика всегда по нулям
                //      double metric= sqrt(double(vec_T[j].x-vec_M[i].x)*(vec_T[j].x-vec_M[i].x)+
                //              (vec_T[j].y-vec_M[i].y)*(vec_T[j].y-vec_M[i].y));
                //      if(min_dist>metric)
                //      {
                //              min_dist=metric;
                //              id=j;
                //      }
                //}

                //line(img,vec_M[i],vec_T[id],cvScalar(0,0,255));

                //int x= vec_M[i].x;
                //int y= vec_M[i].y;
                //int u= vec_T[id].x;
                //int v= vec_T[id].y;

                //test
                line(img,vec_M[i],vec_T[i],cvScalar(0,0,255));
                int x= vec_M[i].x;
                int y= vec_M[i].y;
                int u= vec_T[i].x;
                int v= vec_T[i].y;

                //не забываем что там везде суммы
                //m11*(x*x)+m12*(y*x)+m13*(x)+m21*(0)+m22*(0)+m23(0)=u*x
                //m11*(x*y)+m12*(y*y)+m13*(y)+m21*(0)+m22*(0)+m23(0)=u*y
                //m11*(x)+m12*(y)+m13*(1)+m21*(0)+m22*(0)+m23(0)=u
                //m11*(0)+m12*(0)+m13*(0)+m21*(x*x)+m22*(y*x)+m23(x)=v*x
                //m11*(0)+m12*(0)+m13*(0)+m21*(x*y)+m22*(y*y)+m23(y)=v*y
                //m11*(0)+m12*(0)+m13*(0)+m21*(x)+m22*(y)+m23(1)=v

                sx+=x;
                sy+=x;
                sxx+=x*x;
                syy+=y*y;
                sux+=u*x;
                suy+=u*y;
                svx+=v*x;
                svy+=v*y;
                sv+=v;
                su+=u;
                sxy+=x*y;
                ++k;
        }

        //заполняем матрицу 6х6
        //m11*(x*x)+m12*(y*x)+m13*(x)+m21*(0)+m22*(0)+m23(0)=u*x
        A.at<float>(0,0)= sxx;
        A.at<float>(0,1)= sxy;
        A.at<float>(0,2)= sx;
        A.at<float>(0,3)= 0;
        A.at<float>(0,4)= 0;
        A.at<float>(0,5)= 0;
        //m11*(x*y)+m12*(y*y)+m13*(y)+m21*(0)+m22*(0)+m23(0)=u*y
        A.at<float>(1,0)= sxy;
        A.at<float>(1,1)= syy;
        A.at<float>(1,2)= sy;
        A.at<float>(1,3)= 0;
        A.at<float>(1,4)= 0;
        A.at<float>(1,5)= 0;
        //m11*(x)+m12*(y)+m13*(1)+m21*(0)+m22*(0)+m23(0)=u
        A.at<float>(2,0)= sx;
        A.at<float>(2,1)= sy;
        A.at<float>(2,2)= 1*k;
        A.at<float>(2,3)= 0;
        A.at<float>(2,4)= 0;
        A.at<float>(2,5)= 0;
        //m11*(0)+m12*(0)+m13*(0)+m21*(x*x)+m22*(y*x)+m23(x)=v*x
        A.at<float>(3,0)= 0;
        A.at<float>(3,1)= 0;
        A.at<float>(3,2)= 0;
        A.at<float>(3,3)= sxx;
        A.at<float>(3,4)= sxy;
        A.at<float>(3,5)= sx;
        //m11*(0)+m12*(0)+m13*(0)+m21*(x*y)+m22*(y*y)+m23(y)=v*y
        A.at<float>(4,0)= 0;
        A.at<float>(4,1)= 0;
        A.at<float>(4,2)= 0;
        A.at<float>(4,3)= sxy;
        A.at<float>(4,4)= syy;
        A.at<float>(4,5)= sy;
        //m11*(0)+m12*(0)+m13*(0)+m21*(x)+m22*(y)+m23(1)=v
        A.at<float>(5,0)= 0;
        A.at<float>(5,1)= 0;
        A.at<float>(5,2)= 0;
        A.at<float>(5,3)= sx;
        A.at<float>(5,4)= sy;
        A.at<float>(5,5)= 1*k;

        b.at<float>(0,0)= sux;
        b.at<float>(1,0)= suy;
        b.at<float>(2,0)= su;
        b.at<float>(3,0)= svx;
        b.at<float>(4,0)= svy;
        b.at<float>(5,0)= sv;

        cout<<A;
        cout<<b;
        //пробуем разные методы решения
        Mat m1 = (A.t()*A).inv()*(A.t()*B);
        cout<<m1;
        Mat m2;
        solve(A,b,m2,DECOMP_LU);
        cout<<m2;
        Mat m3;
        solve(A,b,m3,DECOMP_SVD);
        cout<<m3;
        Mat m4;
        solve(A,b,m4,DECOMP_QR);
        cout<<m4;
        
        affine_transform(vec_M,vec_T,m1.reshape(3));
        imshow("img",img);
}

PM MAIL   Вверх
mrgloom
Дата 30.8.2012, 15:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



попробовал метод от Earnest, работает, но  я всё таки не понимаю как выведены эти формулы.
и еще для перспективных искажений так просто не получится? т.е. там система не линейная получается.

Это сообщение отредактировал(а) mrgloom - 30.8.2012, 15:55
PM MAIL   Вверх
W4FhLF
Дата 31.8.2012, 11:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


found myself
****


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

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



Если система переопределена, то ты находишь решение с минимальной нормой невязки (в твоём случае L2 норма, соответственно и выбросы будут влиять сильно, если ничего с этим не делать) и оно единственно, если система недоопределена, то ты находишь одно из возможных решений МНК. 


Цитата(Pavia @  30.8.2012,  09:14 Найти цитируемый пост)
Достаточно популярный метод нахождения псевдообращение через SVD.  

Но как по мне он плохо работает. 


Чем это плохо? Сингулярное разложение самая робастная процедура.



Это сообщение отредактировал(а) W4FhLF - 31.8.2012, 12:10


--------------------
"Бог умер" © Ницше
"Ницше умер" © Бог
PM ICQ   Вверх
mrgloom
Дата 31.8.2012, 15:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



еще раз про Least squares, я так понял это всего лишь метод решения, т.е. задать целевую функцию и её потом минимизировать.

еще есть варианты когда не так чувствительны к аутлпайнерам
http://research.microsoft.com/en-us/um/peo...tim/node24.html

и тут возможно 2 исхода, у нас получится линейная система 
http://en.wikipedia.org/wiki/Linear_least_...s_(mathematics)
вот там как раз рассматривается решение через псевдообратную матрицу, только почему и зачем мы домножаем, как бы и так решаемое уравнение на транспонированную матрицу?(нашел объяснение тут на стр 4 http://classes.soe.ucsc.edu/cmps290c/Spring04/paps/lls.pdf )
а слайд 14 меня натолкнул на мысль, почему бы не вписать элипсы в наборы точек, а потом зная диагонали концов осей не найти преобразование?
потом еще и через QR и SVD. вроде еще и LU используют?
а в разделе Limitations еще вроде и альтернативы написаны которые лучше к шумам относятся.
 
или у нас получится нелинейная система
http://en.wikipedia.org/wiki/Non-linear_least_squares
пока не осиливал.(как такой случай должен получится в случае перспективных искажений, только непонятно всё таки можно найти единственное решение?)


и всё таки разбирая предоставленный код, я не понимаю откуда такие формулы расчёта.
может быть кто нибудь объяснит?



// вычисление средних значений  //почему вычисляем среднее? вроде должны просто сумму?
   double Sx=0,Sy=0,Sv=0,Su=0;
   for (size_t i=0; i < nCnt; ++i) 
   {
      Sx += pRp[i].m_ptSrc.x; Sy += pRp[i].m_ptSrc.y;
      Su += pRp[i].m_ptDst.x; Sv += pRp[i].m_ptDst.y;
   }
   Sx /= nCnt; Sy /= nCnt; Su /= nCnt; Sv /= nCnt;
    // вычисляем суммы  // тут опять же должны просто суммы а зачем то вычитаем среднее
    double Sxx=0,Syy=0,Sxy=0,
          Sxu=0,Syu=0,Sxv=0,Syv=0;
    for (i=0; i < nCnt; ++i)
   {
        double dx = pRp[i].m_ptSrc.x-Sx, 
             dy = pRp[i].m_ptSrc.y-Sy,
                 du = pRp[i].m_ptDst.x-Su, 
             dv = pRp[i].m_ptDst.y-Sv;
        Sxx += dx*dx;    Syy += dy*dy;  Sxy += dx*dy;
      Syv += dy*dv;    Sxv += dx*dv;    Syu += dy*du;    Sxu += dx*du;
    }
    // вычисляем знаменатель // далее вообще непонятно что делается, отдаленно похоже на вычисление определителей 2х2.
    double Dxy = Syy*Sxx - Sxy*Sxy; 
    if (fabs(Dxy) < EPSILON)
      return false;
    // коэффициенты прямого преобразования: (x,y)->(u,v) (SrcToDst)
   //      u = m_D[0]*x + m_D[1]*y + m_D[2]
   //      v = m_D[3]*x + m_D[4]*y + m_D[5]
   m_D[0] = (Syy*Sxu - Sxy*Syu)/Dxy;
    m_D[1] = (Syu*Sxx - Sxy*Sxu)/Dxy;
    m_D[2] = Su - Sx*m_D[0] - Sy*m_D[1];
    m_D[3] = (Syy*Sxv - Sxy*Syv)/Dxy;
    m_D[4] = (Syv*Sxx - Sxy*Sxv)/Dxy;
    m_D[5] = Sv - Sx*m_D[3] - Sy*m_D[4];

Это сообщение отредактировал(а) mrgloom - 6.9.2012, 17:25
PM MAIL   Вверх
mrgloom
Дата 13.9.2012, 08:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



похоже это называется  Horn's method
http://www.mathworks.com/matlabcentral/fil...ms2D_nobsxfun.m
http://home.hiroshima-u.ac.jp/tamaki/study...micp_on_gpu.pdf
слайд 9

только тут определяется поворот, смещение и увеличение.
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Алгоритмы"

maxim1000

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


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

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


 




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


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

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