Internal buffers converted to use OpenCV dynamic memory allocation.

pull/3670/head
Olexa Bilaniuk 10 years ago
parent bb01231990
commit f592321771
  1. 281
      modules/calib3d/src/rhorefc.cpp

@ -158,7 +158,6 @@ struct RHO_HEST_REFC{
/* Levenberg-Marquardt Refinement */
struct{
float* ws; /* Levenberg-Marqhard Workspace */
float (* JtJ)[8]; /* JtJ matrix */
float (* tmp1)[8]; /* Temporary 1 */
float* Jte; /* Jte vector */
@ -169,8 +168,14 @@ struct RHO_HEST_REFC{
uint64_t s[2]; /* PRNG state */
} prng;
/* Memory Management */
struct{
cv::Mat perObj;
cv::Mat perRun;
} mem;
/* Initialized? */
int init;
int initialized;
/* Empty constructors and destructors */
@ -202,6 +207,10 @@ struct RHO_HEST_REFC{
/* Methods to implement internals */
inline void allocatePerObj(void);
inline void allocatePerRun(void);
inline void deallocatePerRun(void);
inline void deallocatePerObj(void);
inline int initRun(void);
inline void finiRun(void);
inline int haveExtrinsicGuess(void);
@ -242,9 +251,6 @@ struct RHO_HEST_REFC{
* Prototypes for purely-computational code.
*/
static inline void* almalloc(size_t nBytes);
static inline void alfree (void* ptr);
static inline void sacInitNonRand (double beta,
unsigned start,
unsigned N,
@ -382,36 +388,6 @@ unsigned rhoRefC(RHO_HEST_REFC* p, /* Homography estimation context. */
/**
* Allocate memory aligned to a boundary of MEMALIGN.
*/
static inline void* almalloc(size_t nBytes){
if(nBytes){
unsigned char* ptr = (unsigned char*)malloc(MEM_ALIGN + nBytes);
if(ptr){
unsigned char* adj = (unsigned char*)(((intptr_t)(ptr+MEM_ALIGN))&((intptr_t)(-MEM_ALIGN)));
ptrdiff_t diff = adj - ptr;
adj[-1] = (unsigned char)(diff - 1);
return adj;
}
}
return NULL;
}
/**
* Free aligned memory.
*
* If argument is NULL, do nothing in accordance with free() semantics.
*/
static inline void alfree(void* ptr){
if(ptr){
unsigned char* cptr = (unsigned char*)ptr;
free(cptr - (ptrdiff_t)cptr[-1] - 1);
}
}
/**
* Constructor for RHO_HEST_REFC.
@ -419,7 +395,7 @@ static inline void alfree(void* ptr){
* Does nothing. True initialization is done by initialize().
*/
RHO_HEST_REFC::RHO_HEST_REFC() : init(0){
RHO_HEST_REFC::RHO_HEST_REFC() : initialized(0){
}
@ -427,7 +403,7 @@ RHO_HEST_REFC::RHO_HEST_REFC() : init(0){
* Private copy constructor for RHO_HEST_REFC. Disabled.
*/
RHO_HEST_REFC::RHO_HEST_REFC(const RHO_HEST_REFC&) : init(0){
RHO_HEST_REFC::RHO_HEST_REFC(const RHO_HEST_REFC&) : initialized(0){
}
@ -436,7 +412,7 @@ RHO_HEST_REFC::RHO_HEST_REFC(const RHO_HEST_REFC&) : init(0){
*/
RHO_HEST_REFC::~RHO_HEST_REFC(){
if(init){
if(initialized){
finalize();
}
}
@ -458,37 +434,30 @@ RHO_HEST_REFC::~RHO_HEST_REFC(){
*/
inline int RHO_HEST_REFC::initialize(void){
ctrl.smpl = (unsigned*)almalloc(SMPL_SIZE*sizeof(*ctrl.smpl));
initialized = 0;
allocatePerObj();
curr.pkdPts = (float*) almalloc(SMPL_SIZE*2*2*sizeof(*curr.pkdPts));
curr.H = (float*) almalloc(HSIZE);
curr.inl = NULL;
curr.numInl = 0;
best.H = (float*) almalloc(HSIZE);
best.inl = NULL;
best.numInl = 0;
nr.size = 0;
nr.beta = 0.0;
lm.ws = NULL;
lm.JtJ = NULL;
lm.tmp1 = NULL;
lm.Jte = NULL;
fastSeed((unsigned)cv::theRNG());
int areAllAllocsSuccessful = ctrl.smpl &&
curr.H &&
best.H &&
curr.pkdPts;
int areAllAllocsSuccessful = !mem.perObj.empty();
if(!areAllAllocsSuccessful){
finalize();
}else{
init = 1;
initialized = 1;
}
return areAllAllocsSuccessful;
@ -502,15 +471,10 @@ inline int RHO_HEST_REFC::initialize(void){
*/
inline void RHO_HEST_REFC::finalize(void){
if(init){
alfree(ctrl.smpl);
alfree(curr.H);
alfree(best.H);
alfree(curr.pkdPts);
memset(this, 0, sizeof(*this));
if(initialized){
deallocatePerObj();
init = 0;
initialized = 0;
}
}
@ -651,6 +615,128 @@ unsigned RHO_HEST_REFC::rhoRefC(const float* src, /* Source points */
}
/**
* Allocate per-object dynamic storage.
*
* This includes aligned, fixed-size internal buffers, but excludes any buffers
* whose size cannot be determined ahead-of-time (before the number of matches
* is known).
*
* All buffer memory is allocated in one single shot, and all pointers are
* initialized.
*/
inline void RHO_HEST_REFC::allocatePerObj(void){
/* We have known sizes */
size_t ctrl_smpl_sz = SMPL_SIZE*sizeof(*ctrl.smpl);
size_t curr_pkdPts_sz = SMPL_SIZE*2*2*sizeof(*curr.pkdPts);
size_t curr_H_sz = HSIZE;
size_t best_H_sz = HSIZE;
size_t lm_JtJ_sz = 8*8*sizeof(float);
size_t lm_tmp1_sz = 8*8*sizeof(float);
size_t lm_Jte_sz = 1*8*sizeof(float);
/* We compute offsets */
size_t total = 0;
#define MK_OFFSET(v) \
size_t v ## _of = total; \
total = alignSize(v ## _of + v ## _sz, MEM_ALIGN)
MK_OFFSET(ctrl_smpl);
MK_OFFSET(curr_pkdPts);
MK_OFFSET(curr_H);
MK_OFFSET(best_H);
MK_OFFSET(lm_JtJ);
MK_OFFSET(lm_tmp1);
MK_OFFSET(lm_Jte);
#undef MK_OFFSET
/* Allocate dynamic memory managed by cv::Mat */
mem.perObj.create(1, total + MEM_ALIGN, CV_8UC1);
/* Extract aligned pointer */
unsigned char* ptr = alignPtr(mem.perObj.data, MEM_ALIGN);
/* Assign pointers */
ctrl.smpl = (unsigned*) (ptr + ctrl_smpl_of);
curr.pkdPts = (float*) (ptr + curr_pkdPts_of);
curr.H = (float*) (ptr + curr_H_of);
best.H = (float*) (ptr + best_H_of);
lm.JtJ = (float(*)[8])(ptr + lm_JtJ_of);
lm.tmp1 = (float(*)[8])(ptr + lm_tmp1_of);
lm.Jte = (float*) (ptr + lm_Jte_of);
}
/**
* Allocate per-run dynamic storage.
*
* This includes storage that is proportional to the number of points, such as
* the inlier mask.
*/
inline void RHO_HEST_REFC::allocatePerRun(void){
/* We have known sizes */
size_t best_inl_sz = arg.N;
size_t curr_inl_sz = arg.N;
/* We compute offsets */
size_t total = 0;
#define MK_OFFSET(v) \
size_t v ## _of = total; \
total = alignSize(v ## _of + v ## _sz, MEM_ALIGN)
MK_OFFSET(best_inl);
MK_OFFSET(curr_inl);
#undef MK_OFFSET
/* Allocate dynamic memory managed by cv::Mat */
mem.perRun.create(1, total + MEM_ALIGN, CV_8UC1);
/* Extract aligned pointer */
unsigned char* ptr = alignPtr(mem.perRun.data, MEM_ALIGN);
/* Assign pointers */
best.inl = (char*)(ptr + best_inl_of);
curr.inl = (char*)(ptr + curr_inl_of);
}
/**
* Deallocate per-run dynamic storage.
*
* Undoes the work by allocatePerRun().
*/
inline void RHO_HEST_REFC::deallocatePerRun(void){
best.inl = NULL;
curr.inl = NULL;
mem.perRun.release();
}
/**
* Deallocate per-object dynamic storage.
*
* Undoes the work by allocatePerObj().
*/
inline void RHO_HEST_REFC::deallocatePerObj(void){
ctrl.smpl = NULL;
curr.pkdPts = NULL;
curr.H = NULL;
best.H = NULL;
lm.JtJ = NULL;
lm.tmp1 = NULL;
lm.Jte = NULL;
mem.perObj.release();
}
/**
* Initialize SAC for a run given its arguments.
*
@ -716,46 +802,18 @@ inline int RHO_HEST_REFC::initRun(void){
* Inlier mask alloc.
*
* Runs second because we want to quit as fast as possible if we can't even
* allocate the up tp two masks.
*
* If the calling software wants an output mask, use buffer provided. If
* not, allocate one anyways internally.
* allocate the two masks.
*/
best.inl = arg.inl ? arg.inl : (char*)almalloc(arg.N);
curr.inl = (char*)almalloc(arg.N);
if(!curr.inl || !best.inl){
return 0;
}
allocatePerRun();
memset(best.inl, 0, arg.N);
memset(curr.inl, 0, arg.N);
/**
* LevMarq workspace alloc.
*
* Runs third, consists only in a few conditional mallocs. If malloc fails
* we wish to quit before doing any serious work.
*/
if(isRefineEnabled() || isFinalRefineEnabled()){
lm.ws = (float*)almalloc(2*8*8*sizeof(float) + 1*8*sizeof(float));
if(!lm.ws){
return 0;
}
lm.JtJ = (float(*)[8])(lm.ws + 0*8*8);
lm.tmp1 = (float(*)[8])(lm.ws + 1*8*8);
lm.Jte = (float*) (lm.ws + 2*8*8);
}else{
lm.ws = NULL;
}
/**
* Reset scalar per-run state.
*
* Runs fourth because there's no point in resetting/calculating a large
* Runs third because there's no point in resetting/calculating a large
* number of fields if something in the above junk failed.
*/
@ -801,32 +859,7 @@ inline int RHO_HEST_REFC::initRun(void){
*/
inline void RHO_HEST_REFC::finiRun(void){
/**
* If no output inlier mask was required, free both (internal) masks.
* Else if an (external) mask was provided as argument, find the other
* (the internal one) and free it.
*/
if(arg.inl){
if(arg.inl == best.inl){
alfree(curr.inl);
}else{
alfree(best.inl);
}
}else{
alfree(best.inl);
alfree(curr.inl);
}
best.inl = NULL;
curr.inl = NULL;
/**
* ree the Levenberg-Marquardt workspace.
*/
alfree(lm.ws);
lm.ws = NULL;
deallocatePerRun();
}
/**
@ -1464,9 +1497,9 @@ inline void RHO_HEST_REFC::nStarOptimize(void){
ctrl.phMax = best_n;
ctrl.phNumInl = bestNumInl;
arg.maxI = sacCalcIterBound(arg.cfd,
(double)ctrl.phNumInl/ctrl.phMax,
SMPL_SIZE,
arg.maxI);
(double)ctrl.phNumInl/ctrl.phMax,
SMPL_SIZE,
arg.maxI);
}
}
@ -1488,7 +1521,7 @@ inline void RHO_HEST_REFC::updateBounds(void){
inline void RHO_HEST_REFC::outputModel(void){
if(isBestModelGoodEnough()){
memcpy(arg.finalH, best.H, HSIZE);
if(arg.inl && arg.inl != best.inl){
if(arg.inl){
memcpy(arg.inl, best.inl, arg.N);
}
}else{
@ -1501,8 +1534,12 @@ inline void RHO_HEST_REFC::outputModel(void){
*/
inline void RHO_HEST_REFC::outputZeroH(void){
memset(arg.finalH, 0, HSIZE);
memset(arg.inl, 0, arg.N);
if(arg.finalH){
memset(arg.finalH, 0, HSIZE);
}
if(arg.inl){
memset(arg.inl, 0, arg.N);
}
}
/**

Loading…
Cancel
Save