commit
218b12c557
115 changed files with 22691 additions and 32667 deletions
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,792 @@ |
||||
/*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
|
||||
//
|
||||
// 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 "old_ml_precomp.hpp" |
||||
#include <ctype.h> |
||||
|
||||
#define MISS_VAL FLT_MAX |
||||
#define CV_VAR_MISS 0 |
||||
|
||||
CvTrainTestSplit::CvTrainTestSplit() |
||||
{ |
||||
train_sample_part_mode = CV_COUNT; |
||||
train_sample_part.count = -1; |
||||
mix = false; |
||||
} |
||||
|
||||
CvTrainTestSplit::CvTrainTestSplit( int _train_sample_count, bool _mix ) |
||||
{ |
||||
train_sample_part_mode = CV_COUNT; |
||||
train_sample_part.count = _train_sample_count; |
||||
mix = _mix; |
||||
} |
||||
|
||||
CvTrainTestSplit::CvTrainTestSplit( float _train_sample_portion, bool _mix ) |
||||
{ |
||||
train_sample_part_mode = CV_PORTION; |
||||
train_sample_part.portion = _train_sample_portion; |
||||
mix = _mix; |
||||
} |
||||
|
||||
////////////////
|
||||
|
||||
CvMLData::CvMLData() |
||||
{ |
||||
values = missing = var_types = var_idx_mask = response_out = var_idx_out = var_types_out = 0; |
||||
train_sample_idx = test_sample_idx = 0; |
||||
header_lines_number = 0; |
||||
sample_idx = 0; |
||||
response_idx = -1; |
||||
|
||||
train_sample_count = -1; |
||||
|
||||
delimiter = ','; |
||||
miss_ch = '?'; |
||||
//flt_separator = '.';
|
||||
|
||||
rng = &cv::theRNG(); |
||||
} |
||||
|
||||
CvMLData::~CvMLData() |
||||
{ |
||||
clear(); |
||||
} |
||||
|
||||
void CvMLData::free_train_test_idx() |
||||
{ |
||||
cvReleaseMat( &train_sample_idx ); |
||||
cvReleaseMat( &test_sample_idx ); |
||||
sample_idx = 0; |
||||
} |
||||
|
||||
void CvMLData::clear() |
||||
{ |
||||
class_map.clear(); |
||||
|
||||
cvReleaseMat( &values ); |
||||
cvReleaseMat( &missing ); |
||||
cvReleaseMat( &var_types ); |
||||
cvReleaseMat( &var_idx_mask ); |
||||
|
||||
cvReleaseMat( &response_out ); |
||||
cvReleaseMat( &var_idx_out ); |
||||
cvReleaseMat( &var_types_out ); |
||||
|
||||
free_train_test_idx(); |
||||
|
||||
total_class_count = 0; |
||||
|
||||
response_idx = -1; |
||||
|
||||
train_sample_count = -1; |
||||
} |
||||
|
||||
|
||||
void CvMLData::set_header_lines_number( int idx ) |
||||
{ |
||||
header_lines_number = std::max(0, idx); |
||||
} |
||||
|
||||
int CvMLData::get_header_lines_number() const |
||||
{ |
||||
return header_lines_number; |
||||
} |
||||
|
||||
static char *fgets_chomp(char *str, int n, FILE *stream) |
||||
{ |
||||
char *head = fgets(str, n, stream); |
||||
if( head ) |
||||
{ |
||||
for(char *tail = head + strlen(head) - 1; tail >= head; --tail) |
||||
{ |
||||
if( *tail != '\r' && *tail != '\n' ) |
||||
break; |
||||
*tail = '\0'; |
||||
} |
||||
} |
||||
return head; |
||||
} |
||||
|
||||
|
||||
int CvMLData::read_csv(const char* filename) |
||||
{ |
||||
const int M = 1000000; |
||||
const char str_delimiter[3] = { ' ', delimiter, '\0' }; |
||||
FILE* file = 0; |
||||
CvMemStorage* storage; |
||||
CvSeq* seq; |
||||
char *ptr; |
||||
float* el_ptr; |
||||
CvSeqReader reader; |
||||
int cols_count = 0; |
||||
uchar *var_types_ptr = 0; |
||||
|
||||
clear(); |
||||
|
||||
file = fopen( filename, "rt" ); |
||||
|
||||
if( !file ) |
||||
return -1; |
||||
|
||||
std::vector<char> _buf(M); |
||||
char* buf = &_buf[0]; |
||||
|
||||
// skip header lines
|
||||
for( int i = 0; i < header_lines_number; i++ ) |
||||
{ |
||||
if( fgets( buf, M, file ) == 0 ) |
||||
{ |
||||
fclose(file); |
||||
return -1; |
||||
} |
||||
} |
||||
|
||||
// read the first data line and determine the number of variables
|
||||
if( !fgets_chomp( buf, M, file )) |
||||
{ |
||||
fclose(file); |
||||
return -1; |
||||
} |
||||
|
||||
ptr = buf; |
||||
while( *ptr == ' ' ) |
||||
ptr++; |
||||
for( ; *ptr != '\0'; ) |
||||
{ |
||||
if(*ptr == delimiter || *ptr == ' ') |
||||
{ |
||||
cols_count++; |
||||
ptr++; |
||||
while( *ptr == ' ' ) ptr++; |
||||
} |
||||
else |
||||
ptr++; |
||||
} |
||||
|
||||
cols_count++; |
||||
|
||||
if ( cols_count == 0) |
||||
{ |
||||
fclose(file); |
||||
return -1; |
||||
} |
||||
|
||||
// create temporary memory storage to store the whole database
|
||||
el_ptr = new float[cols_count]; |
||||
storage = cvCreateMemStorage(); |
||||
seq = cvCreateSeq( 0, sizeof(*seq), cols_count*sizeof(float), storage ); |
||||
|
||||
var_types = cvCreateMat( 1, cols_count, CV_8U ); |
||||
cvZero( var_types ); |
||||
var_types_ptr = var_types->data.ptr; |
||||
|
||||
for(;;) |
||||
{ |
||||
char *token = NULL; |
||||
int type; |
||||
token = strtok(buf, str_delimiter); |
||||
if (!token) |
||||
break; |
||||
for (int i = 0; i < cols_count-1; i++) |
||||
{ |
||||
str_to_flt_elem( token, el_ptr[i], type); |
||||
var_types_ptr[i] |= type; |
||||
token = strtok(NULL, str_delimiter); |
||||
if (!token) |
||||
{ |
||||
fclose(file); |
||||
delete [] el_ptr; |
||||
return -1; |
||||
} |
||||
} |
||||
str_to_flt_elem( token, el_ptr[cols_count-1], type); |
||||
var_types_ptr[cols_count-1] |= type; |
||||
cvSeqPush( seq, el_ptr ); |
||||
if( !fgets_chomp( buf, M, file ) ) |
||||
break; |
||||
} |
||||
fclose(file); |
||||
|
||||
values = cvCreateMat( seq->total, cols_count, CV_32FC1 ); |
||||
missing = cvCreateMat( seq->total, cols_count, CV_8U ); |
||||
var_idx_mask = cvCreateMat( 1, values->cols, CV_8UC1 ); |
||||
cvSet( var_idx_mask, cvRealScalar(1) ); |
||||
train_sample_count = seq->total; |
||||
|
||||
cvStartReadSeq( seq, &reader ); |
||||
for(int i = 0; i < seq->total; i++ ) |
||||
{ |
||||
const float* sdata = (float*)reader.ptr; |
||||
float* ddata = values->data.fl + cols_count*i; |
||||
uchar* dm = missing->data.ptr + cols_count*i; |
||||
|
||||
for( int j = 0; j < cols_count; j++ ) |
||||
{ |
||||
ddata[j] = sdata[j]; |
||||
dm[j] = ( fabs( MISS_VAL - sdata[j] ) <= FLT_EPSILON ); |
||||
} |
||||
CV_NEXT_SEQ_ELEM( seq->elem_size, reader ); |
||||
} |
||||
|
||||
if ( cvNorm( missing, 0, CV_L1 ) <= FLT_EPSILON ) |
||||
cvReleaseMat( &missing ); |
||||
|
||||
cvReleaseMemStorage( &storage ); |
||||
delete []el_ptr; |
||||
return 0; |
||||
} |
||||
|
||||
const CvMat* CvMLData::get_values() const |
||||
{ |
||||
return values; |
||||
} |
||||
|
||||
const CvMat* CvMLData::get_missing() const |
||||
{ |
||||
CV_FUNCNAME( "CvMLData::get_missing" ); |
||||
__BEGIN__; |
||||
|
||||
if ( !values ) |
||||
CV_ERROR( CV_StsInternal, "data is empty" ); |
||||
|
||||
__END__; |
||||
|
||||
return missing; |
||||
} |
||||
|
||||
const std::map<cv::String, int>& CvMLData::get_class_labels_map() const |
||||
{ |
||||
return class_map; |
||||
} |
||||
|
||||
void CvMLData::str_to_flt_elem( const char* token, float& flt_elem, int& type) |
||||
{ |
||||
|
||||
char* stopstring = NULL; |
||||
flt_elem = (float)strtod( token, &stopstring ); |
||||
assert( stopstring ); |
||||
type = CV_VAR_ORDERED; |
||||
if ( *stopstring == miss_ch && strlen(stopstring) == 1 ) // missed value
|
||||
{ |
||||
flt_elem = MISS_VAL; |
||||
type = CV_VAR_MISS; |
||||
} |
||||
else |
||||
{ |
||||
if ( (*stopstring != 0) && (*stopstring != '\n') && (strcmp(stopstring, "\r\n") != 0) ) // class label
|
||||
{ |
||||
int idx = class_map[token]; |
||||
if ( idx == 0) |
||||
{ |
||||
total_class_count++; |
||||
idx = total_class_count; |
||||
class_map[token] = idx; |
||||
} |
||||
flt_elem = (float)idx; |
||||
type = CV_VAR_CATEGORICAL; |
||||
} |
||||
} |
||||
} |
||||
|
||||
void CvMLData::set_delimiter(char ch) |
||||
{ |
||||
CV_FUNCNAME( "CvMLData::set_delimited" ); |
||||
__BEGIN__; |
||||
|
||||
if (ch == miss_ch /*|| ch == flt_separator*/) |
||||
CV_ERROR(CV_StsBadArg, "delimited, miss_character and flt_separator must be different"); |
||||
|
||||
delimiter = ch; |
||||
|
||||
__END__; |
||||
} |
||||
|
||||
char CvMLData::get_delimiter() const |
||||
{ |
||||
return delimiter; |
||||
} |
||||
|
||||
void CvMLData::set_miss_ch(char ch) |
||||
{ |
||||
CV_FUNCNAME( "CvMLData::set_miss_ch" ); |
||||
__BEGIN__; |
||||
|
||||
if (ch == delimiter/* || ch == flt_separator*/) |
||||
CV_ERROR(CV_StsBadArg, "delimited, miss_character and flt_separator must be different"); |
||||
|
||||
miss_ch = ch; |
||||
|
||||
__END__; |
||||
} |
||||
|
||||
char CvMLData::get_miss_ch() const |
||||
{ |
||||
return miss_ch; |
||||
} |
||||
|
||||
void CvMLData::set_response_idx( int idx ) |
||||
{ |
||||
CV_FUNCNAME( "CvMLData::set_response_idx" ); |
||||
__BEGIN__; |
||||
|
||||
if ( !values ) |
||||
CV_ERROR( CV_StsInternal, "data is empty" ); |
||||
|
||||
if ( idx >= values->cols) |
||||
CV_ERROR( CV_StsBadArg, "idx value is not correct" ); |
||||
|
||||
if ( response_idx >= 0 ) |
||||
chahge_var_idx( response_idx, true ); |
||||
if ( idx >= 0 ) |
||||
chahge_var_idx( idx, false ); |
||||
response_idx = idx; |
||||
|
||||
__END__; |
||||
} |
||||
|
||||
int CvMLData::get_response_idx() const |
||||
{ |
||||
CV_FUNCNAME( "CvMLData::get_response_idx" ); |
||||
__BEGIN__; |
||||
|
||||
if ( !values ) |
||||
CV_ERROR( CV_StsInternal, "data is empty" ); |
||||
__END__; |
||||
return response_idx; |
||||
} |
||||
|
||||
void CvMLData::change_var_type( int var_idx, int type ) |
||||
{ |
||||
CV_FUNCNAME( "CvMLData::change_var_type" ); |
||||
__BEGIN__; |
||||
|
||||
int var_count = 0; |
||||
|
||||
if ( !values ) |
||||
CV_ERROR( CV_StsInternal, "data is empty" ); |
||||
|
||||
var_count = values->cols; |
||||
|
||||
if ( var_idx < 0 || var_idx >= var_count) |
||||
CV_ERROR( CV_StsBadArg, "var_idx is not correct" ); |
||||
|
||||
if ( type != CV_VAR_ORDERED && type != CV_VAR_CATEGORICAL) |
||||
CV_ERROR( CV_StsBadArg, "type is not correct" ); |
||||
|
||||
assert( var_types ); |
||||
if ( var_types->data.ptr[var_idx] == CV_VAR_CATEGORICAL && type == CV_VAR_ORDERED) |
||||
CV_ERROR( CV_StsBadArg, "it`s impossible to assign CV_VAR_ORDERED type to categorical variable" ); |
||||
var_types->data.ptr[var_idx] = (uchar)type; |
||||
|
||||
__END__; |
||||
|
||||
return; |
||||
} |
||||
|
||||
void CvMLData::set_var_types( const char* str ) |
||||
{ |
||||
CV_FUNCNAME( "CvMLData::set_var_types" ); |
||||
__BEGIN__; |
||||
|
||||
const char* ord = 0, *cat = 0; |
||||
int var_count = 0, set_var_type_count = 0; |
||||
if ( !values ) |
||||
CV_ERROR( CV_StsInternal, "data is empty" ); |
||||
|
||||
var_count = values->cols; |
||||
|
||||
assert( var_types ); |
||||
|
||||
ord = strstr( str, "ord" ); |
||||
cat = strstr( str, "cat" ); |
||||
if ( !ord && !cat ) |
||||
CV_ERROR( CV_StsBadArg, "types string is not correct" ); |
||||
|
||||
if ( !ord && strlen(cat) == 3 ) // str == "cat"
|
||||
{ |
||||
cvSet( var_types, cvScalarAll(CV_VAR_CATEGORICAL) ); |
||||
return; |
||||
} |
||||
|
||||
if ( !cat && strlen(ord) == 3 ) // str == "ord"
|
||||
{ |
||||
cvSet( var_types, cvScalarAll(CV_VAR_ORDERED) ); |
||||
return; |
||||
} |
||||
|
||||
if ( ord ) // parse ord str
|
||||
{ |
||||
char* stopstring = NULL; |
||||
if ( ord[3] != '[') |
||||
CV_ERROR( CV_StsBadArg, "types string is not correct" ); |
||||
|
||||
ord += 4; // pass "ord["
|
||||
do |
||||
{ |
||||
int b1 = (int)strtod( ord, &stopstring ); |
||||
if ( *stopstring == 0 || (*stopstring != ',' && *stopstring != ']' && *stopstring != '-') ) |
||||
CV_ERROR( CV_StsBadArg, "types string is not correct" ); |
||||
ord = stopstring + 1; |
||||
if ( (stopstring[0] == ',') || (stopstring[0] == ']')) |
||||
{ |
||||
if ( var_types->data.ptr[b1] == CV_VAR_CATEGORICAL) |
||||
CV_ERROR( CV_StsBadArg, "it`s impossible to assign CV_VAR_ORDERED type to categorical variable" ); |
||||
var_types->data.ptr[b1] = CV_VAR_ORDERED; |
||||
set_var_type_count++; |
||||
} |
||||
else |
||||
{ |
||||
if ( stopstring[0] == '-') |
||||
{ |
||||
int b2 = (int)strtod( ord, &stopstring); |
||||
if ( (*stopstring == 0) || (*stopstring != ',' && *stopstring != ']') ) |
||||
CV_ERROR( CV_StsBadArg, "types string is not correct" ); |
||||
ord = stopstring + 1; |
||||
for (int i = b1; i <= b2; i++) |
||||
{ |
||||
if ( var_types->data.ptr[i] == CV_VAR_CATEGORICAL) |
||||
CV_ERROR( CV_StsBadArg, "it`s impossible to assign CV_VAR_ORDERED type to categorical variable" ); |
||||
var_types->data.ptr[i] = CV_VAR_ORDERED; |
||||
} |
||||
set_var_type_count += b2 - b1 + 1; |
||||
} |
||||
else |
||||
CV_ERROR( CV_StsBadArg, "types string is not correct" ); |
||||
|
||||
} |
||||
} |
||||
while (*stopstring != ']'); |
||||
|
||||
if ( stopstring[1] != '\0' && stopstring[1] != ',') |
||||
CV_ERROR( CV_StsBadArg, "types string is not correct" ); |
||||
} |
||||
|
||||
if ( cat ) // parse cat str
|
||||
{ |
||||
char* stopstring = NULL; |
||||
if ( cat[3] != '[') |
||||
CV_ERROR( CV_StsBadArg, "types string is not correct" ); |
||||
|
||||
cat += 4; // pass "cat["
|
||||
do |
||||
{ |
||||
int b1 = (int)strtod( cat, &stopstring ); |
||||
if ( *stopstring == 0 || (*stopstring != ',' && *stopstring != ']' && *stopstring != '-') ) |
||||
CV_ERROR( CV_StsBadArg, "types string is not correct" ); |
||||
cat = stopstring + 1; |
||||
if ( (stopstring[0] == ',') || (stopstring[0] == ']')) |
||||
{ |
||||
var_types->data.ptr[b1] = CV_VAR_CATEGORICAL; |
||||
set_var_type_count++; |
||||
} |
||||
else |
||||
{ |
||||
if ( stopstring[0] == '-') |
||||
{ |
||||
int b2 = (int)strtod( cat, &stopstring); |
||||
if ( (*stopstring == 0) || (*stopstring != ',' && *stopstring != ']') ) |
||||
CV_ERROR( CV_StsBadArg, "types string is not correct" ); |
||||
cat = stopstring + 1; |
||||
for (int i = b1; i <= b2; i++) |
||||
var_types->data.ptr[i] = CV_VAR_CATEGORICAL; |
||||
set_var_type_count += b2 - b1 + 1; |
||||
} |
||||
else |
||||
CV_ERROR( CV_StsBadArg, "types string is not correct" ); |
||||
|
||||
} |
||||
} |
||||
while (*stopstring != ']'); |
||||
|
||||
if ( stopstring[1] != '\0' && stopstring[1] != ',') |
||||
CV_ERROR( CV_StsBadArg, "types string is not correct" ); |
||||
} |
||||
|
||||
if (set_var_type_count != var_count) |
||||
CV_ERROR( CV_StsBadArg, "types string is not correct" ); |
||||
|
||||
__END__; |
||||
} |
||||
|
||||
const CvMat* CvMLData::get_var_types() |
||||
{ |
||||
CV_FUNCNAME( "CvMLData::get_var_types" ); |
||||
__BEGIN__; |
||||
|
||||
uchar *var_types_out_ptr = 0; |
||||
int avcount, vt_size; |
||||
if ( !values ) |
||||
CV_ERROR( CV_StsInternal, "data is empty" ); |
||||
|
||||
assert( var_idx_mask ); |
||||
|
||||
avcount = cvFloor( cvNorm( var_idx_mask, 0, CV_L1 ) ); |
||||
vt_size = avcount + (response_idx >= 0); |
||||
|
||||
if ( avcount == values->cols || (avcount == values->cols-1 && response_idx == values->cols-1) ) |
||||
return var_types; |
||||
|
||||
if ( !var_types_out || ( var_types_out && var_types_out->cols != vt_size ) ) |
||||
{ |
||||
cvReleaseMat( &var_types_out ); |
||||
var_types_out = cvCreateMat( 1, vt_size, CV_8UC1 ); |
||||
} |
||||
|
||||
var_types_out_ptr = var_types_out->data.ptr; |
||||
for( int i = 0; i < var_types->cols; i++) |
||||
{ |
||||
if (i == response_idx || !var_idx_mask->data.ptr[i]) continue; |
||||
*var_types_out_ptr = var_types->data.ptr[i]; |
||||
var_types_out_ptr++; |
||||
} |
||||
if ( response_idx >= 0 ) |
||||
*var_types_out_ptr = var_types->data.ptr[response_idx]; |
||||
|
||||
__END__; |
||||
|
||||
return var_types_out; |
||||
} |
||||
|
||||
int CvMLData::get_var_type( int var_idx ) const |
||||
{ |
||||
return var_types->data.ptr[var_idx]; |
||||
} |
||||
|
||||
const CvMat* CvMLData::get_responses() |
||||
{ |
||||
CV_FUNCNAME( "CvMLData::get_responses_ptr" ); |
||||
__BEGIN__; |
||||
|
||||
int var_count = 0; |
||||
|
||||
if ( !values ) |
||||
CV_ERROR( CV_StsInternal, "data is empty" ); |
||||
var_count = values->cols; |
||||
|
||||
if ( response_idx < 0 || response_idx >= var_count ) |
||||
return 0; |
||||
if ( !response_out ) |
||||
response_out = cvCreateMatHeader( values->rows, 1, CV_32FC1 ); |
||||
else |
||||
cvInitMatHeader( response_out, values->rows, 1, CV_32FC1); |
||||
cvGetCol( values, response_out, response_idx ); |
||||
|
||||
__END__; |
||||
|
||||
return response_out; |
||||
} |
||||
|
||||
void CvMLData::set_train_test_split( const CvTrainTestSplit * spl) |
||||
{ |
||||
CV_FUNCNAME( "CvMLData::set_division" ); |
||||
__BEGIN__; |
||||
|
||||
int sample_count = 0; |
||||
|
||||
if ( !values ) |
||||
CV_ERROR( CV_StsInternal, "data is empty" ); |
||||
|
||||
sample_count = values->rows; |
||||
|
||||
float train_sample_portion; |
||||
|
||||
if (spl->train_sample_part_mode == CV_COUNT) |
||||
{ |
||||
train_sample_count = spl->train_sample_part.count; |
||||
if (train_sample_count > sample_count) |
||||
CV_ERROR( CV_StsBadArg, "train samples count is not correct" ); |
||||
train_sample_count = train_sample_count<=0 ? sample_count : train_sample_count; |
||||
} |
||||
else // dtype.train_sample_part_mode == CV_PORTION
|
||||
{ |
||||
train_sample_portion = spl->train_sample_part.portion; |
||||
if ( train_sample_portion > 1) |
||||
CV_ERROR( CV_StsBadArg, "train samples count is not correct" ); |
||||
train_sample_portion = train_sample_portion <= FLT_EPSILON || |
||||
1 - train_sample_portion <= FLT_EPSILON ? 1 : train_sample_portion; |
||||
train_sample_count = std::max(1, cvFloor( train_sample_portion * sample_count )); |
||||
} |
||||
|
||||
if ( train_sample_count == sample_count ) |
||||
{ |
||||
free_train_test_idx(); |
||||
return; |
||||
} |
||||
|
||||
if ( train_sample_idx && train_sample_idx->cols != train_sample_count ) |
||||
free_train_test_idx(); |
||||
|
||||
if ( !sample_idx) |
||||
{ |
||||
int test_sample_count = sample_count- train_sample_count; |
||||
sample_idx = (int*)cvAlloc( sample_count * sizeof(sample_idx[0]) ); |
||||
for (int i = 0; i < sample_count; i++ ) |
||||
sample_idx[i] = i; |
||||
train_sample_idx = cvCreateMatHeader( 1, train_sample_count, CV_32SC1 ); |
||||
*train_sample_idx = cvMat( 1, train_sample_count, CV_32SC1, &sample_idx[0] ); |
||||
|
||||
CV_Assert(test_sample_count > 0); |
||||
test_sample_idx = cvCreateMatHeader( 1, test_sample_count, CV_32SC1 ); |
||||
*test_sample_idx = cvMat( 1, test_sample_count, CV_32SC1, &sample_idx[train_sample_count] ); |
||||
} |
||||
|
||||
mix = spl->mix; |
||||
if ( mix ) |
||||
mix_train_and_test_idx(); |
||||
|
||||
__END__; |
||||
} |
||||
|
||||
const CvMat* CvMLData::get_train_sample_idx() const |
||||
{ |
||||
CV_FUNCNAME( "CvMLData::get_train_sample_idx" ); |
||||
__BEGIN__; |
||||
|
||||
if ( !values ) |
||||
CV_ERROR( CV_StsInternal, "data is empty" ); |
||||
__END__; |
||||
|
||||
return train_sample_idx; |
||||
} |
||||
|
||||
const CvMat* CvMLData::get_test_sample_idx() const |
||||
{ |
||||
CV_FUNCNAME( "CvMLData::get_test_sample_idx" ); |
||||
__BEGIN__; |
||||
|
||||
if ( !values ) |
||||
CV_ERROR( CV_StsInternal, "data is empty" ); |
||||
__END__; |
||||
|
||||
return test_sample_idx; |
||||
} |
||||
|
||||
void CvMLData::mix_train_and_test_idx() |
||||
{ |
||||
CV_FUNCNAME( "CvMLData::mix_train_and_test_idx" ); |
||||
__BEGIN__; |
||||
|
||||
if ( !values ) |
||||
CV_ERROR( CV_StsInternal, "data is empty" ); |
||||
__END__; |
||||
|
||||
if ( !sample_idx) |
||||
return; |
||||
|
||||
if ( train_sample_count > 0 && train_sample_count < values->rows ) |
||||
{ |
||||
int n = values->rows; |
||||
for (int i = 0; i < n; i++) |
||||
{ |
||||
int a = (*rng)(n); |
||||
int b = (*rng)(n); |
||||
int t; |
||||
CV_SWAP( sample_idx[a], sample_idx[b], t ); |
||||
} |
||||
} |
||||
} |
||||
|
||||
const CvMat* CvMLData::get_var_idx() |
||||
{ |
||||
CV_FUNCNAME( "CvMLData::get_var_idx" ); |
||||
__BEGIN__; |
||||
|
||||
int avcount = 0; |
||||
|
||||
if ( !values ) |
||||
CV_ERROR( CV_StsInternal, "data is empty" ); |
||||
|
||||
assert( var_idx_mask ); |
||||
|
||||
avcount = cvFloor( cvNorm( var_idx_mask, 0, CV_L1 ) ); |
||||
int* vidx; |
||||
|
||||
if ( avcount == values->cols ) |
||||
return 0; |
||||
|
||||
if ( !var_idx_out || ( var_idx_out && var_idx_out->cols != avcount ) ) |
||||
{ |
||||
cvReleaseMat( &var_idx_out ); |
||||
var_idx_out = cvCreateMat( 1, avcount, CV_32SC1); |
||||
if ( response_idx >=0 ) |
||||
var_idx_mask->data.ptr[response_idx] = 0; |
||||
} |
||||
|
||||
vidx = var_idx_out->data.i; |
||||
|
||||
for(int i = 0; i < var_idx_mask->cols; i++) |
||||
if ( var_idx_mask->data.ptr[i] ) |
||||
{ |
||||
*vidx = i; |
||||
vidx++; |
||||
} |
||||
|
||||
__END__; |
||||
|
||||
return var_idx_out; |
||||
} |
||||
|
||||
void CvMLData::chahge_var_idx( int vi, bool state ) |
||||
{ |
||||
change_var_idx( vi, state ); |
||||
} |
||||
|
||||
void CvMLData::change_var_idx( int vi, bool state ) |
||||
{ |
||||
CV_FUNCNAME( "CvMLData::change_var_idx" ); |
||||
__BEGIN__; |
||||
|
||||
int var_count = 0; |
||||
|
||||
if ( !values ) |
||||
CV_ERROR( CV_StsInternal, "data is empty" ); |
||||
|
||||
var_count = values->cols; |
||||
|
||||
if ( vi < 0 || vi >= var_count) |
||||
CV_ERROR( CV_StsBadArg, "variable index is not correct" ); |
||||
|
||||
assert( var_idx_mask ); |
||||
var_idx_mask->data.ptr[vi] = state; |
||||
|
||||
__END__; |
||||
} |
||||
|
||||
/* End of file. */ |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,376 @@ |
||||
/*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
|
||||
//
|
||||
// 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*/
|
||||
|
||||
#ifndef __OPENCV_PRECOMP_H__ |
||||
#define __OPENCV_PRECOMP_H__ |
||||
|
||||
#include "opencv2/core.hpp" |
||||
#include "old_ml.hpp" |
||||
#include "opencv2/core/core_c.h" |
||||
#include "opencv2/core/utility.hpp" |
||||
|
||||
#include "opencv2/core/private.hpp" |
||||
|
||||
#include <assert.h> |
||||
#include <float.h> |
||||
#include <limits.h> |
||||
#include <math.h> |
||||
#include <stdlib.h> |
||||
#include <stdio.h> |
||||
#include <string.h> |
||||
#include <time.h> |
||||
|
||||
#define ML_IMPL CV_IMPL |
||||
#define __BEGIN__ __CV_BEGIN__ |
||||
#define __END__ __CV_END__ |
||||
#define EXIT __CV_EXIT__ |
||||
|
||||
#define CV_MAT_ELEM_FLAG( mat, type, comp, vect, tflag ) \ |
||||
(( tflag == CV_ROW_SAMPLE ) \
|
||||
? (CV_MAT_ELEM( mat, type, comp, vect )) \
|
||||
: (CV_MAT_ELEM( mat, type, vect, comp ))) |
||||
|
||||
/* Convert matrix to vector */ |
||||
#define ICV_MAT2VEC( mat, vdata, vstep, num ) \ |
||||
if( MIN( (mat).rows, (mat).cols ) != 1 ) \
|
||||
CV_ERROR( CV_StsBadArg, "" ); \
|
||||
(vdata) = ((mat).data.ptr); \
|
||||
if( (mat).rows == 1 ) \
|
||||
{ \
|
||||
(vstep) = CV_ELEM_SIZE( (mat).type ); \
|
||||
(num) = (mat).cols; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
(vstep) = (mat).step; \
|
||||
(num) = (mat).rows; \
|
||||
} |
||||
|
||||
/* get raw data */ |
||||
#define ICV_RAWDATA( mat, flags, rdata, sstep, cstep, m, n ) \ |
||||
(rdata) = (mat).data.ptr; \
|
||||
if( CV_IS_ROW_SAMPLE( flags ) ) \
|
||||
{ \
|
||||
(sstep) = (mat).step; \
|
||||
(cstep) = CV_ELEM_SIZE( (mat).type ); \
|
||||
(m) = (mat).rows; \
|
||||
(n) = (mat).cols; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
(cstep) = (mat).step; \
|
||||
(sstep) = CV_ELEM_SIZE( (mat).type ); \
|
||||
(n) = (mat).rows; \
|
||||
(m) = (mat).cols; \
|
||||
} |
||||
|
||||
#define ICV_IS_MAT_OF_TYPE( mat, mat_type) \ |
||||
(CV_IS_MAT( mat ) && CV_MAT_TYPE( mat->type ) == (mat_type) && \
|
||||
(mat)->cols > 0 && (mat)->rows > 0) |
||||
|
||||
/*
|
||||
uchar* data; int sstep, cstep; - trainData->data |
||||
uchar* classes; int clstep; int ncl;- trainClasses |
||||
uchar* tmask; int tmstep; int ntm; - typeMask |
||||
uchar* missed;int msstep, mcstep; -missedMeasurements... |
||||
int mm, mn; == m,n == size,dim |
||||
uchar* sidx;int sistep; - sampleIdx |
||||
uchar* cidx;int cistep; - compIdx |
||||
int k, l; == n,m == dim,size (length of cidx, sidx) |
||||
int m, n; == size,dim |
||||
*/ |
||||
#define ICV_DECLARE_TRAIN_ARGS() \ |
||||
uchar* data; \
|
||||
int sstep, cstep; \
|
||||
uchar* classes; \
|
||||
int clstep; \
|
||||
int ncl; \
|
||||
uchar* tmask; \
|
||||
int tmstep; \
|
||||
int ntm; \
|
||||
uchar* missed; \
|
||||
int msstep, mcstep; \
|
||||
int mm, mn; \
|
||||
uchar* sidx; \
|
||||
int sistep; \
|
||||
uchar* cidx; \
|
||||
int cistep; \
|
||||
int k, l; \
|
||||
int m, n; \
|
||||
\
|
||||
data = classes = tmask = missed = sidx = cidx = NULL; \
|
||||
sstep = cstep = clstep = ncl = tmstep = ntm = msstep = mcstep = mm = mn = 0; \
|
||||
sistep = cistep = k = l = m = n = 0; |
||||
|
||||
#define ICV_TRAIN_DATA_REQUIRED( param, flags ) \ |
||||
if( !ICV_IS_MAT_OF_TYPE( (param), CV_32FC1 ) ) \
|
||||
{ \
|
||||
CV_ERROR( CV_StsBadArg, "Invalid " #param " parameter" ); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
ICV_RAWDATA( *(param), (flags), data, sstep, cstep, m, n ); \
|
||||
k = n; \
|
||||
l = m; \
|
||||
} |
||||
|
||||
#define ICV_TRAIN_CLASSES_REQUIRED( param ) \ |
||||
if( !ICV_IS_MAT_OF_TYPE( (param), CV_32FC1 ) ) \
|
||||
{ \
|
||||
CV_ERROR( CV_StsBadArg, "Invalid " #param " parameter" ); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
ICV_MAT2VEC( *(param), classes, clstep, ncl ); \
|
||||
if( m != ncl ) \
|
||||
{ \
|
||||
CV_ERROR( CV_StsBadArg, "Unmatched sizes" ); \
|
||||
} \
|
||||
} |
||||
|
||||
#define ICV_ARG_NULL( param ) \ |
||||
if( (param) != NULL ) \
|
||||
{ \
|
||||
CV_ERROR( CV_StsBadArg, #param " parameter must be NULL" ); \
|
||||
} |
||||
|
||||
#define ICV_MISSED_MEASUREMENTS_OPTIONAL( param, flags ) \ |
||||
if( param ) \
|
||||
{ \
|
||||
if( !ICV_IS_MAT_OF_TYPE( param, CV_8UC1 ) ) \
|
||||
{ \
|
||||
CV_ERROR( CV_StsBadArg, "Invalid " #param " parameter" ); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
ICV_RAWDATA( *(param), (flags), missed, msstep, mcstep, mm, mn ); \
|
||||
if( mm != m || mn != n ) \
|
||||
{ \
|
||||
CV_ERROR( CV_StsBadArg, "Unmatched sizes" ); \
|
||||
} \
|
||||
} \
|
||||
} |
||||
|
||||
#define ICV_COMP_IDX_OPTIONAL( param ) \ |
||||
if( param ) \
|
||||
{ \
|
||||
if( !ICV_IS_MAT_OF_TYPE( param, CV_32SC1 ) ) \
|
||||
{ \
|
||||
CV_ERROR( CV_StsBadArg, "Invalid " #param " parameter" ); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
ICV_MAT2VEC( *(param), cidx, cistep, k ); \
|
||||
if( k > n ) \
|
||||
CV_ERROR( CV_StsBadArg, "Invalid " #param " parameter" ); \
|
||||
} \
|
||||
} |
||||
|
||||
#define ICV_SAMPLE_IDX_OPTIONAL( param ) \ |
||||
if( param ) \
|
||||
{ \
|
||||
if( !ICV_IS_MAT_OF_TYPE( param, CV_32SC1 ) ) \
|
||||
{ \
|
||||
CV_ERROR( CV_StsBadArg, "Invalid " #param " parameter" ); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
ICV_MAT2VEC( *sampleIdx, sidx, sistep, l ); \
|
||||
if( l > m ) \
|
||||
CV_ERROR( CV_StsBadArg, "Invalid " #param " parameter" ); \
|
||||
} \
|
||||
} |
||||
|
||||
/****************************************************************************************/ |
||||
#define ICV_CONVERT_FLOAT_ARRAY_TO_MATRICE( array, matrice ) \ |
||||
{ \
|
||||
CvMat a, b; \
|
||||
int dims = (matrice)->cols; \
|
||||
int nsamples = (matrice)->rows; \
|
||||
int type = CV_MAT_TYPE((matrice)->type); \
|
||||
int i, offset = dims; \
|
||||
\
|
||||
CV_ASSERT( type == CV_32FC1 || type == CV_64FC1 ); \
|
||||
offset *= ((type == CV_32FC1) ? sizeof(float) : sizeof(double));\
|
||||
\
|
||||
b = cvMat( 1, dims, CV_32FC1 ); \
|
||||
cvGetRow( matrice, &a, 0 ); \
|
||||
for( i = 0; i < nsamples; i++, a.data.ptr += offset ) \
|
||||
{ \
|
||||
b.data.fl = (float*)array[i]; \
|
||||
CV_CALL( cvConvert( &b, &a ) ); \
|
||||
} \
|
||||
} |
||||
|
||||
/****************************************************************************************\
|
||||
* Auxiliary functions declarations * |
||||
\****************************************************************************************/ |
||||
|
||||
/* Generates a set of classes centers in quantity <num_of_clusters> that are generated as
|
||||
uniform random vectors in parallelepiped, where <data> is concentrated. Vectors in |
||||
<data> should have horizontal orientation. If <centers> != NULL, the function doesn't |
||||
allocate any memory and stores generated centers in <centers>, returns <centers>. |
||||
If <centers> == NULL, the function allocates memory and creates the matrice. Centers |
||||
are supposed to be oriented horizontally. */ |
||||
CvMat* icvGenerateRandomClusterCenters( int seed, |
||||
const CvMat* data, |
||||
int num_of_clusters, |
||||
CvMat* centers CV_DEFAULT(0)); |
||||
|
||||
/* Fills the <labels> using <probs> by choosing the maximal probability. Outliers are
|
||||
fixed by <oulier_tresh> and have cluster label (-1). Function also controls that there |
||||
weren't "empty" clusters by filling empty clusters with the maximal probability vector. |
||||
If probs_sums != NULL, filles it with the sums of probabilities for each sample (it is |
||||
useful for normalizing probabilities' matrice of FCM) */ |
||||
void icvFindClusterLabels( const CvMat* probs, float outlier_thresh, float r, |
||||
const CvMat* labels ); |
||||
|
||||
typedef struct CvSparseVecElem32f |
||||
{ |
||||
int idx; |
||||
float val; |
||||
} |
||||
CvSparseVecElem32f; |
||||
|
||||
/* Prepare training data and related parameters */ |
||||
#define CV_TRAIN_STATMODEL_DEFRAGMENT_TRAIN_DATA 1 |
||||
#define CV_TRAIN_STATMODEL_SAMPLES_AS_ROWS 2 |
||||
#define CV_TRAIN_STATMODEL_SAMPLES_AS_COLUMNS 4 |
||||
#define CV_TRAIN_STATMODEL_CATEGORICAL_RESPONSE 8 |
||||
#define CV_TRAIN_STATMODEL_ORDERED_RESPONSE 16 |
||||
#define CV_TRAIN_STATMODEL_RESPONSES_ON_OUTPUT 32 |
||||
#define CV_TRAIN_STATMODEL_ALWAYS_COPY_TRAIN_DATA 64 |
||||
#define CV_TRAIN_STATMODEL_SPARSE_AS_SPARSE 128 |
||||
|
||||
int |
||||
cvPrepareTrainData( const char* /*funcname*/, |
||||
const CvMat* train_data, int tflag, |
||||
const CvMat* responses, int response_type, |
||||
const CvMat* var_idx, |
||||
const CvMat* sample_idx, |
||||
bool always_copy_data, |
||||
const float*** out_train_samples, |
||||
int* _sample_count, |
||||
int* _var_count, |
||||
int* _var_all, |
||||
CvMat** out_responses, |
||||
CvMat** out_response_map, |
||||
CvMat** out_var_idx, |
||||
CvMat** out_sample_idx=0 ); |
||||
|
||||
void |
||||
cvSortSamplesByClasses( const float** samples, const CvMat* classes, |
||||
int* class_ranges, const uchar** mask CV_DEFAULT(0) ); |
||||
|
||||
void |
||||
cvCombineResponseMaps (CvMat* _responses, |
||||
const CvMat* old_response_map, |
||||
CvMat* new_response_map, |
||||
CvMat** out_response_map); |
||||
|
||||
void |
||||
cvPreparePredictData( const CvArr* sample, int dims_all, const CvMat* comp_idx, |
||||
int class_count, const CvMat* prob, float** row_sample, |
||||
int as_sparse CV_DEFAULT(0) ); |
||||
|
||||
/* copies clustering [or batch "predict"] results
|
||||
(labels and/or centers and/or probs) back to the output arrays */ |
||||
void |
||||
cvWritebackLabels( const CvMat* labels, CvMat* dst_labels, |
||||
const CvMat* centers, CvMat* dst_centers, |
||||
const CvMat* probs, CvMat* dst_probs, |
||||
const CvMat* sample_idx, int samples_all, |
||||
const CvMat* comp_idx, int dims_all ); |
||||
#define cvWritebackResponses cvWritebackLabels |
||||
|
||||
#define XML_FIELD_NAME "_name" |
||||
CvFileNode* icvFileNodeGetChild(CvFileNode* father, const char* name); |
||||
CvFileNode* icvFileNodeGetChildArrayElem(CvFileNode* father, const char* name,int index); |
||||
CvFileNode* icvFileNodeGetNext(CvFileNode* n, const char* name); |
||||
|
||||
|
||||
void cvCheckTrainData( const CvMat* train_data, int tflag, |
||||
const CvMat* missing_mask, |
||||
int* var_all, int* sample_all ); |
||||
|
||||
CvMat* cvPreprocessIndexArray( const CvMat* idx_arr, int data_arr_size, bool check_for_duplicates=false ); |
||||
|
||||
CvMat* cvPreprocessVarType( const CvMat* type_mask, const CvMat* var_idx, |
||||
int var_all, int* response_type ); |
||||
|
||||
CvMat* cvPreprocessOrderedResponses( const CvMat* responses, |
||||
const CvMat* sample_idx, int sample_all ); |
||||
|
||||
CvMat* cvPreprocessCategoricalResponses( const CvMat* responses, |
||||
const CvMat* sample_idx, int sample_all, |
||||
CvMat** out_response_map, CvMat** class_counts=0 ); |
||||
|
||||
const float** cvGetTrainSamples( const CvMat* train_data, int tflag, |
||||
const CvMat* var_idx, const CvMat* sample_idx, |
||||
int* _var_count, int* _sample_count, |
||||
bool always_copy_data=false ); |
||||
|
||||
namespace cv |
||||
{ |
||||
struct DTreeBestSplitFinder |
||||
{ |
||||
DTreeBestSplitFinder(){ splitSize = 0, tree = 0; node = 0; } |
||||
DTreeBestSplitFinder( CvDTree* _tree, CvDTreeNode* _node); |
||||
DTreeBestSplitFinder( const DTreeBestSplitFinder& finder, Split ); |
||||
virtual ~DTreeBestSplitFinder() {} |
||||
virtual void operator()(const BlockedRange& range); |
||||
void join( DTreeBestSplitFinder& rhs ); |
||||
Ptr<CvDTreeSplit> bestSplit; |
||||
Ptr<CvDTreeSplit> split; |
||||
int splitSize; |
||||
CvDTree* tree; |
||||
CvDTreeNode* node; |
||||
}; |
||||
|
||||
struct ForestTreeBestSplitFinder : DTreeBestSplitFinder |
||||
{ |
||||
ForestTreeBestSplitFinder() : DTreeBestSplitFinder() {} |
||||
ForestTreeBestSplitFinder( CvForestTree* _tree, CvDTreeNode* _node ); |
||||
ForestTreeBestSplitFinder( const ForestTreeBestSplitFinder& finder, Split ); |
||||
virtual void operator()(const BlockedRange& range); |
||||
}; |
||||
} |
||||
|
||||
#endif /* __ML_H__ */ |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,482 @@ |
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// This is a homography decomposition implementation contributed to OpenCV
|
||||
// by Samson Yilma. It implements the homography decomposition algorithm
|
||||
// descriped in the research report:
|
||||
// Malis, E and Vargas, M, "Deeper understanding of the homography decomposition
|
||||
// for vision-based control", Research Report 6303, INRIA (2007)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2014, Samson Yilma¸ (samson_yilma@yahoo.com), 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 the copyright holders 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 "precomp.hpp" |
||||
#include <memory> |
||||
|
||||
namespace cv |
||||
{ |
||||
|
||||
namespace HomographyDecomposition |
||||
{ |
||||
|
||||
//struct to hold solutions of homography decomposition
|
||||
typedef struct _CameraMotion { |
||||
cv::Matx33d R; //!< rotation matrix
|
||||
cv::Vec3d n; //!< normal of the plane the camera is looking at
|
||||
cv::Vec3d t; //!< translation vector
|
||||
} CameraMotion; |
||||
|
||||
inline int signd(const double x) |
||||
{ |
||||
return ( x >= 0 ? 1 : -1 ); |
||||
} |
||||
|
||||
class HomographyDecomp { |
||||
|
||||
public: |
||||
HomographyDecomp() {} |
||||
virtual ~HomographyDecomp() {} |
||||
virtual void decomposeHomography(const cv::Matx33d& H, const cv::Matx33d& K, |
||||
std::vector<CameraMotion>& camMotions); |
||||
bool isRotationValid(const cv::Matx33d& R, const double epsilon=0.01); |
||||
|
||||
protected: |
||||
bool passesSameSideOfPlaneConstraint(CameraMotion& motion); |
||||
virtual void decompose(std::vector<CameraMotion>& camMotions) = 0; |
||||
const cv::Matx33d& getHnorm() const { |
||||
return _Hnorm; |
||||
} |
||||
|
||||
private: |
||||
cv::Matx33d normalize(const cv::Matx33d& H, const cv::Matx33d& K); |
||||
void removeScale(); |
||||
cv::Matx33d _Hnorm; |
||||
}; |
||||
|
||||
class HomographyDecompZhang : public HomographyDecomp { |
||||
|
||||
public: |
||||
HomographyDecompZhang():HomographyDecomp() {} |
||||
virtual ~HomographyDecompZhang() {} |
||||
|
||||
private: |
||||
virtual void decompose(std::vector<CameraMotion>& camMotions); |
||||
bool findMotionFrom_tstar_n(const cv::Vec3d& tstar, const cv::Vec3d& n, CameraMotion& motion); |
||||
}; |
||||
|
||||
class HomographyDecompInria : public HomographyDecomp { |
||||
|
||||
public: |
||||
HomographyDecompInria():HomographyDecomp() {} |
||||
virtual ~HomographyDecompInria() {} |
||||
|
||||
private: |
||||
virtual void decompose(std::vector<CameraMotion>& camMotions); |
||||
double oppositeOfMinor(const cv::Matx33d& M, const int row, const int col); |
||||
void findRmatFrom_tstar_n(const cv::Vec3d& tstar, const cv::Vec3d& n, const double v, cv::Matx33d& R); |
||||
}; |
||||
|
||||
// normalizes homography with intrinsic camera parameters
|
||||
Matx33d HomographyDecomp::normalize(const Matx33d& H, const Matx33d& K) |
||||
{ |
||||
return K.inv() * H * K; |
||||
} |
||||
|
||||
void HomographyDecomp::removeScale() |
||||
{ |
||||
Mat W; |
||||
SVD::compute(_Hnorm, W); |
||||
_Hnorm = _Hnorm * (1.0/W.at<double>(1)); |
||||
} |
||||
|
||||
/*! This checks that the input is a pure rotation matrix 'm'.
|
||||
* The conditions for this are: R' * R = I and det(R) = 1 (proper rotation matrix) |
||||
*/ |
||||
bool HomographyDecomp::isRotationValid(const Matx33d& R, const double epsilon) |
||||
{ |
||||
Matx33d RtR = R.t() * R; |
||||
Matx33d I(1,0,0, 0,1,0, 0,0,1); |
||||
if (norm(RtR, I, NORM_INF) > epsilon) |
||||
return false; |
||||
return (fabs(determinant(R) - 1.0) < epsilon); |
||||
} |
||||
|
||||
bool HomographyDecomp::passesSameSideOfPlaneConstraint(CameraMotion& motion) |
||||
{ |
||||
typedef Matx<double, 1, 1> Matx11d; |
||||
Matx31d t = Matx31d(motion.t); |
||||
Matx31d n = Matx31d(motion.n); |
||||
Matx11d proj = n.t() * motion.R.t() * t; |
||||
if ( (1 + proj(0, 0) ) <= 0 ) |
||||
return false; |
||||
return true; |
||||
} |
||||
|
||||
//!main routine to decompose homography
|
||||
void HomographyDecomp::decomposeHomography(const Matx33d& H, const cv::Matx33d& K, |
||||
std::vector<CameraMotion>& camMotions) |
||||
{ |
||||
//normalize homography matrix with intrinsic camera matrix
|
||||
_Hnorm = normalize(H, K); |
||||
//remove scale of the normalized homography
|
||||
removeScale(); |
||||
//apply decomposition
|
||||
decompose(camMotions); |
||||
} |
||||
|
||||
/* function computes R&t from tstar, and plane normal(n) using
|
||||
R = H * inv(I + tstar*transpose(n) ); |
||||
t = R * tstar; |
||||
returns true if computed R&t is a valid solution |
||||
*/ |
||||
bool HomographyDecompZhang::findMotionFrom_tstar_n(const cv::Vec3d& tstar, const cv::Vec3d& n, CameraMotion& motion) |
||||
{ |
||||
Matx31d tstar_m = Mat(tstar); |
||||
Matx31d n_m = Mat(n); |
||||
Matx33d temp = tstar_m * n_m.t(); |
||||
temp(0, 0) += 1.0; |
||||
temp(1, 1) += 1.0; |
||||
temp(2, 2) += 1.0; |
||||
motion.R = getHnorm() * temp.inv(); |
||||
motion.t = motion.R * tstar; |
||||
motion.n = n; |
||||
return passesSameSideOfPlaneConstraint(motion); |
||||
} |
||||
|
||||
void HomographyDecompZhang::decompose(std::vector<CameraMotion>& camMotions) |
||||
{ |
||||
Mat W, U, Vt; |
||||
SVD::compute(getHnorm(), W, U, Vt); |
||||
double lambda1=W.at<double>(0); |
||||
double lambda3=W.at<double>(2); |
||||
double lambda1m3 = (lambda1-lambda3); |
||||
double lambda1m3_2 = lambda1m3*lambda1m3; |
||||
double lambda1t3 = lambda1*lambda3; |
||||
|
||||
double t1 = 1.0/(2.0*lambda1t3); |
||||
double t2 = sqrt(1.0+4.0*lambda1t3/lambda1m3_2); |
||||
double t12 = t1*t2; |
||||
|
||||
double e1 = -t1 + t12; //t1*(-1.0f + t2 );
|
||||
double e3 = -t1 - t12; //t1*(-1.0f - t2);
|
||||
double e1_2 = e1*e1; |
||||
double e3_2 = e3*e3; |
||||
|
||||
double nv1p = sqrt(e1_2*lambda1m3_2 + 2*e1*(lambda1t3-1) + 1.0); |
||||
double nv3p = sqrt(e3_2*lambda1m3_2 + 2*e3*(lambda1t3-1) + 1.0); |
||||
double v1p[3], v3p[3]; |
||||
|
||||
v1p[0]=Vt.at<double>(0)*nv1p, v1p[1]=Vt.at<double>(1)*nv1p, v1p[2]=Vt.at<double>(2)*nv1p; |
||||
v3p[0]=Vt.at<double>(6)*nv3p, v3p[1]=Vt.at<double>(7)*nv3p, v3p[2]=Vt.at<double>(8)*nv3p; |
||||
|
||||
/*The eight solutions are
|
||||
(A): tstar = +- (v1p - v3p)/(e1 -e3), n = +- (e1*v3p - e3*v1p)/(e1-e3) |
||||
(B): tstar = +- (v1p + v3p)/(e1 -e3), n = +- (e1*v3p + e3*v1p)/(e1-e3) |
||||
*/ |
||||
double v1pmv3p[3], v1ppv3p[3]; |
||||
double e1v3me3v1[3], e1v3pe3v1[3]; |
||||
double inv_e1me3 = 1.0/(e1-e3); |
||||
|
||||
for(int kk=0;kk<3;++kk){ |
||||
v1pmv3p[kk] = v1p[kk]-v3p[kk]; |
||||
v1ppv3p[kk] = v1p[kk]+v3p[kk]; |
||||
} |
||||
|
||||
for(int kk=0; kk<3; ++kk){ |
||||
double e1v3 = e1*v3p[kk]; |
||||
double e3v1=e3*v1p[kk]; |
||||
e1v3me3v1[kk] = e1v3-e3v1; |
||||
e1v3pe3v1[kk] = e1v3+e3v1; |
||||
} |
||||
|
||||
Vec3d tstar_p, tstar_n; |
||||
Vec3d n_p, n_n; |
||||
|
||||
///Solution group A
|
||||
for(int kk=0; kk<3; ++kk) { |
||||
tstar_p[kk] = v1pmv3p[kk]*inv_e1me3; |
||||
tstar_n[kk] = -tstar_p[kk]; |
||||
n_p[kk] = e1v3me3v1[kk]*inv_e1me3; |
||||
n_n[kk] = -n_p[kk]; |
||||
} |
||||
|
||||
CameraMotion cmotion; |
||||
//(A) Four different combinations for solution A
|
||||
// (i) (+, +)
|
||||
if (findMotionFrom_tstar_n(tstar_p, n_p, cmotion)) |
||||
camMotions.push_back(cmotion); |
||||
|
||||
// (ii) (+, -)
|
||||
if (findMotionFrom_tstar_n(tstar_p, n_n, cmotion)) |
||||
camMotions.push_back(cmotion); |
||||
|
||||
// (iii) (-, +)
|
||||
if (findMotionFrom_tstar_n(tstar_n, n_p, cmotion)) |
||||
camMotions.push_back(cmotion); |
||||
|
||||
// (iv) (-, -)
|
||||
if (findMotionFrom_tstar_n(tstar_n, n_n, cmotion)) |
||||
camMotions.push_back(cmotion); |
||||
//////////////////////////////////////////////////////////////////
|
||||
///Solution group B
|
||||
for(int kk=0;kk<3;++kk){ |
||||
tstar_p[kk] = v1ppv3p[kk]*inv_e1me3; |
||||
tstar_n[kk] = -tstar_p[kk]; |
||||
n_p[kk] = e1v3pe3v1[kk]*inv_e1me3; |
||||
n_n[kk] = -n_p[kk]; |
||||
} |
||||
|
||||
//(B) Four different combinations for solution B
|
||||
// (i) (+, +)
|
||||
if (findMotionFrom_tstar_n(tstar_p, n_p, cmotion)) |
||||
camMotions.push_back(cmotion); |
||||
|
||||
// (ii) (+, -)
|
||||
if (findMotionFrom_tstar_n(tstar_p, n_n, cmotion)) |
||||
camMotions.push_back(cmotion); |
||||
|
||||
// (iii) (-, +)
|
||||
if (findMotionFrom_tstar_n(tstar_n, n_p, cmotion)) |
||||
camMotions.push_back(cmotion); |
||||
|
||||
// (iv) (-, -)
|
||||
if (findMotionFrom_tstar_n(tstar_n, n_n, cmotion)) |
||||
camMotions.push_back(cmotion); |
||||
} |
||||
|
||||
double HomographyDecompInria::oppositeOfMinor(const Matx33d& M, const int row, const int col) |
||||
{ |
||||
int x1 = col == 0 ? 1 : 0; |
||||
int x2 = col == 2 ? 1 : 2; |
||||
int y1 = row == 0 ? 1 : 0; |
||||
int y2 = row == 2 ? 1 : 2; |
||||
|
||||
return (M(y1, x2) * M(y2, x1) - M(y1, x1) * M(y2, x2)); |
||||
} |
||||
|
||||
//computes R = H( I - (2/v)*te_star*ne_t )
|
||||
void HomographyDecompInria::findRmatFrom_tstar_n(const cv::Vec3d& tstar, const cv::Vec3d& n, const double v, cv::Matx33d& R) |
||||
{ |
||||
Matx31d tstar_m = Matx31d(tstar); |
||||
Matx31d n_m = Matx31d(n); |
||||
Matx33d I(1.0, 0.0, 0.0, |
||||
0.0, 1.0, 0.0, |
||||
0.0, 0.0, 1.0); |
||||
|
||||
R = getHnorm() * (I - (2/v) * tstar_m * n_m.t() ); |
||||
} |
||||
|
||||
void HomographyDecompInria::decompose(std::vector<CameraMotion>& camMotions) |
||||
{ |
||||
const double epsilon = 0.001; |
||||
Matx33d S; |
||||
|
||||
//S = H'H - I
|
||||
S = getHnorm().t() * getHnorm(); |
||||
S(0, 0) -= 1.0; |
||||
S(1, 1) -= 1.0; |
||||
S(2, 2) -= 1.0; |
||||
|
||||
//check if H is rotation matrix
|
||||
if( norm(S, NORM_INF) < epsilon) { |
||||
CameraMotion motion; |
||||
motion.R = Matx33d(getHnorm()); |
||||
motion.t = Vec3d(0, 0, 0); |
||||
motion.n = Vec3d(0, 0, 0); |
||||
camMotions.push_back(motion); |
||||
return; |
||||
} |
||||
|
||||
//! Compute nvectors
|
||||
Vec3d npa, npb; |
||||
|
||||
double M00 = oppositeOfMinor(S, 0, 0); |
||||
double M11 = oppositeOfMinor(S, 1, 1); |
||||
double M22 = oppositeOfMinor(S, 2, 2); |
||||
|
||||
double rtM00 = sqrt(M00); |
||||
double rtM11 = sqrt(M11); |
||||
double rtM22 = sqrt(M22); |
||||
|
||||
double M01 = oppositeOfMinor(S, 0, 1); |
||||
double M12 = oppositeOfMinor(S, 1, 2); |
||||
double M02 = oppositeOfMinor(S, 0, 2); |
||||
|
||||
int e12 = signd(M12); |
||||
int e02 = signd(M02); |
||||
int e01 = signd(M01); |
||||
|
||||
double nS00 = abs(S(0, 0)); |
||||
double nS11 = abs(S(1, 1)); |
||||
double nS22 = abs(S(2, 2)); |
||||
|
||||
//find max( |Sii| ), i=0, 1, 2
|
||||
int indx = 0; |
||||
if(nS00 < nS11){ |
||||
indx = 1; |
||||
if( nS11 < nS22 ) |
||||
indx = 2; |
||||
} |
||||
else { |
||||
if(nS00 < nS22 ) |
||||
indx = 2; |
||||
} |
||||
|
||||
switch (indx) { |
||||
case 0: |
||||
npa[0] = S(0, 0), npb[0] = S(0, 0); |
||||
npa[1] = S(0, 1) + rtM22, npb[1] = S(0, 1) - rtM22; |
||||
npa[2] = S(0, 2) + e12 * rtM11, npb[2] = S(0, 2) - e12 * rtM11; |
||||
break; |
||||
case 1: |
||||
npa[0] = S(0, 1) + rtM22, npb[0] = S(0, 1) - rtM22; |
||||
npa[1] = S(1, 1), npb[1] = S(1, 1); |
||||
npa[2] = S(1, 2) - e02 * rtM00, npb[2] = S(1, 2) + e02 * rtM00; |
||||
break; |
||||
case 2: |
||||
npa[0] = S(0, 2) + e01 * rtM11, npb[0] = S(0, 2) - e01 * rtM11; |
||||
npa[1] = S(1, 2) + rtM00, npb[1] = S(1, 2) - rtM00; |
||||
npa[2] = S(2, 2), npb[2] = S(2, 2); |
||||
break; |
||||
default: |
||||
break; |
||||
} |
||||
|
||||
double traceS = S(0, 0) + S(1, 1) + S(2, 2); |
||||
double v = 2.0 * sqrt(1 + traceS - M00 - M11 - M22); |
||||
|
||||
double ESii = signd(S(indx, indx)) ; |
||||
double r_2 = 2 + traceS + v; |
||||
double nt_2 = 2 + traceS - v; |
||||
|
||||
double r = sqrt(r_2); |
||||
double n_t = sqrt(nt_2); |
||||
|
||||
Vec3d na = npa / norm(npa); |
||||
Vec3d nb = npb / norm(npb); |
||||
|
||||
double half_nt = 0.5 * n_t; |
||||
double esii_t_r = ESii * r; |
||||
|
||||
Vec3d ta_star = half_nt * (esii_t_r * nb - n_t * na); |
||||
Vec3d tb_star = half_nt * (esii_t_r * na - n_t * nb); |
||||
|
||||
camMotions.resize(4); |
||||
|
||||
Matx33d Ra, Rb; |
||||
Vec3d ta, tb; |
||||
|
||||
//Ra, ta, na
|
||||
findRmatFrom_tstar_n(ta_star, na, v, Ra); |
||||
ta = Ra * ta_star; |
||||
|
||||
camMotions[0].R = Ra; |
||||
camMotions[0].t = ta; |
||||
camMotions[0].n = na; |
||||
|
||||
//Ra, -ta, -na
|
||||
camMotions[1].R = Ra; |
||||
camMotions[1].t = -ta; |
||||
camMotions[1].n = -na; |
||||
|
||||
//Rb, tb, nb
|
||||
findRmatFrom_tstar_n(tb_star, nb, v, Rb); |
||||
tb = Rb * tb_star; |
||||
|
||||
camMotions[2].R = Rb; |
||||
camMotions[2].t = tb; |
||||
camMotions[2].n = nb; |
||||
|
||||
//Rb, -tb, -nb
|
||||
camMotions[3].R = Rb; |
||||
camMotions[3].t = -tb; |
||||
camMotions[3].n = -nb; |
||||
} |
||||
|
||||
} //namespace HomographyDecomposition
|
||||
|
||||
// function decomposes image-to-image homography to rotation and translation matrices
|
||||
int decomposeHomographyMat(InputArray _H, |
||||
InputArray _K, |
||||
OutputArrayOfArrays _rotations, |
||||
OutputArrayOfArrays _translations, |
||||
OutputArrayOfArrays _normals) |
||||
{ |
||||
using namespace std; |
||||
using namespace HomographyDecomposition; |
||||
|
||||
Mat H = _H.getMat().reshape(1, 3); |
||||
CV_Assert(H.cols == 3 && H.rows == 3); |
||||
|
||||
Mat K = _K.getMat().reshape(1, 3); |
||||
CV_Assert(K.cols == 3 && K.rows == 3); |
||||
|
||||
auto_ptr<HomographyDecomp> hdecomp(new HomographyDecompInria); |
||||
|
||||
vector<CameraMotion> motions; |
||||
hdecomp->decomposeHomography(H, K, motions); |
||||
|
||||
int nsols = static_cast<int>(motions.size()); |
||||
int depth = CV_64F; //double precision matrices used in CameraMotion struct
|
||||
|
||||
if (_rotations.needed()) { |
||||
_rotations.create(nsols, 1, depth); |
||||
for (int k = 0; k < nsols; ++k ) { |
||||
_rotations.getMatRef(k) = Mat(motions[k].R); |
||||
} |
||||
} |
||||
|
||||
if (_translations.needed()) { |
||||
_translations.create(nsols, 1, depth); |
||||
for (int k = 0; k < nsols; ++k ) { |
||||
_translations.getMatRef(k) = Mat(motions[k].t); |
||||
} |
||||
} |
||||
|
||||
if (_normals.needed()) { |
||||
_normals.create(nsols, 1, depth); |
||||
for (int k = 0; k < nsols; ++k ) { |
||||
_normals.getMatRef(k) = Mat(motions[k].n); |
||||
} |
||||
} |
||||
|
||||
return nsols; |
||||
} |
||||
|
||||
} //namespace cv
|
@ -0,0 +1,138 @@ |
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// This is a test file for the function decomposeHomography contributed to OpenCV
|
||||
// by Samson Yilma.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2014, Samson Yilma¸ (samson_yilma@yahoo.com), 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 the copyright holders 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 "test_precomp.hpp" |
||||
#include "opencv2/calib3d.hpp" |
||||
#include <vector> |
||||
|
||||
using namespace cv; |
||||
using namespace std; |
||||
|
||||
class CV_HomographyDecompTest: public cvtest::BaseTest { |
||||
|
||||
public: |
||||
CV_HomographyDecompTest() |
||||
{ |
||||
buildTestDataSet(); |
||||
} |
||||
|
||||
protected: |
||||
void run(int) |
||||
{ |
||||
vector<Mat> rotations; |
||||
vector<Mat> translations; |
||||
vector<Mat> normals; |
||||
|
||||
decomposeHomographyMat(_H, _K, rotations, translations, normals); |
||||
|
||||
//there should be at least 1 solution
|
||||
ASSERT_GT(static_cast<int>(rotations.size()), 0); |
||||
ASSERT_GT(static_cast<int>(translations.size()), 0); |
||||
ASSERT_GT(static_cast<int>(normals.size()), 0); |
||||
|
||||
ASSERT_EQ(rotations.size(), normals.size()); |
||||
ASSERT_EQ(translations.size(), normals.size()); |
||||
|
||||
ASSERT_TRUE(containsValidMotion(rotations, translations, normals)); |
||||
|
||||
decomposeHomographyMat(_H, _K, rotations, noArray(), noArray()); |
||||
ASSERT_GT(static_cast<int>(rotations.size()), 0); |
||||
} |
||||
|
||||
private: |
||||
|
||||
void buildTestDataSet() |
||||
{ |
||||
_K = Matx33d(640, 0.0, 320, |
||||
0, 640, 240, |
||||
0, 0, 1); |
||||
|
||||
_H = Matx33d(2.649157564634028, 4.583875997496426, 70.694447785121326, |
||||
-1.072756858861583, 3.533262150437228, 1513.656999614321649, |
||||
0.001303887589576, 0.003042206876298, 1.000000000000000 |
||||
); |
||||
|
||||
//expected solution for the given homography and intrinsic matrices
|
||||
_R = Matx33d(0.43307983549125, 0.545749113549648, -0.717356090899523, |
||||
-0.85630229674426, 0.497582023798831, -0.138414255706431, |
||||
0.281404038139784, 0.67421809131173, 0.682818960388909); |
||||
|
||||
_t = Vec3d(1.826751712278038, 1.264718492450820, 0.195080809998819); |
||||
_n = Vec3d(0.244875830334816, 0.480857890778889, 0.841909446789566); |
||||
} |
||||
|
||||
bool containsValidMotion(std::vector<Mat>& rotations, |
||||
std::vector<Mat>& translations, |
||||
std::vector<Mat>& normals |
||||
) |
||||
{ |
||||
double max_error = 1.0e-3; |
||||
|
||||
vector<Mat>::iterator riter = rotations.begin(); |
||||
vector<Mat>::iterator titer = translations.begin(); |
||||
vector<Mat>::iterator niter = normals.begin(); |
||||
|
||||
for (; |
||||
riter != rotations.end() && titer != translations.end() && niter != normals.end(); |
||||
++riter, ++titer, ++niter) { |
||||
|
||||
double rdist = norm(*riter, _R, NORM_INF); |
||||
double tdist = norm(*titer, _t, NORM_INF); |
||||
double ndist = norm(*niter, _n, NORM_INF); |
||||
|
||||
if ( rdist < max_error |
||||
&& tdist < max_error |
||||
&& ndist < max_error ) |
||||
return true; |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
Matx33d _R, _K, _H; |
||||
Vec3d _t, _n; |
||||
}; |
||||
|
||||
TEST(Calib3d_DecomposeHomography, regression) { CV_HomographyDecompTest test; test.safe_run(); } |
@ -1,15 +0,0 @@ |
||||
Extremely randomized trees |
||||
========================== |
||||
|
||||
Extremely randomized trees have been introduced by Pierre Geurts, Damien Ernst and Louis Wehenkel in the article "Extremely randomized trees", 2006 [http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.65.7485&rep=rep1&type=pdf]. The algorithm of growing Extremely randomized trees is similar to :ref:`Random Trees` (Random Forest), but there are two differences: |
||||
|
||||
#. Extremely randomized trees don't apply the bagging procedure to construct a set of the training samples for each tree. The same input training set is used to train all trees. |
||||
|
||||
#. Extremely randomized trees pick a node split very extremely (both a variable index and variable splitting value are chosen randomly), whereas Random Forest finds the best split (optimal one by variable index and variable splitting value) among random subset of variables. |
||||
|
||||
|
||||
CvERTrees |
||||
---------- |
||||
.. ocv:class:: CvERTrees : public CvRTrees |
||||
|
||||
The class implements the Extremely randomized trees algorithm. ``CvERTrees`` is inherited from :ocv:class:`CvRTrees` and has the same interface, so see description of :ocv:class:`CvRTrees` class to get details. To set the training parameters of Extremely randomized trees the same class :ocv:struct:`CvRTParams` is used. |
@ -1,272 +0,0 @@ |
||||
.. _Gradient Boosted Trees: |
||||
|
||||
Gradient Boosted Trees |
||||
====================== |
||||
|
||||
.. highlight:: cpp |
||||
|
||||
Gradient Boosted Trees (GBT) is a generalized boosting algorithm introduced by |
||||
Jerome Friedman: http://www.salfordsystems.com/doc/GreedyFuncApproxSS.pdf . |
||||
In contrast to the AdaBoost.M1 algorithm, GBT can deal with both multiclass |
||||
classification and regression problems. Moreover, it can use any |
||||
differential loss function, some popular ones are implemented. |
||||
Decision trees (:ocv:class:`CvDTree`) usage as base learners allows to process ordered |
||||
and categorical variables. |
||||
|
||||
.. _Training GBT: |
||||
|
||||
Training the GBT model |
||||
---------------------- |
||||
|
||||
Gradient Boosted Trees model represents an ensemble of single regression trees |
||||
built in a greedy fashion. Training procedure is an iterative process |
||||
similar to the numerical optimization via the gradient descent method. Summary loss |
||||
on the training set depends only on the current model predictions for the |
||||
training samples, in other words |
||||
:math:`\sum^N_{i=1}L(y_i, F(x_i)) \equiv \mathcal{L}(F(x_1), F(x_2), ... , F(x_N)) |
||||
\equiv \mathcal{L}(F)`. And the :math:`\mathcal{L}(F)` |
||||
gradient can be computed as follows: |
||||
|
||||
.. math:: |
||||
grad(\mathcal{L}(F)) = \left( \dfrac{\partial{L(y_1, F(x_1))}}{\partial{F(x_1)}}, |
||||
\dfrac{\partial{L(y_2, F(x_2))}}{\partial{F(x_2)}}, ... , |
||||
\dfrac{\partial{L(y_N, F(x_N))}}{\partial{F(x_N)}} \right) . |
||||
|
||||
At every training step, a single regression tree is built to predict an |
||||
antigradient vector components. Step length is computed corresponding to the |
||||
loss function and separately for every region determined by the tree leaf. It |
||||
can be eliminated by changing values of the leaves directly. |
||||
|
||||
See below the main scheme of the training process: |
||||
|
||||
#. |
||||
Find the best constant model. |
||||
#. |
||||
For :math:`i` in :math:`[1,M]`: |
||||
|
||||
#. |
||||
Compute the antigradient. |
||||
#. |
||||
Grow a regression tree to predict antigradient components. |
||||
#. |
||||
Change values in the tree leaves. |
||||
#. |
||||
Add the tree to the model. |
||||
|
||||
|
||||
The following loss functions are implemented for regression problems: |
||||
|
||||
* |
||||
Squared loss (``CvGBTrees::SQUARED_LOSS``): |
||||
:math:`L(y,f(x))=\dfrac{1}{2}(y-f(x))^2` |
||||
* |
||||
Absolute loss (``CvGBTrees::ABSOLUTE_LOSS``): |
||||
:math:`L(y,f(x))=|y-f(x)|` |
||||
* |
||||
Huber loss (``CvGBTrees::HUBER_LOSS``): |
||||
:math:`L(y,f(x)) = \left\{ \begin{array}{lr} |
||||
\delta\cdot\left(|y-f(x)|-\dfrac{\delta}{2}\right) & : |y-f(x)|>\delta\\ |
||||
\dfrac{1}{2}\cdot(y-f(x))^2 & : |y-f(x)|\leq\delta \end{array} \right.`, |
||||
|
||||
where :math:`\delta` is the :math:`\alpha`-quantile estimation of the |
||||
:math:`|y-f(x)|`. In the current implementation :math:`\alpha=0.2`. |
||||
|
||||
|
||||
The following loss functions are implemented for classification problems: |
||||
|
||||
* |
||||
Deviance or cross-entropy loss (``CvGBTrees::DEVIANCE_LOSS``): |
||||
:math:`K` functions are built, one function for each output class, and |
||||
:math:`L(y,f_1(x),...,f_K(x)) = -\sum^K_{k=0}1(y=k)\ln{p_k(x)}`, |
||||
where :math:`p_k(x)=\dfrac{\exp{f_k(x)}}{\sum^K_{i=1}\exp{f_i(x)}}` |
||||
is the estimation of the probability of :math:`y=k`. |
||||
|
||||
As a result, you get the following model: |
||||
|
||||
.. math:: f(x) = f_0 + \nu\cdot\sum^M_{i=1}T_i(x) , |
||||
|
||||
where :math:`f_0` is the initial guess (the best constant model) and :math:`\nu` |
||||
is a regularization parameter from the interval :math:`(0,1]`, further called |
||||
*shrinkage*. |
||||
|
||||
.. _Predicting with GBT: |
||||
|
||||
Predicting with the GBT Model |
||||
----------------------------- |
||||
|
||||
To get the GBT model prediction, you need to compute the sum of responses of |
||||
all the trees in the ensemble. For regression problems, it is the answer. |
||||
For classification problems, the result is :math:`\arg\max_{i=1..K}(f_i(x))`. |
||||
|
||||
|
||||
.. highlight:: cpp |
||||
|
||||
|
||||
CvGBTreesParams |
||||
--------------- |
||||
.. ocv:struct:: CvGBTreesParams : public CvDTreeParams |
||||
|
||||
GBT training parameters. |
||||
|
||||
The structure contains parameters for each single decision tree in the ensemble, |
||||
as well as the whole model characteristics. The structure is derived from |
||||
:ocv:class:`CvDTreeParams` but not all of the decision tree parameters are supported: |
||||
cross-validation, pruning, and class priorities are not used. |
||||
|
||||
CvGBTreesParams::CvGBTreesParams |
||||
-------------------------------- |
||||
.. ocv:function:: CvGBTreesParams::CvGBTreesParams() |
||||
|
||||
.. ocv:function:: CvGBTreesParams::CvGBTreesParams( int loss_function_type, int weak_count, float shrinkage, float subsample_portion, int max_depth, bool use_surrogates ) |
||||
|
||||
:param loss_function_type: Type of the loss function used for training |
||||
(see :ref:`Training GBT`). It must be one of the |
||||
following types: ``CvGBTrees::SQUARED_LOSS``, ``CvGBTrees::ABSOLUTE_LOSS``, |
||||
``CvGBTrees::HUBER_LOSS``, ``CvGBTrees::DEVIANCE_LOSS``. The first three |
||||
types are used for regression problems, and the last one for |
||||
classification. |
||||
|
||||
:param weak_count: Count of boosting algorithm iterations. ``weak_count*K`` is the total |
||||
count of trees in the GBT model, where ``K`` is the output classes count |
||||
(equal to one in case of a regression). |
||||
|
||||
:param shrinkage: Regularization parameter (see :ref:`Training GBT`). |
||||
|
||||
:param subsample_portion: Portion of the whole training set used for each algorithm iteration. |
||||
Subset is generated randomly. For more information see |
||||
http://www.salfordsystems.com/doc/StochasticBoostingSS.pdf. |
||||
|
||||
:param max_depth: Maximal depth of each decision tree in the ensemble (see :ocv:class:`CvDTree`). |
||||
|
||||
:param use_surrogates: If ``true``, surrogate splits are built (see :ocv:class:`CvDTree`). |
||||
|
||||
By default the following constructor is used: |
||||
|
||||
.. code-block:: cpp |
||||
|
||||
CvGBTreesParams(CvGBTrees::SQUARED_LOSS, 200, 0.01f, 0.8f, 3, false) |
||||
: CvDTreeParams( 3, 10, 0, false, 10, 0, false, false, 0 ) |
||||
|
||||
CvGBTrees |
||||
--------- |
||||
.. ocv:class:: CvGBTrees : public CvStatModel |
||||
|
||||
The class implements the Gradient boosted tree model as described in the beginning of this section. |
||||
|
||||
CvGBTrees::CvGBTrees |
||||
-------------------- |
||||
Default and training constructors. |
||||
|
||||
.. ocv:function:: CvGBTrees::CvGBTrees() |
||||
|
||||
.. ocv:function:: CvGBTrees::CvGBTrees( const Mat& trainData, int tflag, const Mat& responses, const Mat& varIdx=Mat(), const Mat& sampleIdx=Mat(), const Mat& varType=Mat(), const Mat& missingDataMask=Mat(), CvGBTreesParams params=CvGBTreesParams() ) |
||||
|
||||
.. ocv:function:: CvGBTrees::CvGBTrees( const CvMat* trainData, int tflag, const CvMat* responses, const CvMat* varIdx=0, const CvMat* sampleIdx=0, const CvMat* varType=0, const CvMat* missingDataMask=0, CvGBTreesParams params=CvGBTreesParams() ) |
||||
|
||||
.. ocv:pyfunction:: cv2.GBTrees([trainData, tflag, responses[, varIdx[, sampleIdx[, varType[, missingDataMask[, params]]]]]]) -> <GBTrees object> |
||||
|
||||
The constructors follow conventions of :ocv:func:`CvStatModel::CvStatModel`. See :ocv:func:`CvStatModel::train` for parameters descriptions. |
||||
|
||||
CvGBTrees::train |
||||
---------------- |
||||
Trains a Gradient boosted tree model. |
||||
|
||||
.. ocv:function:: bool CvGBTrees::train(const Mat& trainData, int tflag, const Mat& responses, const Mat& varIdx=Mat(), const Mat& sampleIdx=Mat(), const Mat& varType=Mat(), const Mat& missingDataMask=Mat(), CvGBTreesParams params=CvGBTreesParams(), bool update=false) |
||||
|
||||
.. ocv:function:: bool CvGBTrees::train( const CvMat* trainData, int tflag, const CvMat* responses, const CvMat* varIdx=0, const CvMat* sampleIdx=0, const CvMat* varType=0, const CvMat* missingDataMask=0, CvGBTreesParams params=CvGBTreesParams(), bool update=false ) |
||||
|
||||
.. ocv:function:: bool CvGBTrees::train(CvMLData* data, CvGBTreesParams params=CvGBTreesParams(), bool update=false) |
||||
|
||||
.. ocv:pyfunction:: cv2.GBTrees.train(trainData, tflag, responses[, varIdx[, sampleIdx[, varType[, missingDataMask[, params[, update]]]]]]) -> retval |
||||
|
||||
The first train method follows the common template (see :ocv:func:`CvStatModel::train`). |
||||
Both ``tflag`` values (``CV_ROW_SAMPLE``, ``CV_COL_SAMPLE``) are supported. |
||||
``trainData`` must be of the ``CV_32F`` type. ``responses`` must be a matrix of type |
||||
``CV_32S`` or ``CV_32F``. In both cases it is converted into the ``CV_32F`` |
||||
matrix inside the training procedure. ``varIdx`` and ``sampleIdx`` must be a |
||||
list of indices (``CV_32S``) or a mask (``CV_8U`` or ``CV_8S``). ``update`` is |
||||
a dummy parameter. |
||||
|
||||
The second form of :ocv:func:`CvGBTrees::train` function uses :ocv:class:`CvMLData` as a |
||||
data set container. ``update`` is still a dummy parameter. |
||||
|
||||
All parameters specific to the GBT model are passed into the training function |
||||
as a :ocv:class:`CvGBTreesParams` structure. |
||||
|
||||
|
||||
CvGBTrees::predict |
||||
------------------ |
||||
Predicts a response for an input sample. |
||||
|
||||
.. ocv:function:: float CvGBTrees::predict(const Mat& sample, const Mat& missing=Mat(), const Range& slice = Range::all(), int k=-1) const |
||||
|
||||
.. ocv:function:: float CvGBTrees::predict( const CvMat* sample, const CvMat* missing=0, CvMat* weakResponses=0, CvSlice slice = CV_WHOLE_SEQ, int k=-1 ) const |
||||
|
||||
.. ocv:pyfunction:: cv2.GBTrees.predict(sample[, missing[, slice[, k]]]) -> retval |
||||
|
||||
:param sample: Input feature vector that has the same format as every training set |
||||
element. If not all the variables were actually used during training, |
||||
``sample`` contains forged values at the appropriate places. |
||||
|
||||
:param missing: Missing values mask, which is a dimensional matrix of the same size as |
||||
``sample`` having the ``CV_8U`` type. ``1`` corresponds to the missing value |
||||
in the same position in the ``sample`` vector. If there are no missing values |
||||
in the feature vector, an empty matrix can be passed instead of the missing mask. |
||||
|
||||
:param weakResponses: Matrix used to obtain predictions of all the trees. |
||||
The matrix has :math:`K` rows, |
||||
where :math:`K` is the count of output classes (1 for the regression case). |
||||
The matrix has as many columns as the ``slice`` length. |
||||
|
||||
:param slice: Parameter defining the part of the ensemble used for prediction. |
||||
If ``slice = Range::all()``, all trees are used. Use this parameter to |
||||
get predictions of the GBT models with different ensemble sizes learning |
||||
only one model. |
||||
|
||||
:param k: Number of tree ensembles built in case of the classification problem |
||||
(see :ref:`Training GBT`). Use this |
||||
parameter to change the output to sum of the trees' predictions in the |
||||
``k``-th ensemble only. To get the total GBT model prediction, ``k`` value |
||||
must be -1. For regression problems, ``k`` is also equal to -1. |
||||
|
||||
The method predicts the response corresponding to the given sample |
||||
(see :ref:`Predicting with GBT`). |
||||
The result is either the class label or the estimated function value. The |
||||
:ocv:func:`CvGBTrees::predict` method enables using the parallel version of the GBT model |
||||
prediction if the OpenCV is built with the TBB library. In this case, predictions |
||||
of single trees are computed in a parallel fashion. |
||||
|
||||
|
||||
CvGBTrees::clear |
||||
---------------- |
||||
Clears the model. |
||||
|
||||
.. ocv:function:: void CvGBTrees::clear() |
||||
|
||||
.. ocv:pyfunction:: cv2.GBTrees.clear() -> None |
||||
|
||||
The function deletes the data set information and all the weak models and sets all internal |
||||
variables to the initial state. The function is called in :ocv:func:`CvGBTrees::train` and in the |
||||
destructor. |
||||
|
||||
|
||||
CvGBTrees::calc_error |
||||
--------------------- |
||||
Calculates a training or testing error. |
||||
|
||||
.. ocv:function:: float CvGBTrees::calc_error( CvMLData* _data, int type, std::vector<float> *resp = 0 ) |
||||
|
||||
:param _data: Data set. |
||||
|
||||
:param type: Parameter defining the error that should be computed: train (``CV_TRAIN_ERROR``) or test |
||||
(``CV_TEST_ERROR``). |
||||
|
||||
:param resp: If non-zero, a vector of predictions on the corresponding data set is |
||||
returned. |
||||
|
||||
If the :ocv:class:`CvMLData` data is used to store the data set, :ocv:func:`CvGBTrees::calc_error` can be |
||||
used to get a training/testing error easily and (optionally) all predictions |
||||
on the training/testing set. If the Intel* TBB* library is used, the error is computed in a |
||||
parallel way, namely, predictions for different samples are computed at the same time. |
||||
In case of a regression problem, a mean squared error is returned. For |
||||
classifications, the result is a misclassification error in percent. |
@ -1,279 +1,126 @@ |
||||
MLData |
||||
Training Data |
||||
=================== |
||||
|
||||
.. highlight:: cpp |
||||
|
||||
For the machine learning algorithms, the data set is often stored in a file of the ``.csv``-like format. The file contains a table of predictor and response values where each row of the table corresponds to a sample. Missing values are supported. The UC Irvine Machine Learning Repository (http://archive.ics.uci.edu/ml/) provides many data sets stored in such a format to the machine learning community. The class ``MLData`` is implemented to easily load the data for training one of the OpenCV machine learning algorithms. For float values, only the ``'.'`` separator is supported. The table can have a header and in such case the user have to set the number of the header lines to skip them duaring the file reading. |
||||
In machine learning algorithms there is notion of training data. Training data includes several components: |
||||
|
||||
CvMLData |
||||
-------- |
||||
.. ocv:class:: CvMLData |
||||
* A set of training samples. Each training sample is a vector of values (in Computer Vision it's sometimes referred to as feature vector). Usually all the vectors have the same number of components (features); OpenCV ml module assumes that. Each feature can be ordered (i.e. its values are floating-point numbers that can be compared with each other and strictly ordered, i.e. sorted) or categorical (i.e. its value belongs to a fixed set of values that can be integers, strings etc.). |
||||
|
||||
Class for loading the data from a ``.csv`` file. |
||||
:: |
||||
* Optional set of responses corresponding to the samples. Training data with no responses is used in unsupervised learning algorithms that learn structure of the supplied data based on distances between different samples. Training data with responses is used in supervised learning algorithms, which learn the function mapping samples to responses. Usually the responses are scalar values, ordered (when we deal with regression problem) or categorical (when we deal with classification problem; in this case the responses are often called "labels"). Some algorithms, most noticeably Neural networks, can handle not only scalar, but also multi-dimensional or vector responses. |
||||
|
||||
class CV_EXPORTS CvMLData |
||||
{ |
||||
public: |
||||
CvMLData(); |
||||
virtual ~CvMLData(); |
||||
* Another optional component is the mask of missing measurements. Most algorithms require all the components in all the training samples be valid, but some other algorithms, such as decision tress, can handle the cases of missing measurements. |
||||
|
||||
int read_csv(const char* filename); |
||||
* In the case of classification problem user may want to give different weights to different classes. This is useful, for example, when |
||||
* user wants to shift prediction accuracy towards lower false-alarm rate or higher hit-rate. |
||||
* user wants to compensate for significantly different amounts of training samples from different classes. |
||||
|
||||
const CvMat* get_values() const; |
||||
const CvMat* get_responses(); |
||||
const CvMat* get_missing() const; |
||||
* In addition to that, each training sample may be given a weight, if user wants the algorithm to pay special attention to certain training samples and adjust the training model accordingly. |
||||
|
||||
void set_response_idx( int idx ); |
||||
int get_response_idx() const; |
||||
* Also, user may wish not to use the whole training data at once, but rather use parts of it, e.g. to do parameter optimization via cross-validation procedure. |
||||
|
||||
As you can see, training data can have rather complex structure; besides, it may be very big and/or not entirely available, so there is need to make abstraction for this concept. In OpenCV ml there is ``cv::ml::TrainData`` class for that. |
||||
|
||||
void set_train_test_split( const CvTrainTestSplit * spl); |
||||
const CvMat* get_train_sample_idx() const; |
||||
const CvMat* get_test_sample_idx() const; |
||||
void mix_train_and_test_idx(); |
||||
TrainData |
||||
--------- |
||||
.. ocv:class:: TrainData |
||||
|
||||
const CvMat* get_var_idx(); |
||||
void change_var_idx( int vi, bool state ); |
||||
Class encapsulating training data. Please note that the class only specifies the interface of training data, but not implementation. All the statistical model classes in ml take Ptr<TrainData>. In other words, you can create your own class derived from ``TrainData`` and supply smart pointer to the instance of this class into ``StatModel::train``. |
||||
|
||||
const CvMat* get_var_types(); |
||||
void set_var_types( const char* str ); |
||||
|
||||
int get_var_type( int var_idx ) const; |
||||
void change_var_type( int var_idx, int type); |
||||
|
||||
void set_delimiter( char ch ); |
||||
char get_delimiter() const; |
||||
|
||||
void set_miss_ch( char ch ); |
||||
char get_miss_ch() const; |
||||
|
||||
const std::map<String, int>& get_class_labels_map() const; |
||||
|
||||
protected: |
||||
... |
||||
}; |
||||
|
||||
CvMLData::read_csv |
||||
------------------ |
||||
Reads the data set from a ``.csv``-like ``filename`` file and stores all read values in a matrix. |
||||
TrainData::loadFromCSV |
||||
---------------------- |
||||
Reads the dataset from a .csv file and returns the ready-to-use training data. |
||||
|
||||
.. ocv:function:: int CvMLData::read_csv(const char* filename) |
||||
.. ocv:function:: Ptr<TrainData> loadFromCSV(const String& filename, int headerLineCount, int responseStartIdx=-1, int responseEndIdx=-1, const String& varTypeSpec=String(), char delimiter=',', char missch='?') |
||||
|
||||
:param filename: The input file name |
||||
|
||||
While reading the data, the method tries to define the type of variables (predictors and responses): ordered or categorical. If a value of the variable is not numerical (except for the label for a missing value), the type of the variable is set to ``CV_VAR_CATEGORICAL``. If all existing values of the variable are numerical, the type of the variable is set to ``CV_VAR_ORDERED``. So, the default definition of variables types works correctly for all cases except the case of a categorical variable with numerical class labels. In this case, the type ``CV_VAR_ORDERED`` is set. You should change the type to ``CV_VAR_CATEGORICAL`` using the method :ocv:func:`CvMLData::change_var_type`. For categorical variables, a common map is built to convert a string class label to the numerical class label. Use :ocv:func:`CvMLData::get_class_labels_map` to obtain this map. |
||||
:param headerLineCount: The number of lines in the beginning to skip; besides the header, the function also skips empty lines and lines staring with '#' |
||||
|
||||
Also, when reading the data, the method constructs the mask of missing values. For example, values are equal to `'?'`. |
||||
:param responseStartIdx: Index of the first output variable. If -1, the function considers the last variable as the response |
||||
|
||||
CvMLData::get_values |
||||
-------------------- |
||||
Returns a pointer to the matrix of predictors and response values |
||||
:param responseEndIdx: Index of the last output variable + 1. If -1, then there is single response variable at ``responseStartIdx``. |
||||
|
||||
.. ocv:function:: const CvMat* CvMLData::get_values() const |
||||
:param varTypeSpec: The optional text string that specifies the variables' types. It has the format ``ord[n1-n2,n3,n4-n5,...]cat[n6,n7-n8,...]``. That is, variables from n1 to n2 (inclusive range), n3, n4 to n5 ... are considered ordered and n6, n7 to n8 ... are considered as categorical. The range [n1..n2] + [n3] + [n4..n5] + ... + [n6] + [n7..n8] should cover all the variables. If varTypeSpec is not specified, then algorithm uses the following rules: |
||||
1. all input variables are considered ordered by default. If some column contains has non-numerical values, e.g. 'apple', 'pear', 'apple', 'apple', 'mango', the corresponding variable is considered categorical. |
||||
2. if there are several output variables, they are all considered as ordered. Error is reported when non-numerical values are used. |
||||
3. if there is a single output variable, then if its values are non-numerical or are all integers, then it's considered categorical. Otherwise, it's considered ordered. |
||||
|
||||
The method returns a pointer to the matrix of predictor and response ``values`` or ``0`` if the data has not been loaded from the file yet. |
||||
:param delimiter: The character used to separate values in each line. |
||||
|
||||
The row count of this matrix equals the sample count. The column count equals predictors ``+ 1`` for the response (if exists) count. This means that each row of the matrix contains values of one sample predictor and response. The matrix type is ``CV_32FC1``. |
||||
:param missch: The character used to specify missing measurements. It should not be a digit. Although it's a non-numerical value, it surely does not affect the decision of whether the variable ordered or categorical. |
||||
|
||||
CvMLData::get_responses |
||||
----------------------- |
||||
Returns a pointer to the matrix of response values |
||||
TrainData::create |
||||
----------------- |
||||
Creates training data from in-memory arrays. |
||||
|
||||
.. ocv:function:: const CvMat* CvMLData::get_responses() |
||||
.. ocv:function:: Ptr<TrainData> create(InputArray samples, int layout, InputArray responses, InputArray varIdx=noArray(), InputArray sampleIdx=noArray(), InputArray sampleWeights=noArray(), InputArray varType=noArray()) |
||||
|
||||
The method returns a pointer to the matrix of response values or throws an exception if the data has not been loaded from the file yet. |
||||
:param samples: matrix of samples. It should have ``CV_32F`` type. |
||||
|
||||
This is a single-column matrix of the type ``CV_32FC1``. Its row count is equal to the sample count, one column and . |
||||
:param layout: it's either ``ROW_SAMPLE``, which means that each training sample is a row of ``samples``, or ``COL_SAMPLE``, which means that each training sample occupies a column of ``samples``. |
||||
|
||||
CvMLData::get_missing |
||||
--------------------- |
||||
Returns a pointer to the mask matrix of missing values |
||||
:param responses: matrix of responses. If the responses are scalar, they should be stored as a single row or as a single column. The matrix should have type ``CV_32F`` or ``CV_32S`` (in the former case the responses are considered as ordered by default; in the latter case - as categorical) |
||||
|
||||
.. ocv:function:: const CvMat* CvMLData::get_missing() const |
||||
:param varIdx: vector specifying which variables to use for training. It can be an integer vector (``CV_32S``) containing 0-based variable indices or byte vector (``CV_8U``) containing a mask of active variables. |
||||
|
||||
The method returns a pointer to the mask matrix of missing values or throws an exception if the data has not been loaded from the file yet. |
||||
:param sampleIdx: vector specifying which samples to use for training. It can be an integer vector (``CV_32S``) containing 0-based sample indices or byte vector (``CV_8U``) containing a mask of training samples. |
||||
|
||||
This matrix has the same size as the ``values`` matrix (see :ocv:func:`CvMLData::get_values`) and the type ``CV_8UC1``. |
||||
:param sampleWeights: optional vector with weights for each sample. It should have ``CV_32F`` type. |
||||
|
||||
CvMLData::set_response_idx |
||||
-------------------------- |
||||
Specifies index of response column in the data matrix |
||||
|
||||
.. ocv:function:: void CvMLData::set_response_idx( int idx ) |
||||
|
||||
The method sets the index of a response column in the ``values`` matrix (see :ocv:func:`CvMLData::get_values`) or throws an exception if the data has not been loaded from the file yet. |
||||
:param varType: optional vector of type ``CV_8U`` and size <number_of_variables_in_samples> + <number_of_variables_in_responses>, containing types of each input and output variable. The ordered variables are denoted by value ``VAR_ORDERED``, and categorical - by ``VAR_CATEGORICAL``. |
||||
|
||||
The old response columns become predictors. If ``idx < 0``, there is no response. |
||||
|
||||
CvMLData::get_response_idx |
||||
TrainData::getTrainSamples |
||||
-------------------------- |
||||
Returns index of the response column in the loaded data matrix |
||||
|
||||
.. ocv:function:: int CvMLData::get_response_idx() const |
||||
|
||||
The method returns the index of a response column in the ``values`` matrix (see :ocv:func:`CvMLData::get_values`) or throws an exception if the data has not been loaded from the file yet. |
||||
|
||||
If ``idx < 0``, there is no response. |
||||
|
||||
|
||||
CvMLData::set_train_test_split |
||||
------------------------------ |
||||
Divides the read data set into two disjoint training and test subsets. |
||||
|
||||
.. ocv:function:: void CvMLData::set_train_test_split( const CvTrainTestSplit * spl ) |
||||
|
||||
This method sets parameters for such a split using ``spl`` (see :ocv:class:`CvTrainTestSplit`) or throws an exception if the data has not been loaded from the file yet. |
||||
|
||||
CvMLData::get_train_sample_idx |
||||
------------------------------ |
||||
Returns the matrix of sample indices for a training subset |
||||
|
||||
.. ocv:function:: const CvMat* CvMLData::get_train_sample_idx() const |
||||
|
||||
The method returns the matrix of sample indices for a training subset. This is a single-row matrix of the type ``CV_32SC1``. If data split is not set, the method returns ``0``. If the data has not been loaded from the file yet, an exception is thrown. |
||||
|
||||
CvMLData::get_test_sample_idx |
||||
----------------------------- |
||||
Returns the matrix of sample indices for a testing subset |
||||
|
||||
.. ocv:function:: const CvMat* CvMLData::get_test_sample_idx() const |
||||
|
||||
|
||||
CvMLData::mix_train_and_test_idx |
||||
-------------------------------- |
||||
Mixes the indices of training and test samples |
||||
|
||||
.. ocv:function:: void CvMLData::mix_train_and_test_idx() |
||||
|
||||
The method shuffles the indices of training and test samples preserving sizes of training and test subsets if the data split is set by :ocv:func:`CvMLData::get_values`. If the data has not been loaded from the file yet, an exception is thrown. |
||||
|
||||
CvMLData::get_var_idx |
||||
--------------------- |
||||
Returns the indices of the active variables in the data matrix |
||||
|
||||
.. ocv:function:: const CvMat* CvMLData::get_var_idx() |
||||
|
||||
The method returns the indices of variables (columns) used in the ``values`` matrix (see :ocv:func:`CvMLData::get_values`). |
||||
|
||||
It returns ``0`` if the used subset is not set. It throws an exception if the data has not been loaded from the file yet. Returned matrix is a single-row matrix of the type ``CV_32SC1``. Its column count is equal to the size of the used variable subset. |
||||
|
||||
CvMLData::change_var_idx |
||||
------------------------ |
||||
Enables or disables particular variable in the loaded data |
||||
|
||||
.. ocv:function:: void CvMLData::change_var_idx( int vi, bool state ) |
||||
|
||||
By default, after reading the data set all variables in the ``values`` matrix (see :ocv:func:`CvMLData::get_values`) are used. But you may want to use only a subset of variables and include/exclude (depending on ``state`` value) a variable with the ``vi`` index from the used subset. If the data has not been loaded from the file yet, an exception is thrown. |
||||
|
||||
CvMLData::get_var_types |
||||
----------------------- |
||||
Returns a matrix of the variable types. |
||||
|
||||
.. ocv:function:: const CvMat* CvMLData::get_var_types() |
||||
|
||||
The function returns a single-row matrix of the type ``CV_8UC1``, where each element is set to either ``CV_VAR_ORDERED`` or ``CV_VAR_CATEGORICAL``. The number of columns is equal to the number of variables. If data has not been loaded from file yet an exception is thrown. |
||||
|
||||
CvMLData::set_var_types |
||||
----------------------- |
||||
Sets the variables types in the loaded data. |
||||
|
||||
.. ocv:function:: void CvMLData::set_var_types( const char* str ) |
||||
|
||||
In the string, a variable type is followed by a list of variables indices. For example: ``"ord[0-17],cat[18]"``, ``"ord[0,2,4,10-12], cat[1,3,5-9,13,14]"``, ``"cat"`` (all variables are categorical), ``"ord"`` (all variables are ordered). |
||||
|
||||
CvMLData::get_header_lines_number |
||||
--------------------------------- |
||||
Returns a number of the table header lines. |
||||
|
||||
.. ocv:function:: int CvMLData::get_header_lines_number() const |
||||
|
||||
CvMLData::set_header_lines_number |
||||
--------------------------------- |
||||
Sets a number of the table header lines. |
||||
|
||||
.. ocv:function:: void CvMLData::set_header_lines_number( int n ) |
||||
|
||||
By default it is supposed that the table does not have a header, i.e. it contains only the data. |
||||
|
||||
CvMLData::get_var_type |
||||
---------------------- |
||||
Returns type of the specified variable |
||||
|
||||
.. ocv:function:: int CvMLData::get_var_type( int var_idx ) const |
||||
|
||||
The method returns the type of a variable by the index ``var_idx`` ( ``CV_VAR_ORDERED`` or ``CV_VAR_CATEGORICAL``). |
||||
|
||||
CvMLData::change_var_type |
||||
------------------------- |
||||
Changes type of the specified variable |
||||
|
||||
.. ocv:function:: void CvMLData::change_var_type( int var_idx, int type) |
||||
|
||||
The method changes type of variable with index ``var_idx`` from existing type to ``type`` ( ``CV_VAR_ORDERED`` or ``CV_VAR_CATEGORICAL``). |
||||
Returns matrix of train samples |
||||
|
||||
CvMLData::set_delimiter |
||||
----------------------- |
||||
Sets the delimiter in the file used to separate input numbers |
||||
.. ocv:function:: Mat TrainData::getTrainSamples(int layout=ROW_SAMPLE, bool compressSamples=true, bool compressVars=true) const |
||||
|
||||
.. ocv:function:: void CvMLData::set_delimiter( char ch ) |
||||
:param layout: The requested layout. If it's different from the initial one, the matrix is transposed. |
||||
|
||||
The method sets the delimiter for variables in a file. For example: ``','`` (default), ``';'``, ``' '`` (space), or other characters. The floating-point separator ``'.'`` is not allowed. |
||||
:param compressSamples: if true, the function returns only the training samples (specified by sampleIdx) |
||||
|
||||
CvMLData::get_delimiter |
||||
----------------------- |
||||
Returns the currently used delimiter character. |
||||
:param compressVars: if true, the function returns the shorter training samples, containing only the active variables. |
||||
|
||||
.. ocv:function:: char CvMLData::get_delimiter() const |
||||
In current implementation the function tries to avoid physical data copying and returns the matrix stored inside TrainData (unless the transposition or compression is needed). |
||||
|
||||
|
||||
CvMLData::set_miss_ch |
||||
--------------------- |
||||
Sets the character used to specify missing values |
||||
TrainData::getTrainResponses |
||||
---------------------------- |
||||
Returns the vector of responses |
||||
|
||||
.. ocv:function:: void CvMLData::set_miss_ch( char ch ) |
||||
.. ocv:function:: Mat TrainData::getTrainResponses() const |
||||
|
||||
The method sets the character used to specify missing values. For example: ``'?'`` (default), ``'-'``. The floating-point separator ``'.'`` is not allowed. |
||||
The function returns ordered or the original categorical responses. Usually it's used in regression algorithms. |
||||
|
||||
CvMLData::get_miss_ch |
||||
--------------------- |
||||
Returns the currently used missing value character. |
||||
|
||||
.. ocv:function:: char CvMLData::get_miss_ch() const |
||||
TrainData::getClassLabels |
||||
---------------------------- |
||||
Returns the vector of class labels |
||||
|
||||
CvMLData::get_class_labels_map |
||||
------------------------------- |
||||
Returns a map that converts strings to labels. |
||||
.. ocv:function:: Mat TrainData::getClassLabels() const |
||||
|
||||
.. ocv:function:: const std::map<String, int>& CvMLData::get_class_labels_map() const |
||||
The function returns vector of unique labels occurred in the responses. |
||||
|
||||
The method returns a map that converts string class labels to the numerical class labels. It can be used to get an original class label as in a file. |
||||
|
||||
CvTrainTestSplit |
||||
---------------- |
||||
.. ocv:struct:: CvTrainTestSplit |
||||
TrainData::getTrainNormCatResponses |
||||
----------------------------------- |
||||
Returns the vector of normalized categorical responses |
||||
|
||||
Structure setting the split of a data set read by :ocv:class:`CvMLData`. |
||||
:: |
||||
.. ocv:function:: Mat TrainData::getTrainNormCatResponses() const |
||||
|
||||
struct CvTrainTestSplit |
||||
{ |
||||
CvTrainTestSplit(); |
||||
CvTrainTestSplit( int train_sample_count, bool mix = true); |
||||
CvTrainTestSplit( float train_sample_portion, bool mix = true); |
||||
The function returns vector of responses. Each response is integer from 0 to <number of classes>-1. The actual label value can be retrieved then from the class label vector, see ``TrainData::getClassLabels``. |
||||
|
||||
union |
||||
{ |
||||
int count; |
||||
float portion; |
||||
} train_sample_part; |
||||
int train_sample_part_mode; |
||||
TrainData::setTrainTestSplitRatio |
||||
----------------------------------- |
||||
Splits the training data into the training and test parts |
||||
|
||||
bool mix; |
||||
}; |
||||
.. ocv:function:: void TrainData::setTrainTestSplitRatio(double ratio, bool shuffle=true) |
||||
|
||||
There are two ways to construct a split: |
||||
The function selects a subset of specified relative size and then returns it as the training set. If the function is not called, all the data is used for training. Please, note that for each of ``TrainData::getTrain*`` there is corresponding ``TrainData::getTest*``, so that the test subset can be retrieved and processed as well. |
||||
|
||||
* Set the training sample count (subset size) ``train_sample_count``. Other existing samples are located in a test subset. |
||||
|
||||
* Set a training sample portion in ``[0,..1]``. The flag ``mix`` is used to mix training and test samples indices when the split is set. Otherwise, the data set is split in the storing order: the first part of samples of a given size is a training subset, the second part is a test subset. |
||||
Other methods |
||||
------------- |
||||
The class includes many other methods that can be used to access normalized categorical input variables, access training data by parts, so that does not have to fit into the memory etc. |
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,728 +0,0 @@ |
||||
/*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
|
||||
//
|
||||
// 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 "precomp.hpp" |
||||
|
||||
#if 0 |
||||
|
||||
ML_IMPL int |
||||
icvCmpIntegers (const void* a, const void* b) {return *(const int*)a - *(const int*)b;} |
||||
|
||||
/****************************************************************************************\
|
||||
* Cross-validation algorithms realizations * |
||||
\****************************************************************************************/ |
||||
|
||||
// Return pointer to trainIdx. Function DOES NOT FILL this matrix!
|
||||
ML_IMPL |
||||
const CvMat* cvCrossValGetTrainIdxMatrix (const CvStatModel* estimateModel) |
||||
{ |
||||
CvMat* result = NULL; |
||||
|
||||
CV_FUNCNAME ("cvCrossValGetTrainIdxMatrix"); |
||||
__BEGIN__ |
||||
|
||||
if (!CV_IS_CROSSVAL(estimateModel)) |
||||
{ |
||||
CV_ERROR (CV_StsBadArg, "Pointer point to not CvCrossValidationModel"); |
||||
} |
||||
|
||||
result = ((CvCrossValidationModel*)estimateModel)->sampleIdxTrain; |
||||
|
||||
__END__ |
||||
|
||||
return result; |
||||
} // End of cvCrossValGetTrainIdxMatrix
|
||||
|
||||
/****************************************************************************************/ |
||||
// Return pointer to checkIdx. Function DOES NOT FILL this matrix!
|
||||
ML_IMPL |
||||
const CvMat* cvCrossValGetCheckIdxMatrix (const CvStatModel* estimateModel) |
||||
{ |
||||
CvMat* result = NULL; |
||||
|
||||
CV_FUNCNAME ("cvCrossValGetCheckIdxMatrix"); |
||||
__BEGIN__ |
||||
|
||||
if (!CV_IS_CROSSVAL (estimateModel)) |
||||
{ |
||||
CV_ERROR (CV_StsBadArg, "Pointer point to not CvCrossValidationModel"); |
||||
} |
||||
|
||||
result = ((CvCrossValidationModel*)estimateModel)->sampleIdxEval; |
||||
|
||||
__END__ |
||||
|
||||
return result; |
||||
} // End of cvCrossValGetCheckIdxMatrix
|
||||
|
||||
/****************************************************************************************/ |
||||
// Create new Idx-matrix for next classifiers training and return code of result.
|
||||
// Result is 0 if function can't make next step (error input or folds are finished),
|
||||
// it is 1 if all was correct, and it is 2 if current fold wasn't' checked.
|
||||
ML_IMPL |
||||
int cvCrossValNextStep (CvStatModel* estimateModel) |
||||
{ |
||||
int result = 0; |
||||
|
||||
CV_FUNCNAME ("cvCrossValGetNextTrainIdx"); |
||||
__BEGIN__ |
||||
|
||||
CvCrossValidationModel* crVal = (CvCrossValidationModel*) estimateModel; |
||||
int k, fold; |
||||
|
||||
if (!CV_IS_CROSSVAL (estimateModel)) |
||||
{ |
||||
CV_ERROR (CV_StsBadArg, "Pointer point to not CvCrossValidationModel"); |
||||
} |
||||
|
||||
fold = ++crVal->current_fold; |
||||
|
||||
if (fold >= crVal->folds_all) |
||||
{ |
||||
if (fold == crVal->folds_all) |
||||
EXIT; |
||||
else |
||||
{ |
||||
CV_ERROR (CV_StsInternal, "All iterations has end long ago"); |
||||
} |
||||
} |
||||
|
||||
k = crVal->folds[fold + 1] - crVal->folds[fold]; |
||||
crVal->sampleIdxTrain->data.i = crVal->sampleIdxAll + crVal->folds[fold + 1]; |
||||
crVal->sampleIdxTrain->cols = crVal->samples_all - k; |
||||
crVal->sampleIdxEval->data.i = crVal->sampleIdxAll + crVal->folds[fold]; |
||||
crVal->sampleIdxEval->cols = k; |
||||
|
||||
if (crVal->is_checked) |
||||
{ |
||||
crVal->is_checked = 0; |
||||
result = 1; |
||||
} |
||||
else |
||||
{ |
||||
result = 2; |
||||
} |
||||
|
||||
__END__ |
||||
|
||||
return result; |
||||
} |
||||
|
||||
/****************************************************************************************/ |
||||
// Do checking part of loop of cross-validations metod.
|
||||
ML_IMPL |
||||
void cvCrossValCheckClassifier (CvStatModel* estimateModel, |
||||
const CvStatModel* model, |
||||
const CvMat* trainData, |
||||
int sample_t_flag, |
||||
const CvMat* trainClasses) |
||||
{ |
||||
CV_FUNCNAME ("cvCrossValCheckClassifier "); |
||||
__BEGIN__ |
||||
|
||||
CvCrossValidationModel* crVal = (CvCrossValidationModel*) estimateModel; |
||||
int i, j, k; |
||||
int* data; |
||||
float* responses_fl; |
||||
int step; |
||||
float* responses_result; |
||||
int* responses_i; |
||||
double te, te1; |
||||
double sum_c, sum_p, sum_pp, sum_cp, sum_cc, sq_err; |
||||
|
||||
// Check input data to correct values.
|
||||
if (!CV_IS_CROSSVAL (estimateModel)) |
||||
{ |
||||
CV_ERROR (CV_StsBadArg,"First parameter point to not CvCrossValidationModel"); |
||||
} |
||||
if (!CV_IS_STAT_MODEL (model)) |
||||
{ |
||||
CV_ERROR (CV_StsBadArg, "Second parameter point to not CvStatModel"); |
||||
} |
||||
if (!CV_IS_MAT (trainData)) |
||||
{ |
||||
CV_ERROR (CV_StsBadArg, "Third parameter point to not CvMat"); |
||||
} |
||||
if (!CV_IS_MAT (trainClasses)) |
||||
{ |
||||
CV_ERROR (CV_StsBadArg, "Fifth parameter point to not CvMat"); |
||||
} |
||||
if (crVal->is_checked) |
||||
{ |
||||
CV_ERROR (CV_StsInternal, "This iterations already was checked"); |
||||
} |
||||
|
||||
// Initialize.
|
||||
k = crVal->sampleIdxEval->cols; |
||||
data = crVal->sampleIdxEval->data.i; |
||||
|
||||
// Eval tested feature vectors.
|
||||
CV_CALL (cvStatModelMultiPredict (model, trainData, sample_t_flag, |
||||
crVal->predict_results, NULL, crVal->sampleIdxEval)); |
||||
// Count number if correct results.
|
||||
responses_result = crVal->predict_results->data.fl; |
||||
if (crVal->is_regression) |
||||
{ |
||||
sum_c = sum_p = sum_pp = sum_cp = sum_cc = sq_err = 0; |
||||
if (CV_MAT_TYPE (trainClasses->type) == CV_32FC1) |
||||
{ |
||||
responses_fl = trainClasses->data.fl; |
||||
step = trainClasses->rows == 1 ? 1 : trainClasses->step / sizeof(float); |
||||
for (i = 0; i < k; i++) |
||||
{ |
||||
te = responses_result[*data]; |
||||
te1 = responses_fl[*data * step]; |
||||
sum_c += te1; |
||||
sum_p += te; |
||||
sum_cc += te1 * te1; |
||||
sum_pp += te * te; |
||||
sum_cp += te1 * te; |
||||
te -= te1; |
||||
sq_err += te * te; |
||||
|
||||
data++; |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
responses_i = trainClasses->data.i; |
||||
step = trainClasses->rows == 1 ? 1 : trainClasses->step / sizeof(int); |
||||
for (i = 0; i < k; i++) |
||||
{ |
||||
te = responses_result[*data]; |
||||
te1 = responses_i[*data * step]; |
||||
sum_c += te1; |
||||
sum_p += te; |
||||
sum_cc += te1 * te1; |
||||
sum_pp += te * te; |
||||
sum_cp += te1 * te; |
||||
te -= te1; |
||||
sq_err += te * te; |
||||
|
||||
data++; |
||||
} |
||||
} |
||||
// Fixing new internal values of accuracy.
|
||||
crVal->sum_correct += sum_c; |
||||
crVal->sum_predict += sum_p; |
||||
crVal->sum_cc += sum_cc; |
||||
crVal->sum_pp += sum_pp; |
||||
crVal->sum_cp += sum_cp; |
||||
crVal->sq_error += sq_err; |
||||
} |
||||
else |
||||
{ |
||||
if (CV_MAT_TYPE (trainClasses->type) == CV_32FC1) |
||||
{ |
||||
responses_fl = trainClasses->data.fl; |
||||
step = trainClasses->rows == 1 ? 1 : trainClasses->step / sizeof(float); |
||||
for (i = 0, j = 0; i < k; i++) |
||||
{ |
||||
if (cvRound (responses_result[*data]) == cvRound (responses_fl[*data * step])) |
||||
j++; |
||||
data++; |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
responses_i = trainClasses->data.i; |
||||
step = trainClasses->rows == 1 ? 1 : trainClasses->step / sizeof(int); |
||||
for (i = 0, j = 0; i < k; i++) |
||||
{ |
||||
if (cvRound (responses_result[*data]) == responses_i[*data * step]) |
||||
j++; |
||||
data++; |
||||
} |
||||
} |
||||
// Fixing new internal values of accuracy.
|
||||
crVal->correct_results += j; |
||||
} |
||||
// Fixing that this fold already checked.
|
||||
crVal->all_results += k; |
||||
crVal->is_checked = 1; |
||||
|
||||
__END__ |
||||
} // End of cvCrossValCheckClassifier
|
||||
|
||||
/****************************************************************************************/ |
||||
// Return current accuracy.
|
||||
ML_IMPL |
||||
float cvCrossValGetResult (const CvStatModel* estimateModel, |
||||
float* correlation) |
||||
{ |
||||
float result = 0; |
||||
|
||||
CV_FUNCNAME ("cvCrossValGetResult"); |
||||
__BEGIN__ |
||||
|
||||
double te, te1; |
||||
CvCrossValidationModel* crVal = (CvCrossValidationModel*)estimateModel; |
||||
|
||||
if (!CV_IS_CROSSVAL (estimateModel)) |
||||
{ |
||||
CV_ERROR (CV_StsBadArg, "Pointer point to not CvCrossValidationModel"); |
||||
} |
||||
|
||||
if (crVal->all_results) |
||||
{ |
||||
if (crVal->is_regression) |
||||
{ |
||||
result = ((float)crVal->sq_error) / crVal->all_results; |
||||
if (correlation) |
||||
{ |
||||
te = crVal->all_results * crVal->sum_cp - |
||||
crVal->sum_correct * crVal->sum_predict; |
||||
te *= te; |
||||
te1 = (crVal->all_results * crVal->sum_cc - |
||||
crVal->sum_correct * crVal->sum_correct) * |
||||
(crVal->all_results * crVal->sum_pp - |
||||
crVal->sum_predict * crVal->sum_predict); |
||||
*correlation = (float)(te / te1); |
||||
|
||||
} |
||||
} |
||||
else |
||||
{ |
||||
result = ((float)crVal->correct_results) / crVal->all_results; |
||||
} |
||||
} |
||||
|
||||
__END__ |
||||
|
||||
return result; |
||||
} |
||||
|
||||
/****************************************************************************************/ |
||||
// Reset cross-validation EstimateModel to state the same as it was immidiatly after
|
||||
// its creating.
|
||||
ML_IMPL |
||||
void cvCrossValReset (CvStatModel* estimateModel) |
||||
{ |
||||
CV_FUNCNAME ("cvCrossValReset"); |
||||
__BEGIN__ |
||||
|
||||
CvCrossValidationModel* crVal = (CvCrossValidationModel*)estimateModel; |
||||
|
||||
if (!CV_IS_CROSSVAL (estimateModel)) |
||||
{ |
||||
CV_ERROR (CV_StsBadArg, "Pointer point to not CvCrossValidationModel"); |
||||
} |
||||
|
||||
crVal->current_fold = -1; |
||||
crVal->is_checked = 1; |
||||
crVal->all_results = 0; |
||||
crVal->correct_results = 0; |
||||
crVal->sq_error = 0; |
||||
crVal->sum_correct = 0; |
||||
crVal->sum_predict = 0; |
||||
crVal->sum_cc = 0; |
||||
crVal->sum_pp = 0; |
||||
crVal->sum_cp = 0; |
||||
|
||||
__END__ |
||||
} |
||||
|
||||
/****************************************************************************************/ |
||||
// This function is standart CvStatModel field to release cross-validation EstimateModel.
|
||||
ML_IMPL |
||||
void cvReleaseCrossValidationModel (CvStatModel** model) |
||||
{ |
||||
CvCrossValidationModel* pModel; |
||||
|
||||
CV_FUNCNAME ("cvReleaseCrossValidationModel"); |
||||
__BEGIN__ |
||||
|
||||
if (!model) |
||||
{ |
||||
CV_ERROR (CV_StsNullPtr, ""); |
||||
} |
||||
|
||||
pModel = (CvCrossValidationModel*)*model; |
||||
if (!pModel) |
||||
{ |
||||
return; |
||||
} |
||||
if (!CV_IS_CROSSVAL (pModel)) |
||||
{ |
||||
CV_ERROR (CV_StsBadArg, ""); |
||||
} |
||||
|
||||
cvFree (&pModel->sampleIdxAll); |
||||
cvFree (&pModel->folds); |
||||
cvReleaseMat (&pModel->sampleIdxEval); |
||||
cvReleaseMat (&pModel->sampleIdxTrain); |
||||
cvReleaseMat (&pModel->predict_results); |
||||
|
||||
cvFree (model); |
||||
|
||||
__END__ |
||||
} // End of cvReleaseCrossValidationModel.
|
||||
|
||||
/****************************************************************************************/ |
||||
// This function create cross-validation EstimateModel.
|
||||
ML_IMPL CvStatModel* |
||||
cvCreateCrossValidationEstimateModel( |
||||
int samples_all, |
||||
const CvStatModelParams* estimateParams, |
||||
const CvMat* sampleIdx) |
||||
{ |
||||
CvStatModel* model = NULL; |
||||
CvCrossValidationModel* crVal = NULL; |
||||
|
||||
CV_FUNCNAME ("cvCreateCrossValidationEstimateModel"); |
||||
__BEGIN__ |
||||
|
||||
int k_fold = 10; |
||||
|
||||
int i, j, k, s_len; |
||||
int samples_selected; |
||||
CvRNG rng; |
||||
CvRNG* prng; |
||||
int* res_s_data; |
||||
int* te_s_data; |
||||
int* folds; |
||||
|
||||
rng = cvRNG(cvGetTickCount()); |
||||
cvRandInt (&rng); cvRandInt (&rng); cvRandInt (&rng); cvRandInt (&rng); |
||||
// Check input parameters.
|
||||
if (estimateParams) |
||||
k_fold = ((CvCrossValidationParams*)estimateParams)->k_fold; |
||||
if (!k_fold) |
||||
{ |
||||
CV_ERROR (CV_StsBadArg, "Error in parameters of cross-validation (k_fold == 0)!"); |
||||
} |
||||
if (samples_all <= 0) |
||||
{ |
||||
CV_ERROR (CV_StsBadArg, "<samples_all> should be positive!"); |
||||
} |
||||
|
||||
// Alloc memory and fill standart StatModel's fields.
|
||||
CV_CALL (crVal = (CvCrossValidationModel*)cvCreateStatModel ( |
||||
CV_STAT_MODEL_MAGIC_VAL | CV_CROSSVAL_MAGIC_VAL, |
||||
sizeof(CvCrossValidationModel), |
||||
cvReleaseCrossValidationModel, |
||||
NULL, NULL)); |
||||
crVal->current_fold = -1; |
||||
crVal->folds_all = k_fold; |
||||
if (estimateParams && ((CvCrossValidationParams*)estimateParams)->is_regression) |
||||
crVal->is_regression = 1; |
||||
else |
||||
crVal->is_regression = 0; |
||||
if (estimateParams && ((CvCrossValidationParams*)estimateParams)->rng) |
||||
prng = ((CvCrossValidationParams*)estimateParams)->rng; |
||||
else |
||||
prng = &rng; |
||||
|
||||
// Check and preprocess sample indices.
|
||||
if (sampleIdx) |
||||
{ |
||||
int s_step; |
||||
int s_type = 0; |
||||
|
||||
if (!CV_IS_MAT (sampleIdx)) |
||||
CV_ERROR (CV_StsBadArg, "Invalid sampleIdx array"); |
||||
|
||||
if (sampleIdx->rows != 1 && sampleIdx->cols != 1) |
||||
CV_ERROR (CV_StsBadSize, "sampleIdx array must be 1-dimensional"); |
||||
|
||||
s_len = sampleIdx->rows + sampleIdx->cols - 1; |
||||
s_step = sampleIdx->rows == 1 ? |
||||
1 : sampleIdx->step / CV_ELEM_SIZE(sampleIdx->type); |
||||
|
||||
s_type = CV_MAT_TYPE (sampleIdx->type); |
||||
|
||||
switch (s_type) |
||||
{ |
||||
case CV_8UC1: |
||||
case CV_8SC1: |
||||
{ |
||||
uchar* s_data = sampleIdx->data.ptr; |
||||
|
||||
// sampleIdx is array of 1's and 0's -
|
||||
// i.e. it is a mask of the selected samples
|
||||
if( s_len != samples_all ) |
||||
CV_ERROR (CV_StsUnmatchedSizes, |
||||
"Sample mask should contain as many elements as the total number of samples"); |
||||
|
||||
samples_selected = 0; |
||||
for (i = 0; i < s_len; i++) |
||||
samples_selected += s_data[i * s_step] != 0; |
||||
|
||||
if (samples_selected == 0) |
||||
CV_ERROR (CV_StsOutOfRange, "No samples is selected!"); |
||||
} |
||||
s_len = samples_selected; |
||||
break; |
||||
case CV_32SC1: |
||||
if (s_len > samples_all) |
||||
CV_ERROR (CV_StsOutOfRange, |
||||
"sampleIdx array may not contain more elements than the total number of samples"); |
||||
samples_selected = s_len; |
||||
break; |
||||
default: |
||||
CV_ERROR (CV_StsUnsupportedFormat, "Unsupported sampleIdx array data type " |
||||
"(it should be 8uC1, 8sC1 or 32sC1)"); |
||||
} |
||||
|
||||
// Alloc additional memory for internal Idx and fill it.
|
||||
/*!!*/ CV_CALL (res_s_data = crVal->sampleIdxAll = |
||||
(int*)cvAlloc (2 * s_len * sizeof(int))); |
||||
|
||||
if (s_type < CV_32SC1) |
||||
{ |
||||
uchar* s_data = sampleIdx->data.ptr; |
||||
for (i = 0; i < s_len; i++) |
||||
if (s_data[i * s_step]) |
||||
{ |
||||
*res_s_data++ = i; |
||||
} |
||||
res_s_data = crVal->sampleIdxAll; |
||||
} |
||||
else |
||||
{ |
||||
int* s_data = sampleIdx->data.i; |
||||
int out_of_order = 0; |
||||
|
||||
for (i = 0; i < s_len; i++) |
||||
{ |
||||
res_s_data[i] = s_data[i * s_step]; |
||||
if (i > 0 && res_s_data[i] < res_s_data[i - 1]) |
||||
out_of_order = 1; |
||||
} |
||||
|
||||
if (out_of_order) |
||||
qsort (res_s_data, s_len, sizeof(res_s_data[0]), icvCmpIntegers); |
||||
|
||||
if (res_s_data[0] < 0 || |
||||
res_s_data[s_len - 1] >= samples_all) |
||||
CV_ERROR (CV_StsBadArg, "There are out-of-range sample indices"); |
||||
for (i = 1; i < s_len; i++) |
||||
if (res_s_data[i] <= res_s_data[i - 1]) |
||||
CV_ERROR (CV_StsBadArg, "There are duplicated"); |
||||
} |
||||
} |
||||
else // if (sampleIdx)
|
||||
{ |
||||
// Alloc additional memory for internal Idx and fill it.
|
||||
s_len = samples_all; |
||||
CV_CALL (res_s_data = crVal->sampleIdxAll = (int*)cvAlloc (2 * s_len * sizeof(int))); |
||||
for (i = 0; i < s_len; i++) |
||||
{ |
||||
*res_s_data++ = i; |
||||
} |
||||
res_s_data = crVal->sampleIdxAll; |
||||
} // if (sampleIdx) ... else
|
||||
|
||||
// Resort internal Idx.
|
||||
te_s_data = res_s_data + s_len; |
||||
for (i = s_len; i > 1; i--) |
||||
{ |
||||
j = cvRandInt (prng) % i; |
||||
k = *(--te_s_data); |
||||
*te_s_data = res_s_data[j]; |
||||
res_s_data[j] = k; |
||||
} |
||||
|
||||
// Duplicate resorted internal Idx.
|
||||
// It will be used to simplify operation of getting trainIdx.
|
||||
te_s_data = res_s_data + s_len; |
||||
for (i = 0; i < s_len; i++) |
||||
{ |
||||
*te_s_data++ = *res_s_data++; |
||||
} |
||||
|
||||
// Cut sampleIdxAll to parts.
|
||||
if (k_fold > 0) |
||||
{ |
||||
if (k_fold > s_len) |
||||
{ |
||||
CV_ERROR (CV_StsBadArg, |
||||
"Error in parameters of cross-validation ('k_fold' > #samples)!"); |
||||
} |
||||
folds = crVal->folds = (int*) cvAlloc ((k_fold + 1) * sizeof (int)); |
||||
*folds++ = 0; |
||||
for (i = 1; i < k_fold; i++) |
||||
{ |
||||
*folds++ = cvRound (i * s_len * 1. / k_fold); |
||||
} |
||||
*folds = s_len; |
||||
folds = crVal->folds; |
||||
|
||||
crVal->max_fold_size = (s_len - 1) / k_fold + 1; |
||||
} |
||||
else |
||||
{ |
||||
k = -k_fold; |
||||
crVal->max_fold_size = k; |
||||
if (k >= s_len) |
||||
{ |
||||
CV_ERROR (CV_StsBadArg, |
||||
"Error in parameters of cross-validation (-'k_fold' > #samples)!"); |
||||
} |
||||
crVal->folds_all = k = (s_len - 1) / k + 1; |
||||
|
||||
folds = crVal->folds = (int*) cvAlloc ((k + 1) * sizeof (int)); |
||||
for (i = 0; i < k; i++) |
||||
{ |
||||
*folds++ = -i * k_fold; |
||||
} |
||||
*folds = s_len; |
||||
folds = crVal->folds; |
||||
} |
||||
|
||||
// Prepare other internal fields to working.
|
||||
CV_CALL (crVal->predict_results = cvCreateMat (1, samples_all, CV_32FC1)); |
||||
CV_CALL (crVal->sampleIdxEval = cvCreateMatHeader (1, 1, CV_32SC1)); |
||||
CV_CALL (crVal->sampleIdxTrain = cvCreateMatHeader (1, 1, CV_32SC1)); |
||||
crVal->sampleIdxEval->cols = 0; |
||||
crVal->sampleIdxTrain->cols = 0; |
||||
crVal->samples_all = s_len; |
||||
crVal->is_checked = 1; |
||||
|
||||
crVal->getTrainIdxMat = cvCrossValGetTrainIdxMatrix; |
||||
crVal->getCheckIdxMat = cvCrossValGetCheckIdxMatrix; |
||||
crVal->nextStep = cvCrossValNextStep; |
||||
crVal->check = cvCrossValCheckClassifier; |
||||
crVal->getResult = cvCrossValGetResult; |
||||
crVal->reset = cvCrossValReset; |
||||
|
||||
model = (CvStatModel*)crVal; |
||||
|
||||
__END__ |
||||
|
||||
if (!model) |
||||
{ |
||||
cvReleaseCrossValidationModel ((CvStatModel**)&crVal); |
||||
} |
||||
|
||||
return model; |
||||
} // End of cvCreateCrossValidationEstimateModel
|
||||
|
||||
|
||||
/****************************************************************************************\
|
||||
* Extended interface with backcalls for models * |
||||
\****************************************************************************************/ |
||||
ML_IMPL float |
||||
cvCrossValidation (const CvMat* trueData, |
||||
int tflag, |
||||
const CvMat* trueClasses, |
||||
CvStatModel* (*createClassifier) (const CvMat*, |
||||
int, |
||||
const CvMat*, |
||||
const CvClassifierTrainParams*, |
||||
const CvMat*, |
||||
const CvMat*, |
||||
const CvMat*, |
||||
const CvMat*), |
||||
const CvClassifierTrainParams* estimateParams, |
||||
const CvClassifierTrainParams* trainParams, |
||||
const CvMat* compIdx, |
||||
const CvMat* sampleIdx, |
||||
CvStatModel** pCrValModel, |
||||
const CvMat* typeMask, |
||||
const CvMat* missedMeasurementMask) |
||||
{ |
||||
CvCrossValidationModel* crVal = NULL; |
||||
float result = 0; |
||||
CvStatModel* pClassifier = NULL; |
||||
|
||||
CV_FUNCNAME ("cvCrossValidation"); |
||||
__BEGIN__ |
||||
|
||||
const CvMat* trainDataIdx; |
||||
int samples_all; |
||||
|
||||
// checking input data
|
||||
if ((createClassifier) == NULL) |
||||
{ |
||||
CV_ERROR (CV_StsNullPtr, "Null pointer to functiion which create classifier"); |
||||
} |
||||
if (pCrValModel && *pCrValModel && !CV_IS_CROSSVAL(*pCrValModel)) |
||||
{ |
||||
CV_ERROR (CV_StsBadArg, |
||||
"<pCrValModel> point to not cross-validation model"); |
||||
} |
||||
|
||||
// initialization
|
||||
if (pCrValModel && *pCrValModel) |
||||
{ |
||||
crVal = (CvCrossValidationModel*)*pCrValModel; |
||||
crVal->reset ((CvStatModel*)crVal); |
||||
} |
||||
else |
||||
{ |
||||
samples_all = ((tflag) ? trueData->rows : trueData->cols); |
||||
CV_CALL (crVal = (CvCrossValidationModel*) |
||||
cvCreateCrossValidationEstimateModel (samples_all, estimateParams, sampleIdx)); |
||||
} |
||||
|
||||
CV_CALL (trainDataIdx = crVal->getTrainIdxMat ((CvStatModel*)crVal)); |
||||
|
||||
// operation loop
|
||||
for (; crVal->nextStep((CvStatModel*)crVal) != 0; ) |
||||
{ |
||||
CV_CALL (pClassifier = createClassifier (trueData, tflag, trueClasses, |
||||
trainParams, compIdx, trainDataIdx, typeMask, missedMeasurementMask)); |
||||
CV_CALL (crVal->check ((CvStatModel*)crVal, pClassifier, |
||||
trueData, tflag, trueClasses)); |
||||
|
||||
pClassifier->release (&pClassifier); |
||||
} |
||||
|
||||
// Get result and fill output field.
|
||||
CV_CALL (result = crVal->getResult ((CvStatModel*)crVal, 0)); |
||||
|
||||
if (pCrValModel && !*pCrValModel) |
||||
*pCrValModel = (CvStatModel*)crVal; |
||||
|
||||
__END__ |
||||
|
||||
// Free all memory that should be freed.
|
||||
if (pClassifier) |
||||
pClassifier->release (&pClassifier); |
||||
if (crVal && (!pCrValModel || !*pCrValModel)) |
||||
crVal->release ((CvStatModel**)&crVal); |
||||
|
||||
return result; |
||||
} // End of cvCrossValidation
|
||||
|
||||
#endif |
||||
|
||||
/* End of file */ |
File diff suppressed because it is too large
Load Diff
@ -1,63 +0,0 @@ |
||||
/*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.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., 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 the copyright holders 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 "precomp.hpp" |
||||
|
||||
namespace cv |
||||
{ |
||||
|
||||
CV_INIT_ALGORITHM(EM, "StatModel.EM", |
||||
obj.info()->addParam(obj, "nclusters", obj.nclusters); |
||||
obj.info()->addParam(obj, "covMatType", obj.covMatType); |
||||
obj.info()->addParam(obj, "maxIters", obj.maxIters); |
||||
obj.info()->addParam(obj, "epsilon", obj.epsilon); |
||||
obj.info()->addParam(obj, "weights", obj.weights, true); |
||||
obj.info()->addParam(obj, "means", obj.means, true); |
||||
obj.info()->addParam(obj, "covs", obj.covs, true)) |
||||
|
||||
bool initModule_ml(void) |
||||
{ |
||||
Ptr<Algorithm> em = createEM_ptr_hidden(); |
||||
return em->info() != 0; |
||||
} |
||||
|
||||
} |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue