3430 lines
99 KiB
C++
3430 lines
99 KiB
C++
/*M///////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
|
//
|
|
// By downloading, copying, installing or using the software you agree to this license.
|
|
// If you do not agree to this license, do not download, install,
|
|
// copy or use the software.
|
|
//
|
|
//
|
|
// Intel License Agreement
|
|
// For Open Source Computer Vision Library
|
|
//
|
|
// Copyright (C) 2000, Intel Corporation, all rights reserved.
|
|
// Third party copyrights are property of their respective owners.
|
|
//
|
|
// Redistribution and use in source and binary forms, with or without modification,
|
|
// are permitted provided that the following conditions are met:
|
|
//
|
|
// * Redistribution's of source code must retain the above copyright notice,
|
|
// this list of conditions and the following disclaimer.
|
|
//
|
|
// * Redistribution's in binary form must reproduce the above copyright notice,
|
|
// this list of conditions and the following disclaimer in the documentation
|
|
// and/or other materials provided with the distribution.
|
|
//
|
|
// * The name of Intel Corporation may not be used to endorse or promote products
|
|
// derived from this software without specific prior written permission.
|
|
//
|
|
// This software is provided by the copyright holders and contributors "as is" and
|
|
// any express or implied warranties, including, but not limited to, the implied
|
|
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
|
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
|
// indirect, incidental, special, exemplary, or consequential damages
|
|
// (including, but not limited to, procurement of substitute goods or services;
|
|
// loss of use, data, or profits; or business interruption) however caused
|
|
// and on any theory of liability, whether in contract, strict liability,
|
|
// or tort (including negligence or otherwise) arising in any way out of
|
|
// the use of this software, even if advised of the possibility of such damage.
|
|
//
|
|
//M*/
|
|
|
|
#include "_cxts.h"
|
|
|
|
/****************************************************************************************\
|
|
* Utility Functions *
|
|
\****************************************************************************************/
|
|
|
|
const char* cvTsGetTypeName( int type )
|
|
{
|
|
static const char* type_names[] = { "8u", "8s", "16u", "16s", "32s", "32f", "64f", "ptr" };
|
|
return type_names[CV_MAT_DEPTH(type)];
|
|
}
|
|
|
|
|
|
int cvTsTypeByName( const char* name )
|
|
{
|
|
int i;
|
|
for( i = 0; i < CV_DEPTH_MAX; i++ )
|
|
if( strcmp(name, cvTsGetTypeName(i)) == 0 )
|
|
return i;
|
|
return -1;
|
|
}
|
|
|
|
|
|
void cvTsRandUni( CvRNG* rng, CvMat* a, CvScalar param0, CvScalar param1 )
|
|
{
|
|
int i, j, k, cn, ncols;
|
|
CvScalar scale = param0;
|
|
CvScalar delta = param1;
|
|
double C = 1./(65536.*65536.);
|
|
|
|
cn = CV_MAT_CN(a->type);
|
|
ncols = a->cols*cn;
|
|
|
|
for( k = 0; k < 4; k++ )
|
|
{
|
|
double s = scale.val[k] - delta.val[k];
|
|
if( s >= 0 )
|
|
scale.val[k] = s;
|
|
else
|
|
{
|
|
delta.val[k] = scale.val[k];
|
|
scale.val[k] = -s;
|
|
}
|
|
scale.val[k] *= C;
|
|
}
|
|
|
|
for( i = 0; i < a->rows; i++ )
|
|
{
|
|
uchar* data = a->data.ptr + i*a->step;
|
|
|
|
switch( CV_MAT_DEPTH(a->type) )
|
|
{
|
|
case CV_8U:
|
|
for( j = 0; j < ncols; j += cn )
|
|
for( k = 0; k < cn; k++ )
|
|
{
|
|
int val = cvFloor( cvTsRandInt(rng)*scale.val[k] + delta.val[k] );
|
|
((uchar*)data)[j + k] = CV_CAST_8U(val);
|
|
}
|
|
break;
|
|
case CV_8S:
|
|
for( j = 0; j < ncols; j += cn )
|
|
for( k = 0; k < cn; k++ )
|
|
{
|
|
int val = cvFloor( cvTsRandInt(rng)*scale.val[k] + delta.val[k] );
|
|
((schar*)data)[j + k] = CV_CAST_8S(val);
|
|
}
|
|
break;
|
|
case CV_16U:
|
|
for( j = 0; j < ncols; j += cn )
|
|
for( k = 0; k < cn; k++ )
|
|
{
|
|
int val = cvFloor( cvTsRandInt(rng)*scale.val[k] + delta.val[k] );
|
|
((ushort*)data)[j + k] = CV_CAST_16U(val);
|
|
}
|
|
break;
|
|
case CV_16S:
|
|
for( j = 0; j < ncols; j += cn )
|
|
for( k = 0; k < cn; k++ )
|
|
{
|
|
int val = cvFloor( cvTsRandInt(rng)*scale.val[k] + delta.val[k] );
|
|
((short*)data)[j + k] = CV_CAST_16S(val);
|
|
}
|
|
break;
|
|
case CV_32S:
|
|
for( j = 0; j < ncols; j += cn )
|
|
for( k = 0; k < cn; k++ )
|
|
{
|
|
int val = cvFloor( cvTsRandInt(rng)*scale.val[k] + delta.val[k] );
|
|
((int*)data)[j + k] = val;
|
|
}
|
|
break;
|
|
case CV_32F:
|
|
for( j = 0; j < ncols; j += cn )
|
|
for( k = 0; k < cn; k++ )
|
|
{
|
|
double val = cvTsRandInt(rng)*scale.val[k] + delta.val[k];
|
|
((float*)data)[j + k] = (float)val;
|
|
}
|
|
break;
|
|
case CV_64F:
|
|
for( j = 0; j < ncols; j += cn )
|
|
for( k = 0; k < cn; k++ )
|
|
{
|
|
double val = cvTsRandInt(rng);
|
|
val = (val + cvTsRandInt(rng)*C)*scale.val[k] + delta.val[k];
|
|
((double*)data)[j + k] = val;
|
|
}
|
|
break;
|
|
default:
|
|
assert(0);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void cvTsZero( CvMat* c, const CvMat* mask )
|
|
{
|
|
int i, j, elem_size = CV_ELEM_SIZE(c->type), width = c->cols;
|
|
|
|
for( i = 0; i < c->rows; i++ )
|
|
{
|
|
if( !mask )
|
|
memset( c->data.ptr + i*c->step, 0, width*elem_size );
|
|
else
|
|
{
|
|
const uchar* mrow = mask->data.ptr + mask->step*i;
|
|
uchar* cptr = c->data.ptr + c->step*i;
|
|
for( j = 0; j < width; j++, cptr += elem_size )
|
|
if( mrow[j] )
|
|
memset( cptr, 0, elem_size );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// initializes scaled identity matrix
|
|
void cvTsSetIdentity( CvMat* c, CvScalar diag_value )
|
|
{
|
|
int i, width;
|
|
cvTsZero( c );
|
|
width = MIN(c->rows, c->cols);
|
|
for( i = 0; i < width; i++ )
|
|
cvSet2D( c, i, i, diag_value );
|
|
}
|
|
|
|
|
|
// copies selected region of one array to another array
|
|
void cvTsCopy( const CvMat* a, CvMat* b, const CvMat* mask )
|
|
{
|
|
int i = 0, j = 0, k;
|
|
int el_size, ncols;
|
|
|
|
el_size = CV_ELEM_SIZE(a->type);
|
|
ncols = a->cols;
|
|
if( mask )
|
|
{
|
|
assert( CV_ARE_SIZES_EQ(a,mask) &&
|
|
(CV_MAT_TYPE(mask->type) == CV_8UC1 ||
|
|
CV_MAT_TYPE(mask->type) == CV_8SC1 ));
|
|
}
|
|
|
|
assert( CV_ARE_TYPES_EQ(a,b) && CV_ARE_SIZES_EQ(a,b) );
|
|
|
|
if( !mask )
|
|
ncols *= el_size;
|
|
|
|
for( i = 0; i < a->rows; i++ )
|
|
{
|
|
uchar* a_data = a->data.ptr + a->step*i;
|
|
uchar* b_data = b->data.ptr + b->step*i;
|
|
|
|
if( !mask )
|
|
memcpy( b_data, a_data, ncols );
|
|
else
|
|
{
|
|
uchar* m_data = mask->data.ptr + mask->step*i;
|
|
|
|
for( j = 0; j < ncols; j++, b_data += el_size, a_data += el_size )
|
|
{
|
|
if( m_data[j] )
|
|
{
|
|
for( k = 0; k < el_size; k++ )
|
|
b_data[k] = a_data[k];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void cvTsConvert( const CvMat* a, CvMat* b )
|
|
{
|
|
int i, j, ncols = b->cols*CV_MAT_CN(b->type);
|
|
double* buf = 0;
|
|
|
|
assert( CV_ARE_SIZES_EQ(a,b) && CV_ARE_CNS_EQ(a,b) );
|
|
buf = (double*)cvStackAlloc(ncols*sizeof(buf[0]));
|
|
|
|
for( i = 0; i < b->rows; i++ )
|
|
{
|
|
uchar* a_data = a->data.ptr + i*a->step;
|
|
uchar* b_data = b->data.ptr + i*b->step;
|
|
|
|
switch( CV_MAT_DEPTH(a->type) )
|
|
{
|
|
case CV_8U:
|
|
for( j = 0; j < ncols; j++ )
|
|
buf[j] = ((uchar*)a_data)[j];
|
|
break;
|
|
case CV_8S:
|
|
for( j = 0; j < ncols; j++ )
|
|
buf[j] = ((schar*)a_data)[j];
|
|
break;
|
|
case CV_16U:
|
|
for( j = 0; j < ncols; j++ )
|
|
buf[j] = ((ushort*)a_data)[j];
|
|
break;
|
|
case CV_16S:
|
|
for( j = 0; j < ncols; j++ )
|
|
buf[j] = ((short*)a_data)[j];
|
|
break;
|
|
case CV_32S:
|
|
for( j = 0; j < ncols; j++ )
|
|
buf[j] = ((int*)a_data)[j];
|
|
break;
|
|
case CV_32F:
|
|
for( j = 0; j < ncols; j++ )
|
|
buf[j] = ((float*)a_data)[j];
|
|
break;
|
|
case CV_64F:
|
|
for( j = 0; j < ncols; j++ )
|
|
buf[j] = ((double*)a_data)[j];
|
|
break;
|
|
default:
|
|
assert(0);
|
|
return;
|
|
}
|
|
|
|
switch( CV_MAT_DEPTH(b->type) )
|
|
{
|
|
case CV_8U:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int val = cvRound(buf[j]);
|
|
((uchar*)b_data)[j] = CV_CAST_8U(val);
|
|
}
|
|
break;
|
|
case CV_8S:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int val = cvRound(buf[j]);
|
|
((schar*)b_data)[j] = CV_CAST_8S(val);
|
|
}
|
|
break;
|
|
case CV_16U:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int val = cvRound(buf[j]);
|
|
((ushort*)b_data)[j] = CV_CAST_16U(val);
|
|
}
|
|
break;
|
|
case CV_16S:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int val = cvRound(buf[j]);
|
|
((short*)b_data)[j] = CV_CAST_16S(val);
|
|
}
|
|
break;
|
|
case CV_32S:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int val = cvRound(buf[j]);
|
|
((int*)b_data)[j] = CV_CAST_32S(val);
|
|
}
|
|
break;
|
|
case CV_32F:
|
|
for( j = 0; j < ncols; j++ )
|
|
((float*)b_data)[j] = CV_CAST_32F(buf[j]);
|
|
break;
|
|
case CV_64F:
|
|
for( j = 0; j < ncols; j++ )
|
|
((double*)b_data)[j] = CV_CAST_64F(buf[j]);
|
|
break;
|
|
default:
|
|
assert(0);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// extracts a single channel from a multi-channel array
|
|
void cvTsExtract( const CvMat* a, CvMat* b, int coi )
|
|
{
|
|
int i = 0, j = 0, k;
|
|
int el_size, el_size1, ncols;
|
|
|
|
el_size = CV_ELEM_SIZE(a->type);
|
|
el_size1 = CV_ELEM_SIZE(b->type);
|
|
ncols = a->cols;
|
|
|
|
assert( CV_ARE_DEPTHS_EQ(a,b) && CV_ARE_SIZES_EQ(a,b) &&
|
|
(unsigned)coi < (unsigned)CV_MAT_CN(a->type) &&
|
|
CV_MAT_CN(b->type) == 1 );
|
|
|
|
for( i = 0; i < a->rows; i++ )
|
|
{
|
|
uchar* a_data = a->data.ptr + a->step*i;
|
|
uchar* b_data = b->data.ptr + b->step*i;
|
|
a_data += el_size1*coi;
|
|
for( j = 0; j < ncols; j++, b_data += el_size1, a_data += el_size )
|
|
{
|
|
for( k = 0; k < el_size1; k++ )
|
|
b_data[k] = a_data[k];
|
|
}
|
|
}
|
|
}
|
|
|
|
// replaces a single channel in a multi-channel array
|
|
void cvTsInsert( const CvMat* a, CvMat* b, int coi )
|
|
{
|
|
int i = 0, j = 0, k;
|
|
int el_size, el_size1, ncols;
|
|
|
|
el_size = CV_ELEM_SIZE(b->type);
|
|
el_size1 = CV_ELEM_SIZE(a->type);
|
|
ncols = a->cols;
|
|
|
|
assert( CV_ARE_DEPTHS_EQ(a,b) && CV_ARE_SIZES_EQ(a,b) &&
|
|
(unsigned)coi < (unsigned)CV_MAT_CN(b->type) &&
|
|
CV_MAT_CN(a->type) == 1 );
|
|
|
|
for( i = 0; i < a->rows; i++ )
|
|
{
|
|
uchar* a_data = a->data.ptr + a->step*i;
|
|
uchar* b_data = b->data.ptr + b->step*i;
|
|
b_data += el_size1*coi;
|
|
for( j = 0; j < ncols; j++, b_data += el_size, a_data += el_size1 )
|
|
{
|
|
for( k = 0; k < el_size1; k++ )
|
|
b_data[k] = a_data[k];
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// c = alpha*a + beta*b + gamma
|
|
void cvTsAdd( const CvMat* a, CvScalar alpha, const CvMat* b, CvScalar beta,
|
|
CvScalar gamma, CvMat* c, int calc_abs )
|
|
{
|
|
int i, j, k, cn, ncols;
|
|
double* buf = 0;
|
|
double* alpha_buf = 0;
|
|
double* beta_buf = 0;
|
|
double* gamma_buf = 0;
|
|
|
|
if( !c )
|
|
{
|
|
assert(0);
|
|
return;
|
|
}
|
|
|
|
cn = CV_MAT_CN(c->type);
|
|
ncols = c->cols;
|
|
|
|
if( !a )
|
|
{
|
|
a = b;
|
|
alpha = beta;
|
|
b = 0;
|
|
beta = cvScalar(0);
|
|
}
|
|
|
|
if( a )
|
|
{
|
|
assert( CV_ARE_SIZES_EQ(a,c) && CV_MAT_CN(a->type) == cn );
|
|
buf = (double*)malloc( a->cols * cn * sizeof(buf[0]) );
|
|
alpha_buf = (double*)malloc( a->cols * cn * sizeof(alpha_buf[0]) );
|
|
}
|
|
|
|
if( b )
|
|
{
|
|
assert( CV_ARE_SIZES_EQ(b,c) && CV_MAT_CN(b->type) == cn );
|
|
beta_buf = (double*)malloc( b->cols * cn * sizeof(beta_buf[0]) );
|
|
}
|
|
|
|
ncols *= cn;
|
|
gamma_buf = (double*)malloc( ncols * sizeof(gamma_buf[0]) );
|
|
if( !buf )
|
|
buf = gamma_buf;
|
|
|
|
if( !a && !b && calc_abs )
|
|
{
|
|
for( k = 0; k < cn; k++ )
|
|
gamma.val[k] = fabs(gamma.val[k]);
|
|
}
|
|
|
|
for( i = 0; i < 1 + (a != 0) + (b != 0); i++ )
|
|
{
|
|
double* scalar_buf = i == 0 ? gamma_buf : i == 1 ? alpha_buf : beta_buf;
|
|
CvScalar scalar = i == 0 ? gamma : i == 1 ? alpha : beta;
|
|
for( j = 0; j < ncols; j += cn )
|
|
for( k = 0; k < cn; k++ )
|
|
scalar_buf[j + k] = scalar.val[k];
|
|
}
|
|
|
|
for( i = 0; i < c->rows; i++ )
|
|
{
|
|
uchar* c_data = c->data.ptr + i*c->step;
|
|
|
|
if( a )
|
|
{
|
|
uchar* a_data = a->data.ptr + i*a->step;
|
|
|
|
switch( CV_MAT_DEPTH(a->type) )
|
|
{
|
|
case CV_8U:
|
|
for( j = 0; j < ncols; j++ )
|
|
buf[j] = ((uchar*)a_data)[j]*alpha_buf[j] + gamma_buf[j];
|
|
break;
|
|
case CV_8S:
|
|
for( j = 0; j < ncols; j++ )
|
|
buf[j] = ((schar*)a_data)[j]*alpha_buf[j] + gamma_buf[j];
|
|
break;
|
|
case CV_16U:
|
|
for( j = 0; j < ncols; j++ )
|
|
buf[j] = ((ushort*)a_data)[j]*alpha_buf[j] + gamma_buf[j];
|
|
break;
|
|
case CV_16S:
|
|
for( j = 0; j < ncols; j++ )
|
|
buf[j] = ((short*)a_data)[j]*alpha_buf[j] + gamma_buf[j];
|
|
break;
|
|
case CV_32S:
|
|
for( j = 0; j < ncols; j++ )
|
|
buf[j] = ((int*)a_data)[j]*alpha_buf[j] + gamma_buf[j];
|
|
break;
|
|
case CV_32F:
|
|
for( j = 0; j < ncols; j++ )
|
|
buf[j] = ((float*)a_data)[j]*alpha_buf[j] + gamma_buf[j];
|
|
break;
|
|
case CV_64F:
|
|
for( j = 0; j < ncols; j++ )
|
|
buf[j] = ((double*)a_data)[j]*alpha_buf[j] + gamma_buf[j];
|
|
break;
|
|
default:
|
|
assert(0);
|
|
return;
|
|
}
|
|
}
|
|
|
|
if( b )
|
|
{
|
|
uchar* b_data = b->data.ptr + i*b->step;
|
|
|
|
switch( CV_MAT_DEPTH(b->type) )
|
|
{
|
|
case CV_8U:
|
|
for( j = 0; j < ncols; j++ )
|
|
buf[j] += ((uchar*)b_data)[j]*beta_buf[j];
|
|
break;
|
|
case CV_8S:
|
|
for( j = 0; j < ncols; j++ )
|
|
buf[j] += ((schar*)b_data)[j]*beta_buf[j];
|
|
break;
|
|
case CV_16U:
|
|
for( j = 0; j < ncols; j++ )
|
|
buf[j] += ((ushort*)b_data)[j]*beta_buf[j];
|
|
break;
|
|
case CV_16S:
|
|
for( j = 0; j < ncols; j++ )
|
|
buf[j] += ((short*)b_data)[j]*beta_buf[j];
|
|
break;
|
|
case CV_32S:
|
|
for( j = 0; j < ncols; j++ )
|
|
buf[j] += ((int*)b_data)[j]*beta_buf[j];
|
|
break;
|
|
case CV_32F:
|
|
for( j = 0; j < ncols; j++ )
|
|
buf[j] += ((float*)b_data)[j]*beta_buf[j];
|
|
break;
|
|
case CV_64F:
|
|
for( j = 0; j < ncols; j++ )
|
|
buf[j] += ((double*)b_data)[j]*beta_buf[j];
|
|
break;
|
|
default:
|
|
assert(0);
|
|
return;
|
|
}
|
|
}
|
|
|
|
if( a || b )
|
|
{
|
|
if( calc_abs )
|
|
{
|
|
for( j = 0; j < ncols; j++ )
|
|
buf[j] = fabs(buf[j]);
|
|
}
|
|
}
|
|
else if( i > 0 )
|
|
{
|
|
memcpy( c_data, c_data - c->step, c->cols*CV_ELEM_SIZE(c->type) );
|
|
continue;
|
|
}
|
|
|
|
switch( CV_MAT_DEPTH(c->type) )
|
|
{
|
|
case CV_8U:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int val = cvRound(buf[j]);
|
|
((uchar*)c_data)[j] = CV_CAST_8U(val);
|
|
}
|
|
break;
|
|
case CV_8S:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int val = cvRound(buf[j]);
|
|
((schar*)c_data)[j] = CV_CAST_8S(val);
|
|
}
|
|
break;
|
|
case CV_16U:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int val = cvRound(buf[j]);
|
|
((ushort*)c_data)[j] = CV_CAST_16U(val);
|
|
}
|
|
break;
|
|
case CV_16S:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int val = cvRound(buf[j]);
|
|
((short*)c_data)[j] = CV_CAST_16S(val);
|
|
}
|
|
break;
|
|
case CV_32S:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int val = cvRound(buf[j]);
|
|
((int*)c_data)[j] = CV_CAST_32S(val);
|
|
}
|
|
break;
|
|
case CV_32F:
|
|
for( j = 0; j < ncols; j++ )
|
|
((float*)c_data)[j] = CV_CAST_32F(buf[j]);
|
|
break;
|
|
case CV_64F:
|
|
for( j = 0; j < ncols; j++ )
|
|
((double*)c_data)[j] = CV_CAST_64F(buf[j]);
|
|
break;
|
|
default:
|
|
assert(0);
|
|
}
|
|
}
|
|
|
|
if( buf && buf != gamma_buf )
|
|
free( buf );
|
|
if( gamma_buf )
|
|
free( gamma_buf );
|
|
if( alpha_buf )
|
|
free( alpha_buf );
|
|
if( beta_buf )
|
|
free( beta_buf );
|
|
}
|
|
|
|
|
|
// c = a*b*alpha
|
|
void cvTsMul( const CvMat* a, const CvMat* b, CvScalar alpha, CvMat* c )
|
|
{
|
|
int i, j, k, cn, ncols;
|
|
double* buf = 0;
|
|
double* alpha_buf = 0;
|
|
|
|
if( !a || !b || !c )
|
|
{
|
|
assert(0);
|
|
return;
|
|
}
|
|
|
|
assert( CV_ARE_SIZES_EQ(a,c) && CV_ARE_SIZES_EQ(b,c) &&
|
|
CV_ARE_TYPES_EQ(a,b) && CV_ARE_CNS_EQ(a,c) );
|
|
|
|
cn = CV_MAT_CN(c->type);
|
|
ncols = c->cols * cn;
|
|
alpha_buf = (double*)malloc( ncols * sizeof(alpha_buf[0]) );
|
|
buf = (double*)malloc( ncols * sizeof(buf[0]) );
|
|
|
|
for( j = 0; j < ncols; j += cn )
|
|
for( k = 0; k < cn; k++ )
|
|
alpha_buf[j + k] = alpha.val[k];
|
|
|
|
for( i = 0; i < c->rows; i++ )
|
|
{
|
|
uchar* c_data = c->data.ptr + i*c->step;
|
|
uchar* a_data = a->data.ptr + i*a->step;
|
|
uchar* b_data = b->data.ptr + i*b->step;
|
|
|
|
switch( CV_MAT_DEPTH(a->type) )
|
|
{
|
|
case CV_8U:
|
|
for( j = 0; j < ncols; j++ )
|
|
buf[j] = (alpha_buf[j]*((uchar*)a_data)[j])*((uchar*)b_data)[j];
|
|
break;
|
|
case CV_8S:
|
|
for( j = 0; j < ncols; j++ )
|
|
buf[j] = (alpha_buf[j]*((schar*)a_data)[j])*((schar*)b_data)[j];
|
|
break;
|
|
case CV_16U:
|
|
for( j = 0; j < ncols; j++ )
|
|
buf[j] = (alpha_buf[j]*((ushort*)a_data)[j])*((ushort*)b_data)[j];
|
|
break;
|
|
case CV_16S:
|
|
for( j = 0; j < ncols; j++ )
|
|
buf[j] = (alpha_buf[j]*((short*)a_data)[j])*((short*)b_data)[j];
|
|
break;
|
|
case CV_32S:
|
|
for( j = 0; j < ncols; j++ )
|
|
buf[j] = (alpha_buf[j]*((int*)a_data)[j])*((int*)b_data)[j];
|
|
break;
|
|
case CV_32F:
|
|
for( j = 0; j < ncols; j++ )
|
|
buf[j] = (alpha_buf[j]*((float*)a_data)[j])*((float*)b_data)[j];
|
|
break;
|
|
case CV_64F:
|
|
for( j = 0; j < ncols; j++ )
|
|
buf[j] = (alpha_buf[j]*((double*)a_data)[j])*((double*)b_data)[j];
|
|
break;
|
|
default:
|
|
assert(0);
|
|
return;
|
|
}
|
|
|
|
switch( CV_MAT_DEPTH(c->type) )
|
|
{
|
|
case CV_8U:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int val = cvRound(buf[j]);
|
|
((uchar*)c_data)[j] = CV_CAST_8U(val);
|
|
}
|
|
break;
|
|
case CV_8S:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int val = cvRound(buf[j]);
|
|
((schar*)c_data)[j] = CV_CAST_8S(val);
|
|
}
|
|
break;
|
|
case CV_16U:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int val = cvRound(buf[j]);
|
|
((ushort*)c_data)[j] = CV_CAST_16U(val);
|
|
}
|
|
break;
|
|
case CV_16S:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int val = cvRound(buf[j]);
|
|
((short*)c_data)[j] = CV_CAST_16S(val);
|
|
}
|
|
break;
|
|
case CV_32S:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int val = cvRound(buf[j]);
|
|
((int*)c_data)[j] = CV_CAST_32S(val);
|
|
}
|
|
break;
|
|
case CV_32F:
|
|
for( j = 0; j < ncols; j++ )
|
|
((float*)c_data)[j] = CV_CAST_32F(buf[j]);
|
|
break;
|
|
case CV_64F:
|
|
for( j = 0; j < ncols; j++ )
|
|
((double*)c_data)[j] = CV_CAST_64F(buf[j]);
|
|
break;
|
|
default:
|
|
assert(0);
|
|
}
|
|
}
|
|
|
|
if( alpha_buf )
|
|
free( alpha_buf );
|
|
|
|
if( buf )
|
|
free( buf );
|
|
}
|
|
|
|
|
|
// c = a*alpha/b
|
|
void cvTsDiv( const CvMat* a, const CvMat* b, CvScalar alpha, CvMat* c )
|
|
{
|
|
int i, j, k, cn, ncols;
|
|
double* buf = 0;
|
|
double* alpha_buf = 0;
|
|
|
|
if( !b || !c )
|
|
{
|
|
assert(0);
|
|
return;
|
|
}
|
|
|
|
if( a )
|
|
{
|
|
assert( CV_ARE_SIZES_EQ(a,c) &&
|
|
CV_ARE_TYPES_EQ(a,b) && CV_ARE_CNS_EQ(a,c) );
|
|
}
|
|
|
|
assert( CV_ARE_SIZES_EQ(b,c) && CV_ARE_CNS_EQ(b,c) );
|
|
|
|
cn = CV_MAT_CN(c->type);
|
|
ncols = c->cols * cn;
|
|
alpha_buf = (double*)malloc( ncols * sizeof(alpha_buf[0]) );
|
|
buf = (double*)malloc( ncols * sizeof(buf[0]) );
|
|
|
|
for( j = 0; j < ncols; j += cn )
|
|
for( k = 0; k < cn; k++ )
|
|
alpha_buf[j + k] = alpha.val[k];
|
|
|
|
for( i = 0; i < c->rows; i++ )
|
|
{
|
|
uchar* c_data = c->data.ptr + i*c->step;
|
|
uchar* a_data = a ? a->data.ptr + i*a->step : 0;
|
|
uchar* b_data = b->data.ptr + i*b->step;
|
|
|
|
switch( CV_MAT_DEPTH(b->type) )
|
|
{
|
|
case CV_8U:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int denom = ((uchar*)b_data)[j];
|
|
int num = a_data ? ((uchar*)a_data)[j] : 1;
|
|
buf[j] = !denom ? 0 : (alpha_buf[j]*num/denom);
|
|
}
|
|
break;
|
|
case CV_8S:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int denom = ((schar*)b_data)[j];
|
|
int num = a_data ? ((schar*)a_data)[j] : 1;
|
|
buf[j] = !denom ? 0 : (alpha_buf[j]*num/denom);
|
|
}
|
|
break;
|
|
case CV_16U:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int denom = ((ushort*)b_data)[j];
|
|
int num = a_data ? ((ushort*)a_data)[j] : 1;
|
|
buf[j] = !denom ? 0 : (alpha_buf[j]*num/denom);
|
|
}
|
|
break;
|
|
case CV_16S:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int denom = ((short*)b_data)[j];
|
|
int num = a_data ? ((short*)a_data)[j] : 1;
|
|
buf[j] = !denom ? 0 : (alpha_buf[j]*num/denom);
|
|
}
|
|
break;
|
|
case CV_32S:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int denom = ((int*)b_data)[j];
|
|
int num = a_data ? ((int*)a_data)[j] : 1;
|
|
buf[j] = !denom ? 0 : (alpha_buf[j]*num/denom);
|
|
}
|
|
break;
|
|
case CV_32F:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
double denom = ((float*)b_data)[j];
|
|
double num = a_data ? ((float*)a_data)[j] : 1;
|
|
buf[j] = !denom ? 0 : (alpha_buf[j]*num/denom);
|
|
}
|
|
break;
|
|
case CV_64F:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
double denom = ((double*)b_data)[j];
|
|
double num = a_data ? ((double*)a_data)[j] : 1;
|
|
buf[j] = !denom ? 0 : (alpha_buf[j]*num/denom);
|
|
}
|
|
break;
|
|
default:
|
|
assert(0);
|
|
return;
|
|
}
|
|
|
|
switch( CV_MAT_DEPTH(c->type) )
|
|
{
|
|
case CV_8U:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int val = cvRound(buf[j]);
|
|
((uchar*)c_data)[j] = CV_CAST_8U(val);
|
|
}
|
|
break;
|
|
case CV_8S:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int val = cvRound(buf[j]);
|
|
((schar*)c_data)[j] = CV_CAST_8S(val);
|
|
}
|
|
break;
|
|
case CV_16U:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int val = cvRound(buf[j]);
|
|
((ushort*)c_data)[j] = CV_CAST_16U(val);
|
|
}
|
|
break;
|
|
case CV_16S:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int val = cvRound(buf[j]);
|
|
((short*)c_data)[j] = CV_CAST_16S(val);
|
|
}
|
|
break;
|
|
case CV_32S:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int val = cvRound(buf[j]);
|
|
((int*)c_data)[j] = CV_CAST_32S(val);
|
|
}
|
|
break;
|
|
case CV_32F:
|
|
for( j = 0; j < ncols; j++ )
|
|
((float*)c_data)[j] = CV_CAST_32F(buf[j]);
|
|
break;
|
|
case CV_64F:
|
|
for( j = 0; j < ncols; j++ )
|
|
((double*)c_data)[j] = CV_CAST_64F(buf[j]);
|
|
break;
|
|
default:
|
|
assert(0);
|
|
}
|
|
}
|
|
|
|
if( alpha_buf )
|
|
free( alpha_buf );
|
|
|
|
if( buf )
|
|
free( buf );
|
|
}
|
|
|
|
|
|
// c = min(a,b) or c = max(a,b)
|
|
void cvTsMinMax( const CvMat* a, const CvMat* b, CvMat* c, int op_type )
|
|
{
|
|
int i, j, ncols;
|
|
int calc_max = op_type == CV_TS_MAX;
|
|
|
|
if( !a || !b || !c )
|
|
{
|
|
assert(0);
|
|
return;
|
|
}
|
|
|
|
assert( CV_ARE_SIZES_EQ(a,c) && CV_ARE_TYPES_EQ(a,c) &&
|
|
CV_ARE_SIZES_EQ(b,c) && CV_ARE_TYPES_EQ(b,c) &&
|
|
CV_MAT_CN(a->type) == 1 );
|
|
ncols = c->cols;
|
|
|
|
for( i = 0; i < c->rows; i++ )
|
|
{
|
|
uchar* c_data = c->data.ptr + i*c->step;
|
|
uchar* a_data = a->data.ptr + i*a->step;
|
|
uchar* b_data = b->data.ptr + i*b->step;
|
|
|
|
switch( CV_MAT_DEPTH(a->type) )
|
|
{
|
|
case CV_8U:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int aj = ((uchar*)a_data)[j];
|
|
int bj = ((uchar*)b_data)[j];
|
|
((uchar*)c_data)[j] = (uchar)(calc_max ? MAX(aj, bj) : MIN(aj,bj));
|
|
}
|
|
break;
|
|
case CV_8S:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int aj = ((schar*)a_data)[j];
|
|
int bj = ((schar*)b_data)[j];
|
|
((schar*)c_data)[j] = (schar)(calc_max ? MAX(aj, bj) : MIN(aj,bj));
|
|
}
|
|
break;
|
|
case CV_16U:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int aj = ((ushort*)a_data)[j];
|
|
int bj = ((ushort*)b_data)[j];
|
|
((ushort*)c_data)[j] = (ushort)(calc_max ? MAX(aj, bj) : MIN(aj,bj));
|
|
}
|
|
break;
|
|
case CV_16S:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int aj = ((short*)a_data)[j];
|
|
int bj = ((short*)b_data)[j];
|
|
((short*)c_data)[j] = (short)(calc_max ? MAX(aj, bj) : MIN(aj,bj));
|
|
}
|
|
break;
|
|
case CV_32S:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int aj = ((int*)a_data)[j];
|
|
int bj = ((int*)b_data)[j];
|
|
((int*)c_data)[j] = calc_max ? MAX(aj, bj) : MIN(aj,bj);
|
|
}
|
|
break;
|
|
case CV_32F:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
float aj = ((float*)a_data)[j];
|
|
float bj = ((float*)b_data)[j];
|
|
((float*)c_data)[j] = calc_max ? MAX(aj, bj) : MIN(aj,bj);
|
|
}
|
|
break;
|
|
case CV_64F:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
double aj = ((double*)a_data)[j];
|
|
double bj = ((double*)b_data)[j];
|
|
((double*)c_data)[j] = calc_max ? MAX(aj, bj) : MIN(aj,bj);
|
|
}
|
|
break;
|
|
default:
|
|
assert(0);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
// c = min(a,b) or c = max(a,b)
|
|
void cvTsMinMaxS( const CvMat* a, double s, CvMat* c, int op_type )
|
|
{
|
|
int i, j, ncols;
|
|
int calc_max = op_type == CV_TS_MAX;
|
|
float fs = (float)s;
|
|
int is = cvRound(s);
|
|
|
|
if( !a || !c )
|
|
{
|
|
assert(0);
|
|
return;
|
|
}
|
|
|
|
assert( CV_ARE_SIZES_EQ(a,c) && CV_ARE_TYPES_EQ(a,c) &&
|
|
CV_MAT_CN(a->type) == 1 );
|
|
ncols = c->cols;
|
|
|
|
switch( CV_MAT_DEPTH(a->type) )
|
|
{
|
|
case CV_8U:
|
|
is = CV_CAST_8U(is);
|
|
break;
|
|
case CV_8S:
|
|
is = CV_CAST_8S(is);
|
|
break;
|
|
case CV_16U:
|
|
is = CV_CAST_16U(is);
|
|
break;
|
|
case CV_16S:
|
|
is = CV_CAST_16S(is);
|
|
break;
|
|
default:
|
|
;
|
|
}
|
|
|
|
for( i = 0; i < c->rows; i++ )
|
|
{
|
|
uchar* c_data = c->data.ptr + i*c->step;
|
|
uchar* a_data = a->data.ptr + i*a->step;
|
|
|
|
switch( CV_MAT_DEPTH(a->type) )
|
|
{
|
|
case CV_8U:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int aj = ((uchar*)a_data)[j];
|
|
((uchar*)c_data)[j] = (uchar)(calc_max ? MAX(aj, is) : MIN(aj, is));
|
|
}
|
|
break;
|
|
case CV_8S:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int aj = ((schar*)a_data)[j];
|
|
((schar*)c_data)[j] = (schar)(calc_max ? MAX(aj, is) : MIN(aj, is));
|
|
}
|
|
break;
|
|
case CV_16U:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int aj = ((ushort*)a_data)[j];
|
|
((ushort*)c_data)[j] = (ushort)(calc_max ? MAX(aj, is) : MIN(aj, is));
|
|
}
|
|
break;
|
|
case CV_16S:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int aj = ((short*)a_data)[j];
|
|
((short*)c_data)[j] = (short)(calc_max ? MAX(aj, is) : MIN(aj, is));
|
|
}
|
|
break;
|
|
case CV_32S:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int aj = ((int*)a_data)[j];
|
|
((int*)c_data)[j] = calc_max ? MAX(aj, is) : MIN(aj, is);
|
|
}
|
|
break;
|
|
case CV_32F:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
float aj = ((float*)a_data)[j];
|
|
((float*)c_data)[j] = calc_max ? MAX(aj, fs) : MIN(aj, fs);
|
|
}
|
|
break;
|
|
case CV_64F:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
double aj = ((double*)a_data)[j];
|
|
((double*)c_data)[j] = calc_max ? MAX(aj, s) : MIN(aj, s);
|
|
}
|
|
break;
|
|
default:
|
|
assert(0);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
// checks that the array does not have NaNs and/or Infs and all the elements are
|
|
// within [min_val,max_val). idx is the index of the first "bad" element.
|
|
int cvTsCheck( const CvMat* a, double min_val, double max_val, CvPoint* idx )
|
|
{
|
|
int i = 0, j = 0;
|
|
int cn, ncols;
|
|
int imin = 0, imax = 0;
|
|
cn = CV_MAT_CN(a->type);
|
|
ncols = a->cols*cn;
|
|
|
|
if( CV_MAT_DEPTH(a->type) <= CV_32S )
|
|
{
|
|
imin = cvCeil(min_val);
|
|
imax = cvFloor(max_val);
|
|
}
|
|
|
|
for( i = 0; i < a->rows; i++ )
|
|
{
|
|
uchar* data = a->data.ptr + a->step*i;
|
|
|
|
switch( CV_MAT_DEPTH(a->type) )
|
|
{
|
|
case CV_8U:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int val = ((uchar*)data)[j];
|
|
if( val < imin || imax < val )
|
|
goto _exit_;
|
|
}
|
|
break;
|
|
case CV_8S:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int val = ((schar*)data)[j];
|
|
if( val < imin || imax < val )
|
|
goto _exit_;
|
|
}
|
|
break;
|
|
case CV_16U:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int val = ((ushort*)data)[j];
|
|
if( val < imin || imax < val )
|
|
goto _exit_;
|
|
}
|
|
break;
|
|
case CV_16S:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int val = ((short*)data)[j];
|
|
if( val < imin || imax < val )
|
|
goto _exit_;
|
|
}
|
|
break;
|
|
case CV_32S:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int val = ((int*)data)[j];
|
|
if( val < imin || imax < val )
|
|
goto _exit_;
|
|
}
|
|
break;
|
|
case CV_32F:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
double val = ((float*)data)[j];
|
|
if( cvIsNaN(val) || cvIsInf(val) || val < min_val || max_val < val )
|
|
goto _exit_;
|
|
}
|
|
break;
|
|
case CV_64F:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
double val = ((double*)data)[j];
|
|
if( cvIsNaN(val) || cvIsInf(val) || val < min_val || max_val < val )
|
|
goto _exit_;
|
|
}
|
|
break;
|
|
default:
|
|
assert(0);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
_exit_:
|
|
|
|
idx->x = j;
|
|
idx->y = i;
|
|
return -1;
|
|
}
|
|
|
|
// compares two arrays. max_diff is the maximum actual difference,
|
|
// success_err_level is maximum allowed difference, idx is the index of the first
|
|
// element for which difference is >success_err_level
|
|
// (or index of element with the maximum difference)
|
|
int cvTsCmpEps( const CvMat* check_arr, const CvMat* etalon, double* _max_diff,
|
|
double success_err_level, CvPoint* _idx, bool element_wise_relative_error )
|
|
{
|
|
int i = 0, j = 0;
|
|
int cn, ncols;
|
|
double maxdiff = 0;
|
|
double maxval = 0;
|
|
int imaxdiff = 0;
|
|
int ilevel = 0;
|
|
int result = -1;
|
|
CvPoint stub, *idx = _idx ? _idx : &stub;
|
|
|
|
cn = CV_MAT_CN(check_arr->type);
|
|
ncols = check_arr->cols*cn;
|
|
|
|
*idx = cvPoint(0,0);
|
|
|
|
assert( CV_ARE_TYPES_EQ(check_arr,etalon) && CV_ARE_SIZES_EQ(check_arr,etalon) );
|
|
|
|
if( CV_MAT_DEPTH(check_arr->type) < CV_32S )
|
|
ilevel = cvFloor(success_err_level);
|
|
|
|
if( CV_MAT_DEPTH(check_arr->type) >= CV_32F && !element_wise_relative_error )
|
|
{
|
|
double maxval0 = 1.;
|
|
maxval = cvTsNorm( etalon, 0, CV_C, 0 );
|
|
maxval = MAX(maxval, maxval0);
|
|
}
|
|
|
|
for( i = 0; i < check_arr->rows; i++ )
|
|
{
|
|
uchar* a_data = check_arr->data.ptr + check_arr->step*i;
|
|
uchar* b_data = etalon->data.ptr + etalon->step*i;
|
|
|
|
switch( CV_MAT_DEPTH(check_arr->type) )
|
|
{
|
|
case CV_8U:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int val = abs(((uchar*)a_data)[j] - ((uchar*)b_data)[j]);
|
|
if( val > imaxdiff )
|
|
{
|
|
imaxdiff = val;
|
|
*idx = cvPoint(j,i);
|
|
if( val > ilevel )
|
|
goto _exit_;
|
|
}
|
|
}
|
|
break;
|
|
case CV_8S:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int val = abs(((schar*)a_data)[j] - ((schar*)b_data)[j]);
|
|
if( val > imaxdiff )
|
|
{
|
|
imaxdiff = val;
|
|
*idx = cvPoint(j,i);
|
|
if( val > ilevel )
|
|
goto _exit_;
|
|
}
|
|
}
|
|
break;
|
|
case CV_16U:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int val = abs(((ushort*)a_data)[j] - ((ushort*)b_data)[j]);
|
|
if( val > imaxdiff )
|
|
{
|
|
imaxdiff = val;
|
|
*idx = cvPoint(j,i);
|
|
if( val > ilevel )
|
|
goto _exit_;
|
|
}
|
|
}
|
|
break;
|
|
case CV_16S:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int val = abs(((short*)a_data)[j] - ((short*)b_data)[j]);
|
|
if( val > imaxdiff )
|
|
{
|
|
imaxdiff = val;
|
|
*idx = cvPoint(j,i);
|
|
if( val > ilevel )
|
|
goto _exit_;
|
|
}
|
|
}
|
|
break;
|
|
case CV_32S:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
double val = fabs((double)((int*)a_data)[j] - (double)((int*)b_data)[j]);
|
|
if( val > maxdiff )
|
|
{
|
|
maxdiff = val;
|
|
*idx = cvPoint(j,i);
|
|
if( val > success_err_level )
|
|
goto _exit_;
|
|
}
|
|
}
|
|
break;
|
|
case CV_32F:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
double a_val = ((float*)a_data)[j];
|
|
double b_val = ((float*)b_data)[j];
|
|
double threshold;
|
|
if( ((int*)a_data)[j] == ((int*)b_data)[j] )
|
|
continue;
|
|
if( cvIsNaN(a_val) || cvIsInf(a_val) )
|
|
{
|
|
result = -2;
|
|
*idx = cvPoint(j,i);
|
|
goto _exit_;
|
|
}
|
|
if( cvIsNaN(b_val) || cvIsInf(b_val) )
|
|
{
|
|
result = -3;
|
|
*idx = cvPoint(j,i);
|
|
goto _exit_;
|
|
}
|
|
a_val = fabs(a_val - b_val);
|
|
threshold = element_wise_relative_error ? fabs(b_val) + 1 : maxval;
|
|
if( a_val > threshold*success_err_level )
|
|
{
|
|
maxdiff = a_val/threshold;
|
|
*idx = cvPoint(j,i);
|
|
goto _exit_;
|
|
}
|
|
}
|
|
break;
|
|
case CV_64F:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
double a_val = ((double*)a_data)[j];
|
|
double b_val = ((double*)b_data)[j];
|
|
double threshold;
|
|
if( ((int64*)a_data)[j] == ((int64*)b_data)[j] )
|
|
continue;
|
|
if( cvIsNaN(a_val) || cvIsInf(a_val) )
|
|
{
|
|
result = -2;
|
|
*idx = cvPoint(j,i);
|
|
goto _exit_;
|
|
}
|
|
if( cvIsNaN(b_val) || cvIsInf(b_val) )
|
|
{
|
|
result = -3;
|
|
*idx = cvPoint(j,i);
|
|
goto _exit_;
|
|
}
|
|
a_val = fabs(a_val - b_val);
|
|
threshold = element_wise_relative_error ? fabs(b_val) + 1 : maxval;
|
|
if( a_val > threshold*success_err_level )
|
|
{
|
|
maxdiff = a_val/threshold;
|
|
*idx = cvPoint(j,i);
|
|
goto _exit_;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
assert(0);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
result = 0;
|
|
_exit_:
|
|
|
|
if( CV_MAT_DEPTH(check_arr->type) < CV_32S )
|
|
maxdiff = imaxdiff;
|
|
|
|
if( result < -1 )
|
|
maxdiff = exp(1000.);
|
|
*_max_diff = maxdiff;
|
|
return result;
|
|
}
|
|
|
|
|
|
int cvTsCmpEps2( CvTS* ts, const CvArr* _a, const CvArr* _b, double success_err_level,
|
|
bool element_wise_relative_error, const char* desc )
|
|
{
|
|
char msg[100];
|
|
double diff = 0;
|
|
CvMat astub, bstub, *a, *b;
|
|
CvPoint idx = {0,0};
|
|
int code;
|
|
|
|
a = cvGetMat( _a, &astub );
|
|
b = cvGetMat( _b, &bstub );
|
|
code = cvTsCmpEps( a, b, &diff, success_err_level, &idx,
|
|
element_wise_relative_error );
|
|
|
|
switch( code )
|
|
{
|
|
case -1:
|
|
sprintf( msg, "%s: Too big difference (=%g)", desc, diff );
|
|
code = CvTS::FAIL_BAD_ACCURACY;
|
|
break;
|
|
case -2:
|
|
sprintf( msg, "%s: Invalid output", desc );
|
|
code = CvTS::FAIL_INVALID_OUTPUT;
|
|
break;
|
|
case -3:
|
|
sprintf( msg, "%s: Invalid reference output", desc );
|
|
code = CvTS::FAIL_INVALID_OUTPUT;
|
|
break;
|
|
default:
|
|
;
|
|
}
|
|
|
|
if( code < 0 )
|
|
{
|
|
if( a->rows == 1 && a->cols == 1 )
|
|
{
|
|
assert( idx.x == 0 && idx.y == 0 );
|
|
ts->printf( CvTS::LOG, "%s\n", msg );
|
|
}
|
|
else if( a->rows == 1 || a->cols == 1 )
|
|
{
|
|
assert( idx.x == 0 || idx.y == 0 );
|
|
ts->printf( CvTS::LOG, "%s at element %d\n", msg, idx.x + idx.y );
|
|
}
|
|
else
|
|
ts->printf( CvTS::LOG, "%s at (%d,%d)\n", msg, idx.x, idx.y );
|
|
}
|
|
|
|
return code;
|
|
}
|
|
|
|
|
|
int cvTsCmpEps2_64f( CvTS* ts, const double* val, const double* ref_val, int len,
|
|
double eps, const char* param_name )
|
|
{
|
|
CvMat _val = cvMat( 1, len, CV_64F, (void*)val );
|
|
CvMat _ref_val = cvMat( 1, len, CV_64F, (void*)ref_val );
|
|
|
|
return cvTsCmpEps2( ts, &_val, &_ref_val, eps, true, param_name );
|
|
}
|
|
|
|
// compares two arrays. the result is 8s image that takes values -1, 0, 1
|
|
void cvTsCmp( const CvMat* a, const CvMat* b, CvMat* result, int cmp_op )
|
|
{
|
|
int i = 0, j = 0, ncols;
|
|
ncols = a->cols;
|
|
|
|
assert( CV_ARE_TYPES_EQ(a,b) && CV_ARE_SIZES_EQ(a,b) && CV_MAT_CN(a->type) == 1 );
|
|
assert( CV_ARE_SIZES_EQ(a,result) &&
|
|
(CV_MAT_TYPE(result->type) == CV_8UC1 ||
|
|
CV_MAT_TYPE(result->type) == CV_8SC1 ));
|
|
|
|
for( i = 0; i < a->rows; i++ )
|
|
{
|
|
uchar* a_data = a->data.ptr + a->step*i;
|
|
uchar* b_data = b->data.ptr + b->step*i;
|
|
schar* r_data = (schar*)(result->data.ptr + result->step*i);
|
|
|
|
switch( CV_MAT_DEPTH(a->type) )
|
|
{
|
|
case CV_8U:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int a_val = ((uchar*)a_data)[j];
|
|
int b_val = ((uchar*)b_data)[j];
|
|
r_data[j] = (schar)CV_CMP(a_val,b_val);
|
|
}
|
|
break;
|
|
case CV_8S:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int a_val = ((schar*)a_data)[j];
|
|
int b_val = ((schar*)b_data)[j];
|
|
r_data[j] = (schar)CV_CMP(a_val,b_val);
|
|
}
|
|
break;
|
|
case CV_16U:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int a_val = ((ushort*)a_data)[j];
|
|
int b_val = ((ushort*)b_data)[j];
|
|
r_data[j] = (schar)CV_CMP(a_val,b_val);
|
|
}
|
|
break;
|
|
case CV_16S:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int a_val = ((short*)a_data)[j];
|
|
int b_val = ((short*)b_data)[j];
|
|
r_data[j] = (schar)CV_CMP(a_val,b_val);
|
|
}
|
|
break;
|
|
case CV_32S:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int a_val = ((int*)a_data)[j];
|
|
int b_val = ((int*)b_data)[j];
|
|
r_data[j] = (schar)CV_CMP(a_val,b_val);
|
|
}
|
|
break;
|
|
case CV_32F:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
float a_val = ((float*)a_data)[j];
|
|
float b_val = ((float*)b_data)[j];
|
|
r_data[j] = (schar)CV_CMP(a_val,b_val);
|
|
}
|
|
break;
|
|
case CV_64F:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
double a_val = ((double*)a_data)[j];
|
|
double b_val = ((double*)b_data)[j];
|
|
r_data[j] = (schar)CV_CMP(a_val,b_val);
|
|
}
|
|
break;
|
|
default:
|
|
assert(0);
|
|
}
|
|
|
|
switch( cmp_op )
|
|
{
|
|
case CV_CMP_EQ:
|
|
for( j = 0; j < ncols; j++ )
|
|
r_data[j] = (schar)(r_data[j] == 0 ? -1 : 0);
|
|
break;
|
|
case CV_CMP_NE:
|
|
for( j = 0; j < ncols; j++ )
|
|
r_data[j] = (schar)(r_data[j] != 0 ? -1 : 0);
|
|
break;
|
|
case CV_CMP_LT:
|
|
for( j = 0; j < ncols; j++ )
|
|
r_data[j] = (schar)(r_data[j] < 0 ? -1 : 0);
|
|
break;
|
|
case CV_CMP_LE:
|
|
for( j = 0; j < ncols; j++ )
|
|
r_data[j] = (schar)(r_data[j] <= 0 ? -1 : 0);
|
|
break;
|
|
case CV_CMP_GE:
|
|
for( j = 0; j < ncols; j++ )
|
|
r_data[j] = (schar)(r_data[j] >= 0 ? -1 : 0);
|
|
break;
|
|
case CV_CMP_GT:
|
|
for( j = 0; j < ncols; j++ )
|
|
r_data[j] = (schar)(r_data[j] > 0 ? -1 : 0);
|
|
break;
|
|
default:
|
|
;
|
|
}
|
|
}
|
|
}
|
|
|
|
// compares two arrays. the result is 8s image that takes values -1, 0, 1
|
|
void cvTsCmpS( const CvMat* a, double fval, CvMat* result, int cmp_op )
|
|
{
|
|
int i = 0, j = 0;
|
|
int ncols, ival = 0;
|
|
ncols = a->cols;
|
|
|
|
if( CV_MAT_DEPTH(a->type) <= CV_32S )
|
|
ival = cvRound(fval);
|
|
|
|
assert( CV_MAT_CN(a->type) == 1 );
|
|
assert( CV_ARE_SIZES_EQ(a,result) &&
|
|
(CV_MAT_TYPE(result->type) == CV_8UC1 ||
|
|
CV_MAT_TYPE(result->type) == CV_8SC1 ));
|
|
|
|
for( i = 0; i < a->rows; i++ )
|
|
{
|
|
uchar* a_data = a->data.ptr + a->step*i;
|
|
schar* r_data = (schar*)(result->data.ptr + result->step*i);
|
|
|
|
switch( CV_MAT_DEPTH(a->type) )
|
|
{
|
|
case CV_8U:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int a_val = ((uchar*)a_data)[j];
|
|
r_data[j] = (schar)CV_CMP(a_val,ival);
|
|
}
|
|
break;
|
|
case CV_8S:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int a_val = ((schar*)a_data)[j];
|
|
r_data[j] = (schar)CV_CMP(a_val,ival);
|
|
}
|
|
break;
|
|
case CV_16U:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int a_val = ((ushort*)a_data)[j];
|
|
r_data[j] = (schar)CV_CMP(a_val,ival);
|
|
}
|
|
break;
|
|
case CV_16S:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int a_val = ((short*)a_data)[j];
|
|
r_data[j] = (schar)CV_CMP(a_val,ival);
|
|
}
|
|
break;
|
|
case CV_32S:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int a_val = ((int*)a_data)[j];
|
|
r_data[j] = (schar)CV_CMP(a_val,ival);
|
|
}
|
|
break;
|
|
case CV_32F:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
float a_val = ((float*)a_data)[j];
|
|
r_data[j] = (schar)CV_CMP(a_val,fval);
|
|
}
|
|
break;
|
|
case CV_64F:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
double a_val = ((double*)a_data)[j];
|
|
r_data[j] = (schar)CV_CMP(a_val,fval);
|
|
}
|
|
break;
|
|
default:
|
|
assert(0);
|
|
}
|
|
|
|
switch( cmp_op )
|
|
{
|
|
case CV_CMP_EQ:
|
|
for( j = 0; j < ncols; j++ )
|
|
r_data[j] = (schar)(r_data[j] == 0 ? -1 : 0);
|
|
break;
|
|
case CV_CMP_NE:
|
|
for( j = 0; j < ncols; j++ )
|
|
r_data[j] = (schar)(r_data[j] != 0 ? -1 : 0);
|
|
break;
|
|
case CV_CMP_LT:
|
|
for( j = 0; j < ncols; j++ )
|
|
r_data[j] = (schar)(r_data[j] < 0 ? -1 : 0);
|
|
break;
|
|
case CV_CMP_LE:
|
|
for( j = 0; j < ncols; j++ )
|
|
r_data[j] = (schar)(r_data[j] <= 0 ? -1 : 0);
|
|
break;
|
|
case CV_CMP_GE:
|
|
for( j = 0; j < ncols; j++ )
|
|
r_data[j] = (schar)(r_data[j] >= 0 ? -1 : 0);
|
|
break;
|
|
case CV_CMP_GT:
|
|
for( j = 0; j < ncols; j++ )
|
|
r_data[j] = (schar)(r_data[j] > 0 ? -1 : 0);
|
|
break;
|
|
default:
|
|
;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// calculates norm of a matrix
|
|
double cvTsNorm( const CvMat* arr, const CvMat* mask, int norm_type, int coi )
|
|
{
|
|
int i = 0, j = 0, k;
|
|
int depth, cn0, cn, ncols, el_size1;
|
|
int inorm = 0;
|
|
double fnorm = 0;
|
|
void* buffer = 0;
|
|
uchar* zerobuf = 0;
|
|
|
|
cn0 = cn = CV_MAT_CN(arr->type);
|
|
ncols = arr->cols*cn;
|
|
depth = CV_MAT_DEPTH(arr->type);
|
|
el_size1 = CV_ELEM_SIZE(depth);
|
|
zerobuf = (uchar*)cvStackAlloc(el_size1*cn);
|
|
memset( zerobuf, 0, el_size1*cn);
|
|
|
|
if( mask )
|
|
{
|
|
assert( CV_ARE_SIZES_EQ( arr, mask ) && CV_IS_MASK_ARR(mask) );
|
|
buffer = cvStackAlloc( el_size1*ncols );
|
|
}
|
|
|
|
if( coi == 0 )
|
|
cn = 1;
|
|
|
|
for( i = 0; i < arr->rows; i++ )
|
|
{
|
|
const uchar* data = arr->data.ptr + arr->step*i + (coi - (coi != 0))*el_size1;
|
|
|
|
if( mask )
|
|
{
|
|
const uchar* mdata = mask->data.ptr + mask->step*i;
|
|
switch( depth )
|
|
{
|
|
case CV_8U:
|
|
case CV_8S:
|
|
for( j = 0; j < ncols; j += cn0 )
|
|
{
|
|
const uchar* src = *mdata++ ? (uchar*)data + j : zerobuf;
|
|
for( k = 0; k < cn0; k++ )
|
|
((uchar*)buffer)[j+k] = src[k];
|
|
}
|
|
break;
|
|
case CV_16U:
|
|
case CV_16S:
|
|
for( j = 0; j < ncols; j += cn0 )
|
|
{
|
|
const short* src = *mdata++ ? (short*)data + j : (short*)zerobuf;
|
|
for( k = 0; k < cn0; k++ )
|
|
((short*)buffer)[j+k] = src[k];
|
|
}
|
|
break;
|
|
case CV_32S:
|
|
case CV_32F:
|
|
for( j = 0; j < ncols; j += cn0 )
|
|
{
|
|
const int* src = *mdata++ ? (int*)data + j : (int*)zerobuf;
|
|
for( k = 0; k < cn0; k++ )
|
|
((int*)buffer)[j+k] = src[k];
|
|
}
|
|
break;
|
|
case CV_64F:
|
|
for( j = 0; j < ncols; j += cn0 )
|
|
{
|
|
const double* src = *mdata++ ? (double*)data + j : (double*)zerobuf;
|
|
for( k = 0; k < cn0; k++ )
|
|
((double*)buffer)[j+k] = src[k];
|
|
}
|
|
break;
|
|
default:
|
|
assert(0);
|
|
return -1;
|
|
}
|
|
data = (const uchar*)buffer;
|
|
}
|
|
|
|
switch( depth )
|
|
{
|
|
case CV_8U:
|
|
if( norm_type == CV_C )
|
|
{
|
|
for( j = 0; j < ncols; j += cn )
|
|
{
|
|
int val = ((const uchar*)data)[j];
|
|
inorm = MAX( inorm, val );
|
|
}
|
|
}
|
|
else if( norm_type == CV_L1 )
|
|
{
|
|
inorm = 0;
|
|
for( j = 0; j < ncols; j += cn )
|
|
{
|
|
int val = ((const uchar*)data)[j];
|
|
inorm += val;
|
|
}
|
|
fnorm += inorm;
|
|
}
|
|
else
|
|
{
|
|
inorm = 0;
|
|
for( j = 0; j < ncols; j += cn )
|
|
{
|
|
int val = ((const uchar*)data)[j];
|
|
inorm += val*val;
|
|
}
|
|
fnorm += inorm;
|
|
}
|
|
break;
|
|
case CV_8S:
|
|
if( norm_type == CV_C )
|
|
{
|
|
for( j = 0; j < ncols; j += cn )
|
|
{
|
|
int val = abs(((const schar*)data)[j]);
|
|
inorm = MAX( inorm, val );
|
|
}
|
|
}
|
|
else if( norm_type == CV_L1 )
|
|
{
|
|
inorm = 0;
|
|
for( j = 0; j < ncols; j += cn )
|
|
{
|
|
int val = abs(((const schar*)data)[j]);
|
|
inorm += val;
|
|
}
|
|
fnorm += inorm;
|
|
}
|
|
else
|
|
{
|
|
inorm = 0;
|
|
for( j = 0; j < ncols; j += cn )
|
|
{
|
|
int val = ((const schar*)data)[j];
|
|
inorm += val*val;
|
|
}
|
|
fnorm += inorm;
|
|
}
|
|
break;
|
|
case CV_16U:
|
|
if( norm_type == CV_C )
|
|
{
|
|
for( j = 0; j < ncols; j += cn )
|
|
{
|
|
int val = ((const ushort*)data)[j];
|
|
inorm = MAX( inorm, val );
|
|
}
|
|
}
|
|
else if( norm_type == CV_L1 )
|
|
{
|
|
inorm = 0;
|
|
for( j = 0; j < ncols; j += cn )
|
|
{
|
|
int val = ((const ushort*)data)[j];
|
|
inorm += val;
|
|
}
|
|
fnorm += inorm;
|
|
}
|
|
else
|
|
{
|
|
for( j = 0; j < ncols; j += cn )
|
|
{
|
|
double val = ((const ushort*)data)[j];
|
|
fnorm += val*val;
|
|
}
|
|
}
|
|
break;
|
|
case CV_16S:
|
|
if( norm_type == CV_C )
|
|
{
|
|
for( j = 0; j < ncols; j += cn )
|
|
{
|
|
int val = abs(((const short*)data)[j]);
|
|
inorm = MAX( inorm, val );
|
|
}
|
|
}
|
|
else if( norm_type == CV_L1 )
|
|
{
|
|
inorm = 0;
|
|
for( j = 0; j < ncols; j += cn )
|
|
{
|
|
int val = abs(((const short*)data)[j]);
|
|
inorm += val;
|
|
}
|
|
fnorm += inorm;
|
|
}
|
|
else
|
|
{
|
|
for( j = 0; j < ncols; j += cn )
|
|
{
|
|
double val = ((const short*)data)[j];
|
|
fnorm += val*val;
|
|
}
|
|
}
|
|
break;
|
|
case CV_32S:
|
|
if( norm_type == CV_C )
|
|
{
|
|
for( j = 0; j < ncols; j += cn )
|
|
{
|
|
int val = abs(((const int*)data)[j]);
|
|
inorm = MAX( inorm, val );
|
|
}
|
|
}
|
|
else if( norm_type == CV_L1 )
|
|
{
|
|
for( j = 0; j < ncols; j += cn )
|
|
{
|
|
double val = fabs((double)((const int*)data)[j]);
|
|
fnorm += val;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for( j = 0; j < ncols; j += cn )
|
|
{
|
|
double val = ((const int*)data)[j];
|
|
fnorm += val*val;
|
|
}
|
|
}
|
|
break;
|
|
case CV_32F:
|
|
if( norm_type == CV_C )
|
|
{
|
|
for( j = 0; j < ncols; j += cn )
|
|
{
|
|
double val = fabs((double)((const float*)data)[j]);
|
|
fnorm = MAX( fnorm, val );
|
|
}
|
|
}
|
|
else if( norm_type == CV_L1 )
|
|
{
|
|
for( j = 0; j < ncols; j += cn )
|
|
{
|
|
double val = fabs((double)((const float*)data)[j]);
|
|
fnorm += val;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for( j = 0; j < ncols; j += cn )
|
|
{
|
|
double val = ((const float*)data)[j];
|
|
fnorm += val*val;
|
|
}
|
|
}
|
|
break;
|
|
case CV_64F:
|
|
if( norm_type == CV_C )
|
|
{
|
|
for( j = 0; j < ncols; j += cn )
|
|
{
|
|
double val = fabs(((const double*)data)[j]);
|
|
fnorm = MAX( fnorm, val );
|
|
}
|
|
}
|
|
else if( norm_type == CV_L1 )
|
|
{
|
|
for( j = 0; j < ncols; j += cn )
|
|
{
|
|
double val = fabs(((const double*)data)[j]);
|
|
fnorm += val;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for( j = 0; j < ncols; j += cn )
|
|
{
|
|
double val = ((const double*)data)[j];
|
|
fnorm += val*val;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
assert(0);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
if( norm_type == CV_L2 )
|
|
fnorm = sqrt( fnorm );
|
|
else if( depth < CV_32F && norm_type == CV_C )
|
|
fnorm = inorm;
|
|
|
|
return fnorm;
|
|
}
|
|
|
|
|
|
// retrieves mean, standard deviation and the number of nonzero mask pixels
|
|
int cvTsMeanStdDevNonZero( const CvMat* arr, const CvMat* mask,
|
|
CvScalar* _mean, CvScalar* _stddev, int coi )
|
|
{
|
|
int i = 0, j = 0, k;
|
|
int depth, cn0, cn, cols, ncols, el_size1;
|
|
CvScalar sum = cvScalar(0), sqsum = cvScalar(0);
|
|
double inv_area;
|
|
int isum[4], isqsum[4];
|
|
int nonzero = 0;
|
|
uchar* maskbuf = 0;
|
|
|
|
cn0 = cn = CV_MAT_CN(arr->type);
|
|
cols = arr->cols;
|
|
ncols = arr->cols*cn;
|
|
depth = CV_MAT_DEPTH(arr->type);
|
|
el_size1 = CV_ELEM_SIZE(depth);
|
|
if( mask )
|
|
{
|
|
assert( CV_ARE_SIZES_EQ( arr, mask ) && CV_IS_MASK_ARR(mask) );
|
|
}
|
|
else
|
|
{
|
|
maskbuf = (uchar*)cvStackAlloc( cols );
|
|
memset( maskbuf, 1, cols );
|
|
nonzero = cols*arr->rows;
|
|
}
|
|
|
|
if( coi != 0 )
|
|
cn = 1;
|
|
|
|
for( i = 0; i < arr->rows; i++ )
|
|
{
|
|
const uchar* data = arr->data.ptr + arr->step*i + (coi - (coi != 0))*el_size1;
|
|
const uchar* mdata;
|
|
|
|
if( mask )
|
|
{
|
|
mdata = mask->data.ptr + mask->step*i;
|
|
for( j = 0; j < cols; j++ )
|
|
nonzero += mdata[j] != 0;
|
|
}
|
|
else
|
|
{
|
|
mdata = maskbuf;
|
|
}
|
|
|
|
// if only a number of pixels in the mask is needed, skip the rest of the loop body
|
|
if( !_mean && !_stddev )
|
|
continue;
|
|
|
|
switch( depth )
|
|
{
|
|
case CV_8U:
|
|
for( k = 0; k < cn; k++ )
|
|
isum[k] = isqsum[k] = 0;
|
|
for( j = 0; j < ncols; j += cn0 )
|
|
if( *mdata++ )
|
|
{
|
|
for( k = 0; k < cn; k++ )
|
|
{
|
|
int val = ((const uchar*)data)[j+k];
|
|
isum[k] += val;
|
|
isqsum[k] += val*val;
|
|
}
|
|
}
|
|
for( k = 0; k < cn; k++ )
|
|
{
|
|
sum.val[k] += isum[k];
|
|
sqsum.val[k] += isqsum[k];
|
|
}
|
|
break;
|
|
case CV_8S:
|
|
for( k = 0; k < cn; k++ )
|
|
isum[k] = isqsum[k] = 0;
|
|
for( j = 0; j < ncols; j += cn0 )
|
|
if( *mdata++ )
|
|
{
|
|
for( k = 0; k < cn; k++ )
|
|
{
|
|
int val = ((const schar*)data)[j+k];
|
|
isum[k] += val;
|
|
isqsum[k] += val*val;
|
|
}
|
|
}
|
|
for( k = 0; k < cn; k++ )
|
|
{
|
|
sum.val[k] += isum[k];
|
|
sqsum.val[k] += isqsum[k];
|
|
}
|
|
break;
|
|
case CV_16U:
|
|
for( k = 0; k < cn; k++ )
|
|
isum[k] = 0;
|
|
for( j = 0; j < ncols; j += cn0 )
|
|
if( *mdata++ )
|
|
{
|
|
for( k = 0; k < cn; k++ )
|
|
{
|
|
int val = ((const ushort*)data)[j+k];
|
|
isum[k] += val;
|
|
sqsum.val[k] += ((double)val)*val;
|
|
}
|
|
}
|
|
for( k = 0; k < cn; k++ )
|
|
sum.val[k] += isum[k];
|
|
break;
|
|
case CV_16S:
|
|
for( k = 0; k < cn; k++ )
|
|
isum[k] = 0;
|
|
for( j = 0; j < ncols; j += cn0 )
|
|
if( *mdata++ )
|
|
{
|
|
for( k = 0; k < cn; k++ )
|
|
{
|
|
int val = ((const short*)data)[j+k];
|
|
isum[k] += val;
|
|
sqsum.val[k] += ((double)val)*val;
|
|
}
|
|
}
|
|
for( k = 0; k < cn; k++ )
|
|
sum.val[k] += isum[k];
|
|
break;
|
|
case CV_32S:
|
|
for( j = 0; j < ncols; j += cn0 )
|
|
if( *mdata++ )
|
|
{
|
|
for( k = 0; k < cn; k++ )
|
|
{
|
|
double val = ((const int*)data)[j+k];
|
|
sum.val[k] += val;
|
|
sqsum.val[k] += val*val;
|
|
}
|
|
}
|
|
break;
|
|
case CV_32F:
|
|
for( j = 0; j < ncols; j += cn0 )
|
|
if( *mdata++ )
|
|
{
|
|
for( k = 0; k < cn; k++ )
|
|
{
|
|
double val = ((const float*)data)[j+k];
|
|
sum.val[k] += val;
|
|
sqsum.val[k] += val*val;
|
|
}
|
|
}
|
|
break;
|
|
case CV_64F:
|
|
for( j = 0; j < ncols; j += cn0 )
|
|
if( *mdata++ )
|
|
{
|
|
for( k = 0; k < cn; k++ )
|
|
{
|
|
double val = ((const double*)data)[j+k];
|
|
sum.val[k] += val;
|
|
sqsum.val[k] += val*val;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
assert(0);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
inv_area = nonzero ? 1./nonzero : 0.;
|
|
for( k = 0; k < cn; k++ )
|
|
{
|
|
sum.val[k] *= inv_area;
|
|
double t = sqsum.val[k]*inv_area - sum.val[k]*sum.val[k];
|
|
sqsum.val[k] = sqrt(MAX(t, 0));
|
|
}
|
|
if( _mean )
|
|
*_mean = sum;
|
|
if( _stddev )
|
|
*_stddev = sqsum;
|
|
return nonzero;
|
|
}
|
|
|
|
// retrieves global extremums and their positions
|
|
void cvTsMinMaxLoc( const CvMat* arr, const CvMat* mask,
|
|
double* _minval, double* _maxval,
|
|
CvPoint* _minidx, CvPoint* _maxidx, int coi )
|
|
{
|
|
int i = 0, j = 0;
|
|
int depth, cn, cols, ncols, el_size1;
|
|
CvPoint minidx = {-1,-1}, maxidx = {-1,-1};
|
|
uchar* maskbuf = 0;
|
|
int iminval = INT_MAX, imaxval = INT_MIN;
|
|
double minval = DBL_MAX, maxval = -minval;
|
|
|
|
cn = CV_MAT_CN(arr->type);
|
|
cols = arr->cols;
|
|
ncols = arr->cols*cn;
|
|
depth = CV_MAT_DEPTH(arr->type);
|
|
el_size1 = CV_ELEM_SIZE(depth);
|
|
|
|
if( mask )
|
|
{
|
|
assert( CV_ARE_SIZES_EQ( arr, mask ) && CV_IS_MASK_ARR(mask) );
|
|
}
|
|
else
|
|
{
|
|
maskbuf = (uchar*)cvStackAlloc( cols );
|
|
memset( maskbuf, 1, cols );
|
|
}
|
|
|
|
if( coi == 0 && cn > 1 )
|
|
{
|
|
assert(0);
|
|
return;
|
|
}
|
|
|
|
for( i = 0; i < arr->rows; i++ )
|
|
{
|
|
const uchar* data = arr->data.ptr + arr->step*i + (coi - (coi != 0))*el_size1;
|
|
const uchar* mdata = mask ? mask->data.ptr + mask->step*i : maskbuf;
|
|
|
|
switch( depth )
|
|
{
|
|
case CV_8U:
|
|
for( j = 0; j < ncols; j += cn, mdata++ )
|
|
{
|
|
int val = ((const uchar*)data)[j];
|
|
if( val < iminval && *mdata )
|
|
{
|
|
iminval = val;
|
|
minidx = cvPoint(j,i);
|
|
}
|
|
if( val > imaxval && *mdata )
|
|
{
|
|
imaxval = val;
|
|
maxidx = cvPoint(j,i);
|
|
}
|
|
}
|
|
break;
|
|
case CV_8S:
|
|
for( j = 0; j < ncols; j += cn, mdata++ )
|
|
{
|
|
int val = ((const schar*)data)[j];
|
|
if( val < iminval && *mdata )
|
|
{
|
|
iminval = val;
|
|
minidx = cvPoint(j,i);
|
|
}
|
|
if( val > imaxval && *mdata )
|
|
{
|
|
imaxval = val;
|
|
maxidx = cvPoint(j,i);
|
|
}
|
|
}
|
|
break;
|
|
case CV_16U:
|
|
for( j = 0; j < ncols; j += cn, mdata++ )
|
|
{
|
|
int val = ((const ushort*)data)[j];
|
|
if( val < iminval && *mdata )
|
|
{
|
|
iminval = val;
|
|
minidx = cvPoint(j,i);
|
|
}
|
|
if( val > imaxval && *mdata )
|
|
{
|
|
imaxval = val;
|
|
maxidx = cvPoint(j,i);
|
|
}
|
|
}
|
|
break;
|
|
case CV_16S:
|
|
for( j = 0; j < ncols; j += cn, mdata++ )
|
|
{
|
|
int val = ((const short*)data)[j];
|
|
if( val < iminval && *mdata )
|
|
{
|
|
iminval = val;
|
|
minidx = cvPoint(j,i);
|
|
}
|
|
if( val > imaxval && *mdata )
|
|
{
|
|
imaxval = val;
|
|
maxidx = cvPoint(j,i);
|
|
}
|
|
}
|
|
break;
|
|
case CV_32S:
|
|
for( j = 0; j < ncols; j += cn, mdata++ )
|
|
{
|
|
int val = ((const int*)data)[j];
|
|
if( val < iminval && *mdata )
|
|
{
|
|
iminval = val;
|
|
minidx = cvPoint(j,i);
|
|
}
|
|
if( val > imaxval && *mdata )
|
|
{
|
|
imaxval = val;
|
|
maxidx = cvPoint(j,i);
|
|
}
|
|
}
|
|
break;
|
|
case CV_32F:
|
|
for( j = 0; j < ncols; j += cn, mdata++ )
|
|
{
|
|
float val = ((const float*)data)[j];
|
|
if( val < minval && *mdata )
|
|
{
|
|
minval = val;
|
|
minidx = cvPoint(j,i);
|
|
}
|
|
if( val > maxval && *mdata )
|
|
{
|
|
maxval = val;
|
|
maxidx = cvPoint(j,i);
|
|
}
|
|
}
|
|
break;
|
|
case CV_64F:
|
|
for( j = 0; j < ncols; j += cn, mdata++ )
|
|
{
|
|
double val = ((const double*)data)[j];
|
|
if( val < minval && *mdata )
|
|
{
|
|
minval = val;
|
|
minidx = cvPoint(j,i);
|
|
}
|
|
if( val > maxval && *mdata )
|
|
{
|
|
maxval = val;
|
|
maxidx = cvPoint(j,i);
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
assert(0);
|
|
return;
|
|
}
|
|
}
|
|
|
|
if( minidx.x < 0 )
|
|
minval = maxval = 0;
|
|
else
|
|
{
|
|
if( depth < CV_32F )
|
|
minval = iminval, maxval = imaxval;
|
|
minidx.x /= cn;
|
|
maxidx.x /= cn;
|
|
}
|
|
|
|
if( _minval )
|
|
*_minval = minval;
|
|
|
|
if( _maxval )
|
|
*_maxval = maxval;
|
|
|
|
if( _minidx )
|
|
*_minidx = minidx;
|
|
|
|
if( _maxidx )
|
|
*_maxidx = maxidx;
|
|
}
|
|
|
|
|
|
void cvTsLogic( const CvMat* a, const CvMat* b, CvMat* c, int logic_op )
|
|
{
|
|
int i = 0, j = 0, ncols;
|
|
ncols = a->cols*CV_ELEM_SIZE(a->type);
|
|
|
|
assert( CV_ARE_TYPES_EQ(a,b) && CV_ARE_SIZES_EQ(a,b) );
|
|
assert( CV_ARE_TYPES_EQ(a,c) && CV_ARE_SIZES_EQ(a,c) );
|
|
|
|
for( i = 0; i < a->rows; i++ )
|
|
{
|
|
uchar* a_data = a->data.ptr + a->step*i;
|
|
uchar* b_data = b->data.ptr + b->step*i;
|
|
uchar* c_data = c->data.ptr + c->step*i;
|
|
|
|
switch( logic_op )
|
|
{
|
|
case CV_TS_LOGIC_AND:
|
|
for( j = 0; j < ncols; j++ )
|
|
c_data[j] = (uchar)(a_data[j] & b_data[j]);
|
|
break;
|
|
case CV_TS_LOGIC_OR:
|
|
for( j = 0; j < ncols; j++ )
|
|
c_data[j] = (uchar)(a_data[j] | b_data[j]);
|
|
break;
|
|
case CV_TS_LOGIC_XOR:
|
|
for( j = 0; j < ncols; j++ )
|
|
c_data[j] = (uchar)(a_data[j] ^ b_data[j]);
|
|
break;
|
|
default:
|
|
assert(0);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void cvTsLogicS( const CvMat* a, CvScalar s, CvMat* c, int logic_op )
|
|
{
|
|
int i = 0, j = 0, k;
|
|
int cn, ncols, elem_size;
|
|
uchar* b_data;
|
|
union
|
|
{
|
|
uchar ptr[4];
|
|
schar c[4];
|
|
short s[4];
|
|
ushort w[4];
|
|
int i[4];
|
|
float f[4];
|
|
double d[4];
|
|
} buf;
|
|
cn = CV_MAT_CN(a->type);
|
|
elem_size = CV_ELEM_SIZE(a->type);
|
|
ncols = a->cols * elem_size;
|
|
b_data = (uchar*)malloc( ncols );
|
|
|
|
assert( CV_ARE_TYPES_EQ(a,c) && CV_ARE_SIZES_EQ(a,c) );
|
|
|
|
if( logic_op == CV_TS_LOGIC_NOT )
|
|
{
|
|
memset( b_data, -1, ncols );
|
|
logic_op = CV_TS_LOGIC_XOR;
|
|
}
|
|
else
|
|
{
|
|
switch( CV_MAT_DEPTH(a->type) )
|
|
{
|
|
case CV_8U:
|
|
for( k = 0; k < cn; k++ )
|
|
{
|
|
int val = cvRound(s.val[k]);
|
|
buf.ptr[k] = CV_CAST_8U(val);
|
|
}
|
|
break;
|
|
case CV_8S:
|
|
for( k = 0; k < cn; k++ )
|
|
{
|
|
int val = cvRound(s.val[k]);
|
|
buf.c[k] = CV_CAST_8S(val);
|
|
}
|
|
break;
|
|
case CV_16U:
|
|
for( k = 0; k < cn; k++ )
|
|
{
|
|
int val = cvRound(s.val[k]);
|
|
buf.w[k] = CV_CAST_16U(val);
|
|
}
|
|
break;
|
|
case CV_16S:
|
|
for( k = 0; k < cn; k++ )
|
|
{
|
|
int val = cvRound(s.val[k]);
|
|
buf.s[k] = CV_CAST_16S(val);
|
|
}
|
|
break;
|
|
case CV_32S:
|
|
for( k = 0; k < cn; k++ )
|
|
{
|
|
int val = cvRound(s.val[k]);
|
|
buf.i[k] = CV_CAST_32S(val);
|
|
}
|
|
break;
|
|
case CV_32F:
|
|
for( k = 0; k < cn; k++ )
|
|
{
|
|
double val = s.val[k];
|
|
buf.f[k] = CV_CAST_32F(val);
|
|
}
|
|
break;
|
|
case CV_64F:
|
|
for( k = 0; k < cn; k++ )
|
|
{
|
|
double val = s.val[k];
|
|
buf.d[k] = CV_CAST_64F(val);
|
|
}
|
|
break;
|
|
default:
|
|
assert(0);
|
|
return;
|
|
}
|
|
|
|
for( j = 0; j < ncols; j += elem_size )
|
|
memcpy( b_data + j, buf.ptr, elem_size );
|
|
}
|
|
|
|
for( i = 0; i < a->rows; i++ )
|
|
{
|
|
uchar* a_data = a->data.ptr + a->step*i;
|
|
uchar* c_data = c->data.ptr + c->step*i;
|
|
|
|
switch( logic_op )
|
|
{
|
|
case CV_TS_LOGIC_AND:
|
|
for( j = 0; j < ncols; j++ )
|
|
c_data[j] = (uchar)(a_data[j] & b_data[j]);
|
|
break;
|
|
case CV_TS_LOGIC_OR:
|
|
for( j = 0; j < ncols; j++ )
|
|
c_data[j] = (uchar)(a_data[j] | b_data[j]);
|
|
break;
|
|
case CV_TS_LOGIC_XOR:
|
|
for( j = 0; j < ncols; j++ )
|
|
c_data[j] = (uchar)(a_data[j] ^ b_data[j]);
|
|
break;
|
|
default:
|
|
assert(0);
|
|
return;
|
|
}
|
|
}
|
|
|
|
if( b_data )
|
|
free( b_data );
|
|
}
|
|
|
|
|
|
void cvTsGEMM( const CvMat* a, const CvMat* b, double alpha,
|
|
const CvMat* c, double beta, CvMat* d, int flags )
|
|
{
|
|
int i, j, k;
|
|
int a_rows, a_cols, b_rows, b_cols;
|
|
int c_rows, c_cols, d_rows, d_cols;
|
|
int cn, el_size;
|
|
int a_step, a_delta, b_step, b_delta;
|
|
int c_step, c_delta, d_step;
|
|
|
|
a_rows = a->rows; a_cols = a->cols;
|
|
cn = CV_MAT_CN(a->type);
|
|
el_size = CV_ELEM_SIZE(a->type & ~CV_MAT_CN_MASK);
|
|
a_step = a->step / el_size; a_delta = cn;
|
|
d_rows = d->rows; d_cols = d->cols;
|
|
b_rows = b->rows; b_cols = b->cols;
|
|
b_step = b->step / el_size; b_delta = cn;
|
|
c_rows = c ? c->rows : 0; c_cols = c ? c->cols : 0;
|
|
c_step = c ? c->step / el_size : 0; c_delta = c ? cn : 0;
|
|
d_step = d->step / el_size;
|
|
|
|
assert( CV_ARE_TYPES_EQ(a,b) && CV_ARE_TYPES_EQ(a,d) );
|
|
assert( CV_MAT_CN(a->type) <= 2 );
|
|
|
|
if( flags & CV_TS_GEMM_A_T )
|
|
{
|
|
CV_SWAP( a_rows, a_cols, i );
|
|
CV_SWAP( a_step, a_delta, i );
|
|
}
|
|
|
|
if( flags & CV_TS_GEMM_B_T )
|
|
{
|
|
CV_SWAP( b_rows, b_cols, i );
|
|
CV_SWAP( b_step, b_delta, i );
|
|
}
|
|
|
|
if( flags & CV_TS_GEMM_C_T )
|
|
{
|
|
CV_SWAP( c_rows, c_cols, i );
|
|
CV_SWAP( c_step, c_delta, i );
|
|
}
|
|
|
|
assert( a_rows == d_rows && a_cols == b_rows && b_cols == d_cols );
|
|
assert( a->data.ptr != d->data.ptr && b->data.ptr != d->data.ptr );
|
|
|
|
if( c )
|
|
{
|
|
assert( CV_ARE_TYPES_EQ(a,c) && c_rows == d_rows && c_cols == d_cols );
|
|
assert( c->data.ptr != d->data.ptr || (flags & CV_TS_GEMM_C_T) == 0 );
|
|
}
|
|
|
|
if( CV_MAT_DEPTH(a->type) == CV_32F )
|
|
{
|
|
float* a_data0 = a->data.fl;
|
|
float* b_data0 = b->data.fl;
|
|
float* c_data0 = c ? c->data.fl : 0;
|
|
float* d_data = d->data.fl;
|
|
|
|
for( i = 0; i < d_rows; i++, d_data += d_step, c_data0 += c_step, a_data0 += a_step )
|
|
{
|
|
for( j = 0; j < d_cols; j++ )
|
|
{
|
|
float* a_data = a_data0;
|
|
float* b_data = b_data0 + j*b_delta;
|
|
float* c_data = c_data0 + j*c_delta;
|
|
|
|
if( cn == 1 )
|
|
{
|
|
double s = 0;
|
|
for( k = 0; k < a_cols; k++ )
|
|
{
|
|
s += ((double)a_data[0])*b_data[0];
|
|
a_data += a_delta;
|
|
b_data += b_step;
|
|
}
|
|
d_data[j] = (float)(s*alpha + (c_data ? c_data[0]*beta : 0));
|
|
}
|
|
else
|
|
{
|
|
double s_re = 0, s_im = 0;
|
|
|
|
for( k = 0; k < a_cols; k++ )
|
|
{
|
|
s_re += ((double)a_data[0])*b_data[0] - ((double)a_data[1])*b_data[1];
|
|
s_im += ((double)a_data[0])*b_data[1] + ((double)a_data[1])*b_data[0];
|
|
a_data += a_delta;
|
|
b_data += b_step;
|
|
}
|
|
|
|
s_re *= alpha;
|
|
s_im *= alpha;
|
|
|
|
if( c_data )
|
|
{
|
|
s_re += c_data[0]*beta;
|
|
s_im += c_data[1]*beta;
|
|
}
|
|
|
|
d_data[j*2] = (float)s_re;
|
|
d_data[j*2+1] = (float)s_im;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if( CV_MAT_DEPTH(a->type) == CV_64F )
|
|
{
|
|
double* a_data0 = a->data.db;
|
|
double* b_data0 = b->data.db;
|
|
double* c_data0 = c ? c->data.db : 0;
|
|
double* d_data = d->data.db;
|
|
|
|
for( i = 0; i < d_rows; i++, d_data += d_step, c_data0 += c_step, a_data0 += a_step )
|
|
{
|
|
for( j = 0; j < d_cols; j++ )
|
|
{
|
|
double* a_data = a_data0;
|
|
double* b_data = b_data0 + j*b_delta;
|
|
double* c_data = c_data0 + j*c_delta;
|
|
|
|
if( cn == 1 )
|
|
{
|
|
double s = 0;
|
|
for( k = 0; k < a_cols; k++ )
|
|
{
|
|
s += a_data[0]*b_data[0];
|
|
a_data += a_delta;
|
|
b_data += b_step;
|
|
}
|
|
d_data[j] = s*alpha + (c_data ? c_data[0]*beta : 0);
|
|
}
|
|
else
|
|
{
|
|
double s_re = 0, s_im = 0;
|
|
|
|
for( k = 0; k < a_cols; k++ )
|
|
{
|
|
s_re += a_data[0]*b_data[0] - a_data[1]*b_data[1];
|
|
s_im += a_data[0]*b_data[1] + a_data[1]*b_data[0];
|
|
a_data += a_delta;
|
|
b_data += b_step;
|
|
}
|
|
s_re *= alpha;
|
|
s_im *= alpha;
|
|
|
|
if( c_data )
|
|
{
|
|
s_re += c_data[0]*beta;
|
|
s_im += c_data[1]*beta;
|
|
}
|
|
|
|
d_data[j*2] = s_re;
|
|
d_data[j*2+1] = s_im;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
assert(0);
|
|
}
|
|
}
|
|
|
|
|
|
CvMat* cvTsSelect( const CvMat* a, CvMat* header, CvRect rect )
|
|
{
|
|
CvMat h;
|
|
int el_size;
|
|
|
|
h = cvMat( rect.height, rect.width, a->type );
|
|
el_size = CV_ELEM_SIZE(a->type);
|
|
|
|
h.data.ptr = a->data.ptr + rect.y*a->step + rect.x*el_size;
|
|
h.step = rect.height > 1 ? a->step : 0;
|
|
h.type &= ~CV_MAT_CONT_FLAG;
|
|
if( rect.height == 1 || h.step == h.cols*el_size )
|
|
h.type |= CV_MAT_CONT_FLAG;
|
|
*header = h;
|
|
return header;
|
|
}
|
|
|
|
|
|
double cvTsMinVal( int type )
|
|
{
|
|
switch( CV_MAT_DEPTH(type) )
|
|
{
|
|
case CV_8U:
|
|
return 0;
|
|
case CV_8S:
|
|
return -128;
|
|
case CV_16U:
|
|
return 0;
|
|
case CV_16S:
|
|
return -32768;
|
|
case CV_32S:
|
|
return -1000000;
|
|
case CV_32F:
|
|
return -1000.;
|
|
case CV_64F:
|
|
return -1000.;
|
|
}
|
|
return log(-1.);
|
|
}
|
|
|
|
|
|
double cvTsMaxVal( int type )
|
|
{
|
|
switch( CV_MAT_DEPTH(type) )
|
|
{
|
|
case CV_8U:
|
|
return 256;
|
|
case CV_8S:
|
|
return 128;
|
|
case CV_16U:
|
|
return 65536;
|
|
case CV_16S:
|
|
return 32768;
|
|
case CV_32S:
|
|
return 1000000;
|
|
case CV_32F:
|
|
return 1000.;
|
|
case CV_64F:
|
|
return 1000.;
|
|
}
|
|
return log(-1.);
|
|
}
|
|
|
|
|
|
void cvTsPrepareToFilter( const CvMat* a, CvMat* b, CvPoint ofs,
|
|
int border_mode, CvScalar fill_val )
|
|
{
|
|
int i, j, dir;
|
|
CvMat temp, temp2;
|
|
|
|
assert( 0 <= ofs.x && ofs.x <= b->cols - a->cols &&
|
|
0 <= ofs.y && ofs.y <= b->rows - a->rows );
|
|
|
|
cvTsSelect( b, &temp, cvRect( ofs.x, ofs.y, a->cols, a->rows ));
|
|
cvTsCopy( a, &temp, 0 );
|
|
|
|
assert( border_mode == CV_TS_BORDER_FILL ||
|
|
border_mode == CV_TS_BORDER_REPLICATE ||
|
|
border_mode == CV_TS_BORDER_REFLECT );
|
|
|
|
if( ofs.y > 0 )
|
|
{
|
|
if( border_mode == CV_TS_BORDER_FILL )
|
|
{
|
|
cvTsSelect( b, &temp, cvRect( ofs.x, 0, a->cols, ofs.y ));
|
|
cvTsAdd( 0, cvScalar(0), 0, cvScalar(0), fill_val, &temp, 0 );
|
|
}
|
|
else if( border_mode == CV_TS_BORDER_REPLICATE || a->rows == 1 )
|
|
{
|
|
cvTsSelect( b, &temp, cvRect( ofs.x, ofs.y, a->cols, 1 ));
|
|
for( i = ofs.y-1; i >= 0; i-- )
|
|
{
|
|
cvTsSelect( b, &temp2, cvRect( ofs.x, i, a->cols, 1 ));
|
|
cvTsCopy( &temp, &temp2, 0 );
|
|
}
|
|
}
|
|
else if( border_mode == CV_TS_BORDER_REFLECT )
|
|
{
|
|
j = 1; dir = 1;
|
|
for( i = ofs.y-1; i >= 0; i-- )
|
|
{
|
|
cvTsSelect( b, &temp, cvRect( ofs.x, ofs.y+j, a->cols, 1 ));
|
|
cvTsSelect( b, &temp2, cvRect( ofs.x, i, a->cols, 1 ));
|
|
cvTsCopy( &temp, &temp2, 0 );
|
|
if( (unsigned)(j + dir) >= (unsigned)a->rows )
|
|
dir = -dir;
|
|
j += dir;
|
|
}
|
|
}
|
|
}
|
|
|
|
ofs.y += a->rows;
|
|
if( ofs.y < b->rows )
|
|
{
|
|
if( border_mode == CV_TS_BORDER_FILL )
|
|
{
|
|
cvTsSelect( b, &temp, cvRect( ofs.x, ofs.y, a->cols, b->rows - ofs.y ));
|
|
cvTsAdd( 0, cvScalar(0), 0, cvScalar(0), fill_val, &temp, 0 );
|
|
}
|
|
else if( border_mode == CV_TS_BORDER_REPLICATE || a->rows == 1 )
|
|
{
|
|
cvTsSelect( b, &temp, cvRect( ofs.x, ofs.y - 1, a->cols, 1 ));
|
|
for( i = ofs.y; i < b->rows; i++ )
|
|
{
|
|
cvTsSelect( b, &temp2, cvRect( ofs.x, i, a->cols, 1 ));
|
|
cvTsCopy( &temp, &temp2, 0 );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
j = a->rows - 2; dir = -1;
|
|
for( i = ofs.y; i < b->rows; i++ )
|
|
{
|
|
cvTsSelect( b, &temp, cvRect( ofs.x, ofs.y-a->rows+j, a->cols, 1 ));
|
|
cvTsSelect( b, &temp2, cvRect( ofs.x, i, a->cols, 1 ));
|
|
cvTsCopy( &temp, &temp2, 0 );
|
|
if( (unsigned)(j + dir) >= (unsigned)a->rows )
|
|
dir = -dir;
|
|
j += dir;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( ofs.x > 0 )
|
|
{
|
|
if( border_mode == CV_TS_BORDER_FILL )
|
|
{
|
|
cvTsSelect( b, &temp, cvRect( 0, 0, ofs.x, b->rows ));
|
|
cvTsAdd( 0, cvScalar(0), 0, cvScalar(0), fill_val, &temp, 0 );
|
|
}
|
|
else if( border_mode == CV_TS_BORDER_REPLICATE || a->cols == 1 )
|
|
{
|
|
cvTsSelect( b, &temp, cvRect( ofs.x, 0, 1, b->rows ));
|
|
for( i = ofs.x-1; i >= 0; i-- )
|
|
{
|
|
cvTsSelect( b, &temp2, cvRect( i, 0, 1, b->rows ));
|
|
cvTsCopy( &temp, &temp2, 0 );
|
|
}
|
|
}
|
|
else if( border_mode == CV_TS_BORDER_REFLECT )
|
|
{
|
|
j = 1; dir = 1;
|
|
for( i = ofs.x-1; i >= 0; i-- )
|
|
{
|
|
cvTsSelect( b, &temp, cvRect( ofs.x+j, 0, 1, b->rows ));
|
|
cvTsSelect( b, &temp2, cvRect( i, 0, 1, b->rows ));
|
|
cvTsCopy( &temp, &temp2, 0 );
|
|
if( (unsigned)(j + dir) >= (unsigned)a->cols )
|
|
dir = -dir;
|
|
j += dir;
|
|
}
|
|
}
|
|
}
|
|
|
|
ofs.x += a->cols;
|
|
if( ofs.x < b->cols )
|
|
{
|
|
if( border_mode == CV_TS_BORDER_FILL )
|
|
{
|
|
cvTsSelect( b, &temp, cvRect( ofs.x, 0, b->cols - ofs.x, b->rows ));
|
|
cvTsAdd( 0, cvScalar(0), 0, cvScalar(0), fill_val, &temp, 0 );
|
|
}
|
|
else if( border_mode == CV_TS_BORDER_REPLICATE || a->cols == 1 )
|
|
{
|
|
cvTsSelect( b, &temp, cvRect( ofs.x-1, 0, 1, b->rows ));
|
|
for( i = ofs.x; i < b->cols; i++ )
|
|
{
|
|
cvTsSelect( b, &temp2, cvRect( i, 0, 1, b->rows ));
|
|
cvTsCopy( &temp, &temp2, 0 );
|
|
}
|
|
}
|
|
else if( border_mode == CV_TS_BORDER_REFLECT )
|
|
{
|
|
j = a->cols - 2; dir = -1;
|
|
for( i = ofs.x; i < b->cols; i++ )
|
|
{
|
|
cvTsSelect( b, &temp, cvRect( ofs.x-a->cols+j, 0, 1, b->rows ));
|
|
cvTsSelect( b, &temp2, cvRect( i, 0, 1, b->rows ));
|
|
cvTsCopy( &temp, &temp2, 0 );
|
|
if( (unsigned)(j + dir) >= (unsigned)a->cols )
|
|
dir = -dir;
|
|
j += dir;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void cvTsConvolve2D( const CvMat* a, CvMat* b, const CvMat* kernel, CvPoint anchor )
|
|
{
|
|
int i, j, k;
|
|
int cn, ncols, a_step;
|
|
int ker_size = kernel->rows*kernel->cols;
|
|
int* offset = (int*)malloc( ker_size*sizeof(offset[0]));
|
|
float* k_data = (float*)malloc( ker_size*sizeof(k_data[0]));
|
|
int all_same = 1;
|
|
float first = kernel->data.fl[0];
|
|
uchar *a_data, *b_data;
|
|
|
|
cn = CV_MAT_CN(a->type);
|
|
ncols = b->cols*cn;
|
|
a_step = a->step / CV_ELEM_SIZE(a->type & ~CV_MAT_CN_MASK);
|
|
|
|
assert( a->cols == b->cols + kernel->cols - 1 &&
|
|
a->rows == b->rows + kernel->rows - 1 && CV_ARE_TYPES_EQ( a, b ) );
|
|
assert( CV_MAT_TYPE(kernel->type) == CV_32FC1 );
|
|
assert( 0 <= anchor.x && anchor.x < kernel->cols &&
|
|
0 <= anchor.y && anchor.y < kernel->rows );
|
|
|
|
for( i = 0, k = 0; i < kernel->rows; i++ )
|
|
for( j = 0; j < kernel->cols; j++ )
|
|
{
|
|
float f = ((float*)(kernel->data.ptr + kernel->step*i))[j];
|
|
if( f )
|
|
{
|
|
k_data[k] = f;
|
|
offset[k++] = (i - anchor.y)*a_step + (j - anchor.x)*cn;
|
|
}
|
|
if( f != first )
|
|
all_same = 0;
|
|
}
|
|
|
|
ker_size = k;
|
|
a_data = a->data.ptr + a->step*anchor.y + CV_ELEM_SIZE(a->type)*anchor.x;
|
|
b_data = b->data.ptr;
|
|
|
|
for( i = 0; i < b->rows; i++, a_data += a->step, b_data += b->step )
|
|
{
|
|
switch( CV_MAT_DEPTH(a->type) )
|
|
{
|
|
case CV_8U:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
double s = 0;
|
|
int val;
|
|
for( k = 0; k < ker_size; k++ )
|
|
s += ((uchar*)a_data)[j+offset[k]]*k_data[k];
|
|
val = cvRound(s);
|
|
((uchar*)b_data)[j] = CV_CAST_8U(val);
|
|
}
|
|
break;
|
|
case CV_8S:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
double s = 0;
|
|
int val;
|
|
for( k = 0; k < ker_size; k++ )
|
|
s += ((schar*)a_data)[j+offset[k]]*k_data[k];
|
|
val = cvRound(s);
|
|
((schar*)b_data)[j] = CV_CAST_8S(val);
|
|
}
|
|
break;
|
|
case CV_16U:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
double s = 0;
|
|
int val;
|
|
for( k = 0; k < ker_size; k++ )
|
|
s += ((ushort*)a_data)[j+offset[k]]*k_data[k];
|
|
val = cvRound(s);
|
|
((ushort*)b_data)[j] = CV_CAST_16U(val);
|
|
}
|
|
break;
|
|
case CV_16S:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
double s = 0;
|
|
int val;
|
|
for( k = 0; k < ker_size; k++ )
|
|
s += ((short*)a_data)[j+offset[k]]*k_data[k];
|
|
val = cvRound(s);
|
|
((short*)b_data)[j] = CV_CAST_16S(val);
|
|
}
|
|
break;
|
|
case CV_32S:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
double s = 0;
|
|
for( k = 0; k < ker_size; k++ )
|
|
s += ((int*)a_data)[j+offset[k]]*k_data[k];
|
|
((int*)b_data)[j] = cvRound(s);
|
|
}
|
|
break;
|
|
case CV_32F:
|
|
if( !all_same )
|
|
{
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
double s = 0;
|
|
for( k = 0; k < ker_size; k++ )
|
|
s += (double)((float*)a_data)[j+offset[k]]*k_data[k];
|
|
((float*)b_data)[j] = (float)s;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// special branch to speedup feature selection and blur tests
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
double s = 0;
|
|
for( k = 0; k < ker_size; k++ )
|
|
s += (double)((float*)a_data)[j+offset[k]];
|
|
((float*)b_data)[j] = (float)(s*first);
|
|
}
|
|
}
|
|
break;
|
|
case CV_64F:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
double s = 0;
|
|
for( k = 0; k < ker_size; k++ )
|
|
s += ((double*)a_data)[j+offset[k]]*k_data[k];
|
|
((double*)b_data)[j] = (double)s;
|
|
}
|
|
break;
|
|
default:
|
|
assert(0);
|
|
}
|
|
}
|
|
|
|
free( offset );
|
|
free( k_data );
|
|
}
|
|
|
|
|
|
void cvTsMinMaxFilter( const CvMat* a, CvMat* b, const IplConvKernel* kernel, int op_type )
|
|
{
|
|
int i, j, k;
|
|
int cn, ncols, a_step;
|
|
int ker_size = kernel->nRows*kernel->nCols;
|
|
int* offset = (int*)malloc( ker_size*sizeof(offset[0]));
|
|
int calc_max = op_type != 0;
|
|
uchar *a_data, *b_data;
|
|
|
|
cn = CV_MAT_CN(a->type);
|
|
ncols = b->cols*cn;
|
|
a_step = a->step / CV_ELEM_SIZE(a->type & ~CV_MAT_CN_MASK);
|
|
|
|
assert( a->cols == b->cols + kernel->nCols - 1 &&
|
|
a->rows == b->rows + kernel->nRows - 1 && CV_ARE_TYPES_EQ( a, b ) );
|
|
assert( 0 <= kernel->anchorX && kernel->anchorX < kernel->nCols &&
|
|
0 <= kernel->anchorY && kernel->anchorY < kernel->nRows );
|
|
|
|
for( i = 0, k = 0; i < kernel->nRows; i++ )
|
|
for( j = 0; j < kernel->nCols; j++ )
|
|
{
|
|
if( !kernel->values || kernel->values[i*kernel->nCols + j] )
|
|
offset[k++] = (i - kernel->anchorY)*a_step + (j - kernel->anchorX)*cn;
|
|
}
|
|
|
|
if( k == 0 )
|
|
offset[k++] = 0;
|
|
|
|
ker_size = k;
|
|
|
|
a_data = a->data.ptr + kernel->anchorY*a->step + kernel->anchorX*CV_ELEM_SIZE(a->type);
|
|
b_data = b->data.ptr;
|
|
|
|
for( i = 0; i < b->rows; i++, a_data += a->step, b_data += b->step )
|
|
{
|
|
switch( CV_MAT_DEPTH(a->type) )
|
|
{
|
|
case CV_8U:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int m = ((uchar*)a_data)[j+offset[0]];
|
|
for( k = 1; k < ker_size; k++ )
|
|
{
|
|
int v = ((uchar*)a_data)[j+offset[k]];
|
|
if( calc_max )
|
|
{
|
|
if( m < v )
|
|
m = v;
|
|
}
|
|
else if( m > v )
|
|
m = v;
|
|
}
|
|
((uchar*)b_data)[j] = (uchar)m;
|
|
}
|
|
break;
|
|
case CV_16U:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int m = ((ushort*)a_data)[j+offset[0]];
|
|
for( k = 1; k < ker_size; k++ )
|
|
{
|
|
int v = ((ushort*)a_data)[j+offset[k]];
|
|
if( calc_max )
|
|
{
|
|
if( m < v )
|
|
m = v;
|
|
}
|
|
else if( m > v )
|
|
m = v;
|
|
}
|
|
((ushort*)b_data)[j] = (ushort)m;
|
|
}
|
|
break;
|
|
case CV_16S:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int m = ((short*)a_data)[j+offset[0]];
|
|
for( k = 1; k < ker_size; k++ )
|
|
{
|
|
int v = ((short*)a_data)[j+offset[k]];
|
|
if( calc_max )
|
|
{
|
|
if( m < v )
|
|
m = v;
|
|
}
|
|
else if( m > v )
|
|
m = v;
|
|
}
|
|
((short*)b_data)[j] = (short)m;
|
|
}
|
|
break;
|
|
case CV_32S:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
int m = ((int*)a_data)[j+offset[0]];
|
|
for( k = 1; k < ker_size; k++ )
|
|
{
|
|
int v = ((int*)a_data)[j+offset[k]];
|
|
if( calc_max )
|
|
{
|
|
if( m < v )
|
|
m = v;
|
|
}
|
|
else if( m > v )
|
|
m = v;
|
|
}
|
|
((int*)b_data)[j] = m;
|
|
}
|
|
break;
|
|
case CV_32F:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
float m = ((float*)a_data)[j+offset[0]];
|
|
for( k = 1; k < ker_size; k++ )
|
|
{
|
|
float v = ((float*)a_data)[j+offset[k]];
|
|
if( calc_max )
|
|
{
|
|
if( m < v )
|
|
m = v;
|
|
}
|
|
else if( m > v )
|
|
m = v;
|
|
}
|
|
((float*)b_data)[j] = (float)m;
|
|
}
|
|
break;
|
|
case CV_64F:
|
|
for( j = 0; j < ncols; j++ )
|
|
{
|
|
double m = ((double*)a_data)[j+offset[0]];
|
|
for( k = 1; k < ker_size; k++ )
|
|
{
|
|
double v = ((double*)a_data)[j+offset[k]];
|
|
if( calc_max )
|
|
{
|
|
if( m < v )
|
|
m = v;
|
|
}
|
|
else if( m > v )
|
|
m = v;
|
|
}
|
|
((double*)b_data)[j] = (double)m;
|
|
}
|
|
break;
|
|
default:
|
|
assert(0);
|
|
}
|
|
}
|
|
|
|
free( offset );
|
|
}
|
|
|
|
|
|
double cvTsCrossCorr( const CvMat* a, const CvMat* b )
|
|
{
|
|
int i, j;
|
|
int cn, ncols;
|
|
double s = 0;
|
|
|
|
cn = CV_MAT_CN(a->type);
|
|
ncols = a->cols*cn;
|
|
|
|
assert( CV_ARE_SIZES_EQ( a, b ) && CV_ARE_TYPES_EQ( a, b ) );
|
|
for( i = 0; i < a->rows; i++ )
|
|
{
|
|
uchar* a_data = a->data.ptr + a->step*i;
|
|
uchar* b_data = b->data.ptr + b->step*i;
|
|
|
|
switch( CV_MAT_DEPTH(a->type) )
|
|
{
|
|
case CV_8U:
|
|
for( j = 0; j < ncols; j++ )
|
|
s += ((uchar*)a_data)[j]*((uchar*)b_data)[j];
|
|
break;
|
|
case CV_8S:
|
|
for( j = 0; j < ncols; j++ )
|
|
s += ((schar*)a_data)[j]*((schar*)b_data)[j];
|
|
break;
|
|
case CV_16U:
|
|
for( j = 0; j < ncols; j++ )
|
|
s += (double)((ushort*)a_data)[j]*((ushort*)b_data)[j];
|
|
break;
|
|
case CV_16S:
|
|
for( j = 0; j < ncols; j++ )
|
|
s += ((short*)a_data)[j]*((short*)b_data)[j];
|
|
break;
|
|
case CV_32S:
|
|
for( j = 0; j < ncols; j++ )
|
|
s += ((double)((int*)a_data)[j])*((int*)b_data)[j];
|
|
break;
|
|
case CV_32F:
|
|
for( j = 0; j < ncols; j++ )
|
|
s += ((double)((float*)a_data)[j])*((float*)b_data)[j];
|
|
break;
|
|
case CV_64F:
|
|
for( j = 0; j < ncols; j++ )
|
|
s += ((double*)a_data)[j]*((double*)b_data)[j];
|
|
break;
|
|
default:
|
|
assert(0);
|
|
return log(-1.);
|
|
}
|
|
}
|
|
|
|
return s;
|
|
}
|
|
|
|
|
|
void cvTsTransform( const CvMat* a, CvMat* b, const CvMat* transmat, const CvMat* shift )
|
|
{
|
|
int i, j, k, cols, dst_cols;
|
|
int cn, dst_cn, depth, mat_depth, shiftstep;
|
|
double mat[20], *buf, *dst_buf;
|
|
|
|
cn = CV_MAT_CN(a->type);
|
|
dst_cn = CV_MAT_CN(b->type);
|
|
depth = CV_MAT_DEPTH(a->type);
|
|
mat_depth = CV_MAT_DEPTH(transmat->type);
|
|
cols = transmat->cols;
|
|
|
|
// prepare cn x (cn + 1) transform matrix
|
|
if( mat_depth == CV_32F )
|
|
{
|
|
shiftstep = shift && shift->rows > 1 ? shift->step/sizeof(float) : 1;
|
|
for( i = 0; i < transmat->rows; i++ )
|
|
{
|
|
mat[i*(cn+1) + cn] = 0.;
|
|
for( j = 0; j < cols; j++ )
|
|
mat[i*(cn+1) + j] = ((float*)(transmat->data.ptr + transmat->step*i))[j];
|
|
if( shift )
|
|
mat[i*(cn+1) + cn] = shift->data.fl[i*shiftstep];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
assert( mat_depth == CV_64F );
|
|
|
|
shiftstep = shift && shift->rows > 1 ? shift->step/sizeof(double) : 1;
|
|
for( i = 0; i < transmat->rows; i++ )
|
|
{
|
|
mat[i*(cn+1) + cn] = 0.;
|
|
for( j = 0; j < cols; j++ )
|
|
mat[i*(cn+1) + j] = ((double*)(transmat->data.ptr + transmat->step*i))[j];
|
|
if( shift )
|
|
mat[i*(cn+1) + cn] = shift->data.db[i*shiftstep];
|
|
}
|
|
}
|
|
|
|
// transform data
|
|
cols = a->cols * cn;
|
|
dst_cols = a->cols * dst_cn;
|
|
buf = (double*)cvStackAlloc( cols * sizeof(double) );
|
|
dst_buf = (double*)cvStackAlloc( dst_cols * sizeof(double) );
|
|
|
|
for( i = 0; i < a->rows; i++ )
|
|
{
|
|
uchar* src = a->data.ptr + i*a->step;
|
|
uchar* dst = b->data.ptr + i*b->step;
|
|
double* _dst = dst_buf;
|
|
|
|
switch( depth )
|
|
{
|
|
case CV_8U:
|
|
for( j = 0; j < cols; j++ )
|
|
buf[j] = ((uchar*)src)[j];
|
|
break;
|
|
case CV_16U:
|
|
for( j = 0; j < cols; j++ )
|
|
buf[j] = ((ushort*)src)[j];
|
|
break;
|
|
case CV_16S:
|
|
for( j = 0; j < cols; j++ )
|
|
buf[j] = ((short*)src)[j];
|
|
break;
|
|
case CV_32S:
|
|
for( j = 0; j < cols; j++ )
|
|
buf[j] = ((int*)src)[j];
|
|
break;
|
|
case CV_32F:
|
|
for( j = 0; j < cols; j++ )
|
|
buf[j] = ((float*)src)[j];
|
|
break;
|
|
case CV_64F:
|
|
for( j = 0; j < cols; j++ )
|
|
buf[j] = ((double*)src)[j];
|
|
break;
|
|
default:
|
|
assert(0);
|
|
}
|
|
|
|
switch( cn )
|
|
{
|
|
case 1:
|
|
for( j = 0; j < cols; j++, _dst += dst_cn )
|
|
for( k = 0; k < dst_cn; k++ )
|
|
_dst[k] = buf[j]*mat[2*k] + mat[2*k+1];
|
|
break;
|
|
case 2:
|
|
for( j = 0; j < cols; j += 2, _dst += dst_cn )
|
|
for( k = 0; k < dst_cn; k++ )
|
|
_dst[k] = buf[j]*mat[3*k] + buf[j+1]*mat[3*k+1] + mat[3*k+2];
|
|
break;
|
|
case 3:
|
|
for( j = 0; j < cols; j += 3, _dst += dst_cn )
|
|
for( k = 0; k < dst_cn; k++ )
|
|
_dst[k] = buf[j]*mat[4*k] + buf[j+1]*mat[4*k+1] +
|
|
buf[j+2]*mat[4*k+2] + mat[4*k+3];
|
|
break;
|
|
case 4:
|
|
for( j = 0; j < cols; j += 4, _dst += dst_cn )
|
|
for( k = 0; k < dst_cn; k++ )
|
|
_dst[k] = buf[j]*mat[5*k] + buf[j+1]*mat[5*k+1] +
|
|
buf[j+2]*mat[5*k+2] + buf[j+3]*mat[5*k+3] + mat[5*k+4];
|
|
break;
|
|
default:
|
|
assert(0);
|
|
}
|
|
|
|
switch( depth )
|
|
{
|
|
case CV_8U:
|
|
for( j = 0; j < dst_cols; j++ )
|
|
{
|
|
int val = cvRound(dst_buf[j]);
|
|
((uchar*)dst)[j] = CV_CAST_8U(val);
|
|
}
|
|
break;
|
|
case CV_16U:
|
|
for( j = 0; j < dst_cols; j++ )
|
|
{
|
|
int val = cvRound(dst_buf[j]);
|
|
((ushort*)dst)[j] = CV_CAST_16U(val);
|
|
}
|
|
break;
|
|
case CV_16S:
|
|
for( j = 0; j < dst_cols; j++ )
|
|
{
|
|
int val = cvRound(dst_buf[j]);
|
|
((short*)dst)[j] = CV_CAST_16S(val);
|
|
}
|
|
break;
|
|
case CV_32S:
|
|
for( j = 0; j < dst_cols; j++ )
|
|
((int*)dst)[j] = cvRound(dst_buf[j]);
|
|
break;
|
|
case CV_32F:
|
|
for( j = 0; j < dst_cols; j++ )
|
|
((float*)dst)[j] = (float)dst_buf[j];
|
|
break;
|
|
case CV_64F:
|
|
for( j = 0; j < dst_cols; j++ )
|
|
((double*)dst)[j] = dst_buf[j];
|
|
break;
|
|
default:
|
|
assert(0);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
CvMat* cvTsTranspose( const CvMat* a, CvMat* b )
|
|
{
|
|
int i, j, k, rows, cols, elem_size;
|
|
uchar *a_data, *b_data;
|
|
int a_step, b_step;
|
|
|
|
elem_size = CV_ELEM_SIZE(a->type);
|
|
rows = a->rows;
|
|
cols = a->cols;
|
|
|
|
assert( a->rows == b->cols && a->cols == b->rows && CV_ARE_TYPES_EQ(a,b) );
|
|
a_data = a->data.ptr;
|
|
a_step = a->step;
|
|
b_data = b->data.ptr;
|
|
b_step = b->step;
|
|
|
|
if( rows == cols )
|
|
{
|
|
for( i = 0; i < rows; i++ )
|
|
{
|
|
for( j = 0; j <= i; j++ )
|
|
{
|
|
uchar* a_ij = a_data + a_step*i + elem_size*j;
|
|
uchar* a_ji = a_data + a_step*j + elem_size*i;
|
|
uchar* b_ij = b_data + b_step*i + elem_size*j;
|
|
uchar* b_ji = b_data + b_step*j + elem_size*i;
|
|
for( k = 0; k < elem_size; k++ )
|
|
{
|
|
uchar t0 = a_ij[k];
|
|
uchar t1 = a_ji[k];
|
|
b_ji[k] = t0;
|
|
b_ij[k] = t1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for( i = 0; i < cols; i++ )
|
|
{
|
|
for( j = 0; j < rows; j++ )
|
|
{
|
|
uchar* a_ji = a_data + a_step*j + elem_size*i;
|
|
uchar* b_ij = b_data + b_step*i + elem_size*j;
|
|
for( k = 0; k < elem_size; k++ )
|
|
b_ij[k] = a_ji[k];
|
|
}
|
|
}
|
|
}
|
|
|
|
return b;
|
|
}
|
|
|
|
|
|
void cvTsFlip( const CvMat* a, CvMat* b, int flip_type )
|
|
{
|
|
int i, j, k, rows, cols, elem_size;
|
|
uchar *a_data, *b_data;
|
|
int a_step, b_step;
|
|
|
|
elem_size = CV_ELEM_SIZE(a->type);
|
|
rows = a->rows;
|
|
cols = a->cols*elem_size;
|
|
|
|
assert( CV_ARE_SIZES_EQ(a,b) && CV_ARE_TYPES_EQ(a,b) && a->data.ptr != b->data.ptr );
|
|
a_data = a->data.ptr;
|
|
a_step = a->step;
|
|
b_data = b->data.ptr;
|
|
b_step = b->step;
|
|
|
|
if( flip_type <= 0 )
|
|
{
|
|
a_data += a_step*(rows-1);
|
|
a_step = -a_step;
|
|
}
|
|
|
|
for( i = 0; i < rows; i++ )
|
|
{
|
|
if( flip_type == 0 )
|
|
memcpy( b_data, a_data, cols );
|
|
else
|
|
{
|
|
for( j = 0; j < cols; j += elem_size )
|
|
for( k = 0; k < elem_size; k++ )
|
|
b_data[j+k] = a_data[cols - elem_size - j + k];
|
|
}
|
|
a_data += a_step;
|
|
b_data += b_step;
|
|
}
|
|
}
|
|
|
|
|
|
void cvTsPatchZeros( CvMat* mat, double level )
|
|
{
|
|
int i, j, ncols = mat->cols * CV_MAT_CN(mat->type);
|
|
|
|
for( i = 0; i < mat->rows; i++ )
|
|
{
|
|
switch( CV_MAT_DEPTH(mat->type) )
|
|
{
|
|
case CV_32F:
|
|
{
|
|
float* data = (float*)(mat->data.ptr + i*mat->step);
|
|
for( j = 0; j < ncols; j++ )
|
|
if( fabs(data[j]) < level )
|
|
data[j] += 1;
|
|
}
|
|
break;
|
|
case CV_64F:
|
|
{
|
|
double* data = (double*)(mat->data.ptr + i*mat->step);
|
|
for( j = 0; j < ncols; j++ )
|
|
if( fabs(data[j]) < level )
|
|
data[j] += 1;
|
|
}
|
|
break;
|
|
default:
|
|
assert(0);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* End of file. */
|