opencv CvSolve函式深度解析

2021-07-23 14:54:59 字數 3287 閱讀 4168

opencv cvsolve函式主要是用來求解線性系統ax=b的方程,x的解。solve函式跟它的演算法是一樣的,也是用來求解線性系統。

設方程ax = b.根據有效的方程個數和未知數的個數,可以分為以下3種情況:

1)rank(a) < n,也就是說方程個數小於未知數的個數,約束不夠,方程存在無陣列解,

2)  rank(a) =  n  方程個數等於未知數的個數, 方程存在唯一的精確解,解法通常有我們熟悉的消元法,lu分解法

3)  rank(a) > n,方程個數多於未知數個數,這個時候約束過於嚴格,沒有精確解,這種方程又稱之為超定方程。通常工程應用都會遇到這種情況,找不到精確解的情況下,我們選取最優解。這個最優解,又稱之為最小二乘解。

前面2種情況是比較好理解的,我們在這裡就不多說了,我們重點研究的是第3種情況,也是我們應用中碰到最多最常見的情況。

這個超定方程的最優解是怎麼求的呢?常規的消元法是無解的,於是有人提出並證明了這樣乙個理論:

以下是定理3的證明:

我們把ax=b的問題直接轉化成a'a x = a'b的求解,那麼求超定線性方程組的方法,應該就轉換成(a'*a)x = (a'*b)咯。而這個新的方程又具有什麼樣的特性呢?

那麼,這個應該是常規線性方程求解啦,為什麼不能直接lu分解或是用消元法呢,這個文件裡說了,也確實是可以的

update(2017.5.8):這是有前提的,必須是r(a) = n時,atax = atb才有唯一解,否則,我們求的還是最小二乘解。

而在solve函式的**中,用特徵值分解(jacobi)呢?

jacobi方法用於求解對稱矩陣的特徵值,對稱矩陣不一定是滿秩矩陣,不一定能夠順利的lu分解,但是可以作svd分解!如果是呼叫cvsolve的話,求最小二乘解,

那麼最後一項要傳入cv_svd.不管是svd還是jacobi都是跟特徵值相關。jacobi求奇異值分解的方法

詳情參考

**片段加註解:

templatebool

jacobiimpl_( _tp* a, size_t astep, _tp* w, _tp* v, size_t vstep, int n, uchar* buf )

}int iters, maxiters = n*n*30;

int* indr = (int*)alignptr(buf, sizeof(int));

int* indc = indr + n;

_tp mv = (_tp)0;

for( k = 0; k < n; k++ )

indr[k] = m; //第a[k][k]右邊最大的非對角元素的列下標

}if( k > 0 )

indc[k] = m;//第a[k][k]上邊最大的非對角元素的行下標}}

if( n > 1 ) for( iters = 0; iters < maxiters; iters++ )

int l = indr[k];

for( i = 1; i < n; i++ )

_tp p = a[astep*k + l];

if( std::abs(p) <= eps )

break;

_tp y = (_tp)((w[l] - w[k])*0.5);

_tp t = std::abs(y) + hypot(p, y);

_tp s = hypot(p, t);

_tp c = t/s;

s = p/s; t = (p/t)*p;

if( y < 0 )

s = -s, t = -t;

a[astep*k + l] = 0;

w[k] -= t;

w[l] += t;

_tp a0, b0;

#undef rotate

#define rotate(v0, v1) a0 = v0, b0 = v1, v0 = a0*c - b0*s, v1 = a0*s + b0*c

// rotate rows and columns k and l

for( i = 0; i < k; i++ )

rotate(a[astep*i+k], a[astep*i+l]);

for( i = k+1; i < l; i++ )

rotate(a[astep*k+i], a[astep*i+l]);

for( i = l+1; i < n; i++ )

rotate(a[astep*k+i], a[astep*l+i]);

// rotate eigenvectors

if( v )

for( i = 0; i < n; i++ )

rotate(v[vstep*k+i], v[vstep*l+i]);

#undef rotate

for( j = 0; j < 2; j++ )

indr[idx] = m;

}if( idx > 0 )

indc[idx] = m;}}

}//降序排列特徵值和相應的特徵向量

// sort eigenvalues & eigenvectors

for( k = 0; k < n-1; k++ )

if( k != m )

}return true;

}

值得一提的是,當b = 0時,超定齊次線性方程 a*x =0;求解最小二乘解,在||x||=1的約束下,其最小二乘解為矩陣a'a最小特徵值所對應的特徵向量。

參考簡單證明:

min ||ax|| 

s.t    ||x||=1

目標函式:||ax|| = x'a'ax = x'lamda x=lamda||x||=lamda,其中lamda是a'a的特徵值。

於是可知,得到了a'a的最小特徵值,就得到了最優值,而其最小特徵值對應的特徵向量就是最優解.

函式基礎 匿名函式,函式,箭頭函式,立即執行函式

doctype html html lang en head meta charset utf 8 meta name viewport content width device width,initial scale 1.0 title document title head body body ...

函式 常見函式

def fib n if n 1 return 1if n 2 return 1return fib n 1 fib n 2 def hannuo n,a,b,c n 表示有n個盤子 a 代表第乙個塔,開始的塔 b 代表第二個塔,過渡塔 c 代表第三個塔,目標塔 d.在 中n 2,這個分支可以不要,...

Lua 函式 函式

在lua中,函式是一種對語句和表示式進行抽象的主要機制。函式既可以完成某項特定的任務,也可以只做一些計算並返回結果。lua具有一項非常於總不同的特徵,允許函式返回多個結果 s,e string.find hello lua users lua print s,e 7 9 以lua編寫的函式同樣可以返...