📄 cxmatrix.cpp
字号:
/****************************************************************************************\
* Determinant of the matrix *
\****************************************************************************************/
#define det2(m) (m(0,0)*m(1,1) - m(0,1)*m(1,0))
#define det3(m) (m(0,0)*(m(1,1)*m(2,2) - m(1,2)*m(2,1)) - \
m(0,1)*(m(1,0)*m(2,2) - m(1,2)*m(2,0)) + \
m(0,2)*(m(1,0)*m(2,1) - m(1,1)*m(2,0)))
CV_IMPL double
cvDet( const CvArr* arr )
{
double result = 0;
uchar* buffer = 0;
int local_alloc = 0;
CV_FUNCNAME( "cvDet" );
__BEGIN__;
CvMat stub, *mat = (CvMat*)arr;
int type;
if( !CV_IS_MAT( mat ))
{
CV_CALL( mat = cvGetMat( mat, &stub ));
}
type = CV_MAT_TYPE( mat->type );
if( mat->width != mat->height )
CV_ERROR( CV_StsBadSize, "The matrix must be square" );
#define Mf( y, x ) ((float*)(m + y*step))[x]
#define Md( y, x ) ((double*)(m + y*step))[x]
if( mat->width == 2 )
{
uchar* m = mat->data.ptr;
int step = mat->step;
if( type == CV_32FC1 )
{
result = det2(Mf);
}
else if( type == CV_64FC1 )
{
result = det2(Md);
}
else
{
CV_ERROR( CV_StsUnsupportedFormat, "" );
}
}
else if( mat->width == 3 )
{
uchar* m = mat->data.ptr;
int step = mat->step;
if( type == CV_32FC1 )
{
result = det3(Mf);
}
else if( type == CV_64FC1 )
{
result = det3(Md);
}
else
{
CV_ERROR( CV_StsUnsupportedFormat, "" );
}
}
else if( mat->width == 1 )
{
if( type == CV_32FC1 )
{
result = mat->data.fl[0];
}
else if( type == CV_64FC1 )
{
result = mat->data.db[0];
}
else
{
CV_ERROR( CV_StsUnsupportedFormat, "" );
}
}
else
{
CvLUDecompFunc decomp_func;
CvSize size = cvGetMatSize( mat );
const int worktype = CV_64FC1;
int buf_size = size.width*size.height*CV_ELEM_SIZE(worktype);
CvMat tmat;
if( !lu_inittab )
{
icvInitLUTable( &lu_decomp_tab, &lu_back_tab );
lu_inittab = 1;
}
if( CV_MAT_CN( type ) != 1 || CV_MAT_DEPTH( type ) < CV_32F )
CV_ERROR( CV_StsUnsupportedFormat, "" );
if( size.width <= CV_MAX_LOCAL_MAT_SIZE )
{
buffer = (uchar*)cvStackAlloc( buf_size );
local_alloc = 1;
}
else
{
CV_CALL( buffer = (uchar*)cvAlloc( buf_size ));
}
CV_CALL( cvInitMatHeader( &tmat, size.height, size.width, worktype, buffer ));
if( type == worktype )
{
CV_CALL( cvCopy( mat, &tmat ));
}
else
CV_CALL( cvConvert( mat, &tmat ));
decomp_func = (CvLUDecompFunc)(lu_decomp_tab.fn_2d[CV_MAT_DEPTH(worktype)-CV_32F]);
assert( decomp_func );
IPPI_CALL( decomp_func( tmat.data.db, tmat.step, size, 0, 0, size, &result ));
}
#undef Mf
#undef Md
/*icvCheckVector_64f( &result, 1 );*/
__END__;
if( buffer && !local_alloc )
cvFree( &buffer );
return result;
}
/****************************************************************************************\
* Inverse (or pseudo-inverse) of the matrix *
\****************************************************************************************/
#define Sf( y, x ) ((float*)(srcdata + y*srcstep))[x]
#define Sd( y, x ) ((double*)(srcdata + y*srcstep))[x]
#define Df( y, x ) ((float*)(dstdata + y*dststep))[x]
#define Dd( y, x ) ((double*)(dstdata + y*dststep))[x]
CV_IMPL double
cvInvert( const CvArr* srcarr, CvArr* dstarr, int method )
{
CvMat* u = 0;
CvMat* v = 0;
CvMat* w = 0;
uchar* buffer = 0;
int local_alloc = 0;
double result = 0;
CV_FUNCNAME( "cvInvert" );
__BEGIN__;
CvMat sstub, *src = (CvMat*)srcarr;
CvMat dstub, *dst = (CvMat*)dstarr;
int type;
if( !CV_IS_MAT( src ))
CV_CALL( src = cvGetMat( src, &sstub ));
if( !CV_IS_MAT( dst ))
CV_CALL( dst = cvGetMat( dst, &dstub ));
type = CV_MAT_TYPE( src->type );
if( method == CV_SVD || method == CV_SVD_SYM )
{
int n = MIN(src->rows,src->cols);
if( method == CV_SVD_SYM && src->rows != src->cols )
CV_ERROR( CV_StsBadSize, "CV_SVD_SYM method is used for non-square matrix" );
CV_CALL( u = cvCreateMat( n, src->rows, src->type ));
if( method != CV_SVD_SYM )
CV_CALL( v = cvCreateMat( n, src->cols, src->type ));
CV_CALL( w = cvCreateMat( n, 1, src->type ));
CV_CALL( cvSVD( src, w, u, v, CV_SVD_U_T + CV_SVD_V_T ));
if( type == CV_32FC1 )
result = w->data.fl[0] >= FLT_EPSILON ?
w->data.fl[w->rows-1]/w->data.fl[0] : 0;
else
result = w->data.db[0] >= FLT_EPSILON ?
w->data.db[w->rows-1]/w->data.db[0] : 0;
CV_CALL( cvSVBkSb( w, u, v ? v : u, 0, dst, CV_SVD_U_T + CV_SVD_V_T ));
EXIT;
}
else if( method != CV_LU )
CV_ERROR( CV_StsBadArg, "Unknown inversion method" );
if( !CV_ARE_TYPES_EQ( src, dst ))
CV_ERROR( CV_StsUnmatchedFormats, "" );
if( src->width != src->height )
CV_ERROR( CV_StsBadSize, "The matrix must be square" );
if( !CV_ARE_SIZES_EQ( src, dst ))
CV_ERROR( CV_StsUnmatchedSizes, "" );
if( type != CV_32FC1 && type != CV_64FC1 )
CV_ERROR( CV_StsUnsupportedFormat, "" );
if( src->width <= 3 )
{
uchar* srcdata = src->data.ptr;
uchar* dstdata = dst->data.ptr;
int srcstep = src->step;
int dststep = dst->step;
if( src->width == 2 )
{
if( type == CV_32FC1 )
{
double d = det2(Sf);
if( d != 0. )
{
double t0, t1;
result = d;
d = 1./d;
t0 = Sf(0,0)*d;
t1 = Sf(1,1)*d;
Df(1,1) = (float)t0;
Df(0,0) = (float)t1;
t0 = -Sf(0,1)*d;
t1 = -Sf(1,0)*d;
Df(0,1) = (float)t0;
Df(1,0) = (float)t1;
}
}
else
{
double d = det2(Sd);
if( d != 0. )
{
double t0, t1;
result = d;
d = 1./d;
t0 = Sd(0,0)*d;
t1 = Sd(1,1)*d;
Dd(1,1) = t0;
Dd(0,0) = t1;
t0 = -Sd(0,1)*d;
t1 = -Sd(1,0)*d;
Dd(0,1) = t0;
Dd(1,0) = t1;
}
}
}
else if( src->width == 3 )
{
if( type == CV_32FC1 )
{
double d = det3(Sf);
if( d != 0. )
{
float t[9];
result = d;
d = 1./d;
t[0] = (float)((Sf(1,1) * Sf(2,2) - Sf(1,2) * Sf(2,1)) * d);
t[1] = (float)((Sf(0,2) * Sf(2,1) - Sf(0,1) * Sf(2,2)) * d);
t[2] = (float)((Sf(0,1) * Sf(1,2) - Sf(0,2) * Sf(1,1)) * d);
t[3] = (float)((Sf(1,2) * Sf(2,0) - Sf(1,0) * Sf(2,2)) * d);
t[4] = (float)((Sf(0,0) * Sf(2,2) - Sf(0,2) * Sf(2,0)) * d);
t[5] = (float)((Sf(0,2) * Sf(1,0) - Sf(0,0) * Sf(1,2)) * d);
t[6] = (float)((Sf(1,0) * Sf(2,1) - Sf(1,1) * Sf(2,0)) * d);
t[7] = (float)((Sf(0,1) * Sf(2,0) - Sf(0,0) * Sf(2,1)) * d);
t[8] = (float)((Sf(0,0) * Sf(1,1) - Sf(0,1) * Sf(1,0)) * d);
Df(0,0) = t[0]; Df(0,1) = t[1]; Df(0,2) = t[2];
Df(1,0) = t[3]; Df(1,1) = t[4]; Df(1,2) = t[5];
Df(2,0) = t[6]; Df(2,1) = t[7]; Df(2,2) = t[8];
}
}
else
{
double d = det3(Sd);
if( d != 0. )
{
double t[9];
result = d;
d = 1./d;
t[0] = (Sd(1,1) * Sd(2,2) - Sd(1,2) * Sd(2,1)) * d;
t[1] = (Sd(0,2) * Sd(2,1) - Sd(0,1) * Sd(2,2)) * d;
t[2] = (Sd(0,1) * Sd(1,2) - Sd(0,2) * Sd(1,1)) * d;
t[3] = (Sd(1,2) * Sd(2,0) - Sd(1,0) * Sd(2,2)) * d;
t[4] = (Sd(0,0) * Sd(2,2) - Sd(0,2) * Sd(2,0)) * d;
t[5] = (Sd(0,2) * Sd(1,0) - Sd(0,0) * Sd(1,2)) * d;
t[6] = (Sd(1,0) * Sd(2,1) - Sd(1,1) * Sd(2,0)) * d;
t[7] = (Sd(0,1) * Sd(2,0) - Sd(0,0) * Sd(2,1)) * d;
t[8] = (Sd(0,0) * Sd(1,1) - Sd(0,1) * Sd(1,0)) * d;
Dd(0,0) = t[0]; Dd(0,1) = t[1]; Dd(0,2) = t[2];
Dd(1,0) = t[3]; Dd(1,1) = t[4]; Dd(1,2) = t[5];
Dd(2,0) = t[6]; Dd(2,1) = t[7]; Dd(2,2) = t[8];
}
}
}
else
{
assert( src->width == 1 );
if( type == CV_32FC1 )
{
double d = Sf(0,0);
if( d != 0. )
{
result = d;
Df(0,0) = (float)(1./d);
}
}
else
{
double d = Sd(0,0);
if( d != 0. )
{
result = d;
Dd(0,0) = 1./d;
}
}
}
}
else
{
CvLUDecompFunc decomp_func;
CvLUBackFunc back_func;
CvSize size = cvGetMatSize( src );
const int worktype = CV_64FC1;
int buf_size = size.width*size.height*CV_ELEM_SIZE(worktype);
CvMat tmat;
if( !lu_inittab )
{
icvInitLUTable( &lu_decomp_tab, &lu_back_tab );
lu_inittab = 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -