mirror of
https://github.com/opencv/opencv.git
synced 2026-07-31 00:03:03 +04:00
completely new C++ persistence implementation (#13011)
* integrated the new C++ persistence; removed old persistence; most of OpenCV compiles fine! the tests have not been run yet * fixed multiple bugs in the new C++ persistence * fixed raw size of the parsed empty sequences * [temporarily] excluded obsolete applications traincascade and createsamples from build * fixed several compiler warnings and multiple test failures * undo changes in cocoa window rendering (that was fixed in another PR) * fixed more compile warnings and the remaining test failures (hopefully) * trying to fix the last little warning
This commit is contained in:
@@ -913,13 +913,23 @@ bool CascadeClassifierImpl::load(const String& filename)
|
||||
if( !fs.isOpened() )
|
||||
return false;
|
||||
|
||||
if( read_(fs.getFirstTopLevelNode()) )
|
||||
FileNode fs_root = fs.getFirstTopLevelNode();
|
||||
|
||||
if( read_(fs_root) )
|
||||
return true;
|
||||
|
||||
fs.release();
|
||||
// probably, it's the cascade in the old format;
|
||||
// let's try to convert it to the new format
|
||||
FileStorage newfs(".yml", FileStorage::WRITE+FileStorage::MEMORY);
|
||||
haar_cvt::convert(fs_root, newfs);
|
||||
std::string newfs_content = newfs.releaseAndGetString();
|
||||
newfs.open(newfs_content, FileStorage::READ+FileStorage::MEMORY);
|
||||
fs_root = newfs.getFirstTopLevelNode();
|
||||
|
||||
oldCascade.reset((CvHaarClassifierCascade*)cvLoad(filename.c_str(), 0, 0, 0));
|
||||
return !oldCascade.empty();
|
||||
if( read_(fs_root) )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CascadeClassifierImpl::read(const FileNode& node)
|
||||
|
||||
@@ -647,4 +647,10 @@ inline int predictCategoricalStump( CascadeClassifierImpl& cascade,
|
||||
sum = (double)tmp;
|
||||
return 1;
|
||||
}
|
||||
|
||||
namespace haar_cvt
|
||||
{
|
||||
bool convert(const FileNode& oldcascade_root, FileStorage& newfs);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
/* Haar features calculation */
|
||||
|
||||
#include "precomp.hpp"
|
||||
#include "cascadedetect.hpp"
|
||||
#include <stdio.h>
|
||||
|
||||
namespace cv
|
||||
@@ -111,13 +112,8 @@ struct HaarStageClassifier
|
||||
std::vector<HaarClassifier> weaks;
|
||||
};
|
||||
|
||||
static bool convert(const String& oldcascade, const String& newcascade)
|
||||
bool convert(const FileNode& oldroot, FileStorage& newfs)
|
||||
{
|
||||
FileStorage oldfs(oldcascade, FileStorage::READ);
|
||||
if( !oldfs.isOpened() )
|
||||
return false;
|
||||
FileNode oldroot = oldfs.getFirstTopLevelNode();
|
||||
|
||||
FileNode sznode = oldroot[ICV_HAAR_SIZE_NAME];
|
||||
if( sznode.empty() )
|
||||
return false;
|
||||
@@ -194,10 +190,6 @@ static bool convert(const String& oldcascade, const String& newcascade)
|
||||
}
|
||||
}
|
||||
|
||||
FileStorage newfs(newcascade, FileStorage::WRITE);
|
||||
if( !newfs.isOpened() )
|
||||
return false;
|
||||
|
||||
int maxWeakCount = 0, nfeatures = (int)features.size();
|
||||
for( i = 0; i < nstages; i++ )
|
||||
maxWeakCount = std::max(maxWeakCount, (int)stages[i].weaks.size());
|
||||
@@ -225,12 +217,12 @@ static bool convert(const String& oldcascade, const String& newcascade)
|
||||
for( j = 0; j < nweaks; j++ )
|
||||
{
|
||||
const HaarClassifier& c = stages[i].weaks[j];
|
||||
newfs << "{" << "internalNodes" << "[";
|
||||
newfs << "{" << "internalNodes" << "[:";
|
||||
int nnodes = (int)c.nodes.size(), nleaves = (int)c.leaves.size();
|
||||
for( k = 0; k < nnodes; k++ )
|
||||
newfs << c.nodes[k].left << c.nodes[k].right
|
||||
<< c.nodes[k].f << c.nodes[k].threshold;
|
||||
newfs << "]" << "leafValues" << "[";
|
||||
newfs << "]" << "leafValues" << "[:";
|
||||
for( k = 0; k < nleaves; k++ )
|
||||
newfs << c.leaves[k];
|
||||
newfs << "]" << "}";
|
||||
@@ -249,7 +241,7 @@ static bool convert(const String& oldcascade, const String& newcascade)
|
||||
{
|
||||
if( j >= 2 && fabs(f.rect[j].weight) < FLT_EPSILON )
|
||||
break;
|
||||
newfs << "[" << f.rect[j].r.x << f.rect[j].r.y <<
|
||||
newfs << "[:" << f.rect[j].r.x << f.rect[j].r.y <<
|
||||
f.rect[j].r.width << f.rect[j].r.height << f.rect[j].weight << "]";
|
||||
}
|
||||
newfs << "]";
|
||||
@@ -266,7 +258,13 @@ static bool convert(const String& oldcascade, const String& newcascade)
|
||||
|
||||
bool CascadeClassifier::convert(const String& oldcascade, const String& newcascade)
|
||||
{
|
||||
bool ok = haar_cvt::convert(oldcascade, newcascade);
|
||||
FileStorage oldfs(oldcascade, FileStorage::READ);
|
||||
FileStorage newfs(newcascade, FileStorage::WRITE);
|
||||
if( !oldfs.isOpened() || !newfs.isOpened() )
|
||||
return false;
|
||||
FileNode oldroot = oldfs.getFirstTopLevelNode();
|
||||
|
||||
bool ok = haar_cvt::convert(oldroot, newfs);
|
||||
if( !ok && newcascade.size() > 0 )
|
||||
remove(newcascade.c_str());
|
||||
return ok;
|
||||
|
||||
@@ -102,26 +102,6 @@ typedef struct CvHidHaarClassifierCascade
|
||||
const int icv_object_win_border = 1;
|
||||
const float icv_stage_threshold_bias = 0.0001f;
|
||||
|
||||
static CvHaarClassifierCascade*
|
||||
icvCreateHaarClassifierCascade( int stage_count )
|
||||
{
|
||||
CvHaarClassifierCascade* cascade = 0;
|
||||
|
||||
int block_size = sizeof(*cascade) + stage_count*sizeof(*cascade->stage_classifier);
|
||||
|
||||
if( stage_count <= 0 )
|
||||
CV_Error( CV_StsOutOfRange, "Number of stages should be positive" );
|
||||
|
||||
cascade = (CvHaarClassifierCascade*)cvAlloc( block_size );
|
||||
memset( cascade, 0, block_size );
|
||||
|
||||
cascade->stage_classifier = (CvHaarStageClassifier*)(cascade + 1);
|
||||
cascade->flags = CV_HAAR_MAGIC_VAL;
|
||||
cascade->count = stage_count;
|
||||
|
||||
return cascade;
|
||||
}
|
||||
|
||||
static void
|
||||
icvReleaseHidHaarClassifierCascade( CvHidHaarClassifierCascade** _cascade )
|
||||
{
|
||||
@@ -1057,7 +1037,6 @@ public:
|
||||
|
||||
}
|
||||
|
||||
|
||||
CvSeq*
|
||||
cvHaarDetectObjectsForROC( const CvArr* _img,
|
||||
CvHaarClassifierCascade* cascade, CvMemStorage* storage,
|
||||
@@ -1373,6 +1352,32 @@ cvHaarDetectObjects( const CvArr* _img,
|
||||
|
||||
}
|
||||
|
||||
CV_IMPL void
|
||||
cvReleaseHaarClassifierCascade( CvHaarClassifierCascade** _cascade )
|
||||
{
|
||||
if( _cascade && *_cascade )
|
||||
{
|
||||
int i, j;
|
||||
CvHaarClassifierCascade* cascade = *_cascade;
|
||||
|
||||
for( i = 0; i < cascade->count; i++ )
|
||||
{
|
||||
for( j = 0; j < cascade->stage_classifier[i].count; j++ )
|
||||
cvFree( &cascade->stage_classifier[i].classifier[j].haar_feature );
|
||||
cvFree( &cascade->stage_classifier[i].classifier );
|
||||
}
|
||||
icvReleaseHidHaarClassifierCascade( &cascade->hid_cascade );
|
||||
cvFree( _cascade );
|
||||
}
|
||||
}
|
||||
|
||||
CV_IMPL CvHaarClassifierCascade*
|
||||
cvLoadHaarClassifierCascade( const char*, CvSize )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
static CvHaarClassifierCascade*
|
||||
icvLoadCascadeCART( const char** input_cascade, int n, CvSize orig_window_size )
|
||||
@@ -1398,7 +1403,7 @@ icvLoadCascadeCART( const char** input_cascade, int n, CvSize orig_window_size )
|
||||
CV_Assert( count > 0 && count < CV_HAAR_STAGE_MAX);
|
||||
cascade->stage_classifier[i].count = count;
|
||||
cascade->stage_classifier[i].classifier =
|
||||
(CvHaarClassifier*)cvAlloc( count*sizeof(cascade->stage_classifier[i].classifier[0]));
|
||||
(CvHaarClassifier*)cvAlloc( count*sizeof(cascade->stage_classifier[i].classifier[0]));
|
||||
|
||||
for( j = 0; j < count; j++ )
|
||||
{
|
||||
@@ -1411,11 +1416,11 @@ icvLoadCascadeCART( const char** input_cascade, int n, CvSize orig_window_size )
|
||||
|
||||
CV_Assert( classifier->count > 0 && classifier->count< CV_HAAR_STAGE_MAX);
|
||||
classifier->haar_feature = (CvHaarFeature*) cvAlloc(
|
||||
classifier->count * ( sizeof( *classifier->haar_feature ) +
|
||||
sizeof( *classifier->threshold ) +
|
||||
sizeof( *classifier->left ) +
|
||||
sizeof( *classifier->right ) ) +
|
||||
(classifier->count + 1) * sizeof( *classifier->alpha ) );
|
||||
classifier->count * ( sizeof( *classifier->haar_feature ) +
|
||||
sizeof( *classifier->threshold ) +
|
||||
sizeof( *classifier->left ) +
|
||||
sizeof( *classifier->right ) ) +
|
||||
(classifier->count + 1) * sizeof( *classifier->alpha ) );
|
||||
classifier->threshold = (float*) (classifier->haar_feature+classifier->count);
|
||||
classifier->left = (int*) (classifier->threshold + classifier->count);
|
||||
classifier->right = (int*) (classifier->left + classifier->count);
|
||||
@@ -1433,8 +1438,8 @@ icvLoadCascadeCART( const char** input_cascade, int n, CvSize orig_window_size )
|
||||
cv::Rect r;
|
||||
int band = 0;
|
||||
sscanf( stage, "%d%d%d%d%d%f%n",
|
||||
&r.x, &r.y, &r.width, &r.height, &band,
|
||||
&(classifier->haar_feature[l].rect[k].weight), &dl );
|
||||
&r.x, &r.y, &r.width, &r.height, &band,
|
||||
&(classifier->haar_feature[l].rect[k].weight), &dl );
|
||||
stage += dl;
|
||||
classifier->haar_feature[l].rect[k].r = cvRect(r);
|
||||
}
|
||||
@@ -1446,12 +1451,12 @@ icvLoadCascadeCART( const char** input_cascade, int n, CvSize orig_window_size )
|
||||
for( k = rects; k < CV_HAAR_FEATURE_MAX; k++ )
|
||||
{
|
||||
memset( classifier->haar_feature[l].rect + k, 0,
|
||||
sizeof(classifier->haar_feature[l].rect[k]) );
|
||||
sizeof(classifier->haar_feature[l].rect[k]) );
|
||||
}
|
||||
|
||||
sscanf( stage, "%f%d%d%n", &(classifier->threshold[l]),
|
||||
&(classifier->left[l]),
|
||||
&(classifier->right[l]), &dl );
|
||||
&(classifier->left[l]),
|
||||
&(classifier->right[l]), &dl );
|
||||
stage += dl;
|
||||
}
|
||||
for( l = 0; l <= classifier->count; l++ )
|
||||
@@ -1557,27 +1562,6 @@ cvLoadHaarClassifierCascade( const char* directory, CvSize orig_window_size )
|
||||
return cascade;
|
||||
}
|
||||
|
||||
|
||||
CV_IMPL void
|
||||
cvReleaseHaarClassifierCascade( CvHaarClassifierCascade** _cascade )
|
||||
{
|
||||
if( _cascade && *_cascade )
|
||||
{
|
||||
int i, j;
|
||||
CvHaarClassifierCascade* cascade = *_cascade;
|
||||
|
||||
for( i = 0; i < cascade->count; i++ )
|
||||
{
|
||||
for( j = 0; j < cascade->stage_classifier[i].count; j++ )
|
||||
cvFree( &cascade->stage_classifier[i].classifier[j].haar_feature );
|
||||
cvFree( &cascade->stage_classifier[i].classifier );
|
||||
}
|
||||
icvReleaseHidHaarClassifierCascade( &cascade->hid_cascade );
|
||||
cvFree( _cascade );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************************\
|
||||
* Persistence functions *
|
||||
\****************************************************************************************/
|
||||
@@ -1605,6 +1589,26 @@ icvIsHaarClassifier( const void* struct_ptr )
|
||||
return CV_IS_HAAR_CLASSIFIER( struct_ptr );
|
||||
}
|
||||
|
||||
static CvHaarClassifierCascade*
|
||||
icvCreateHaarClassifierCascade( int stage_count )
|
||||
{
|
||||
CvHaarClassifierCascade* cascade = 0;
|
||||
|
||||
int block_size = sizeof(*cascade) + stage_count*sizeof(*cascade->stage_classifier);
|
||||
|
||||
if( stage_count <= 0 )
|
||||
CV_Error( CV_StsOutOfRange, "Number of stages should be positive" );
|
||||
|
||||
cascade = (CvHaarClassifierCascade*)cvAlloc( block_size );
|
||||
memset( cascade, 0, block_size );
|
||||
|
||||
cascade->stage_classifier = (CvHaarStageClassifier*)(cascade + 1);
|
||||
cascade->flags = CV_HAAR_MAGIC_VAL;
|
||||
cascade->count = stage_count;
|
||||
|
||||
return cascade;
|
||||
}
|
||||
|
||||
static void*
|
||||
icvReadHaarClassifier( CvFileStorage* fs, CvFileNode* node )
|
||||
{
|
||||
@@ -2124,4 +2128,6 @@ CvType haar_type( CV_TYPE_NAME_HAAR, icvIsHaarClassifier,
|
||||
icvReadHaarClassifier, icvWriteHaarClassifier,
|
||||
icvCloneHaarClassifier );
|
||||
|
||||
#endif
|
||||
|
||||
/* End of file. */
|
||||
|
||||
@@ -2118,62 +2118,6 @@ void HOGDescriptor::detectMultiScale(InputArray img, std::vector<Rect>& foundLoc
|
||||
padding, scale0, finalThreshold, useMeanshiftGrouping);
|
||||
}
|
||||
|
||||
template<typename _ClsName> struct RTTIImpl
|
||||
{
|
||||
public:
|
||||
static int isInstance(const void* ptr)
|
||||
{
|
||||
static _ClsName dummy;
|
||||
static void* dummyp = &dummy;
|
||||
union
|
||||
{
|
||||
const void* p;
|
||||
const void** pp;
|
||||
} a, b;
|
||||
a.p = dummyp;
|
||||
b.p = ptr;
|
||||
return *a.pp == *b.pp;
|
||||
}
|
||||
static void release(void** dbptr)
|
||||
{
|
||||
if(dbptr && *dbptr)
|
||||
{
|
||||
delete (_ClsName*)*dbptr;
|
||||
*dbptr = 0;
|
||||
}
|
||||
}
|
||||
static void* read(CvFileStorage* fs, CvFileNode* n)
|
||||
{
|
||||
FileNode fn(fs, n);
|
||||
_ClsName* obj = new _ClsName;
|
||||
if(obj->read(fn))
|
||||
return obj;
|
||||
delete obj;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void write(CvFileStorage* _fs, const char* name, const void* ptr, CvAttrList)
|
||||
{
|
||||
if(ptr && _fs)
|
||||
{
|
||||
FileStorage fs(_fs, false);
|
||||
((const _ClsName*)ptr)->write(fs, String(name));
|
||||
}
|
||||
}
|
||||
|
||||
static void* clone(const void* ptr)
|
||||
{
|
||||
if(!ptr)
|
||||
return 0;
|
||||
return new _ClsName(*(const _ClsName*)ptr);
|
||||
}
|
||||
};
|
||||
|
||||
typedef RTTIImpl<HOGDescriptor> HOGRTTI;
|
||||
|
||||
CvType hog_type( CV_TYPE_NAME_HOG_DESCRIPTOR, HOGRTTI::isInstance,
|
||||
HOGRTTI::release, HOGRTTI::read, HOGRTTI::write, HOGRTTI::clone);
|
||||
|
||||
std::vector<float> HOGDescriptor::getDefaultPeopleDetector()
|
||||
{
|
||||
static const float detector[] = {
|
||||
|
||||
Reference in New Issue
Block a user