From 595ec6b852588df9008a5e73755da224f5b14b99 Mon Sep 17 00:00:00 2001 From: Guo Yejun Date: Thu, 8 Jan 2015 16:10:38 +0800 Subject: [PATCH 1/9] correct the size of buf which holds integral sum/sumsq layer_dy is not initialized correctly, it results in a small height of the buffer, and so memory write is out of range in cv::integral. --- modules/objdetect/src/cascadedetect.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/modules/objdetect/src/cascadedetect.cpp b/modules/objdetect/src/cascadedetect.cpp index 6ddc0c878f..c11e552666 100644 --- a/modules/objdetect/src/cascadedetect.cpp +++ b/modules/objdetect/src/cascadedetect.cpp @@ -449,6 +449,12 @@ bool FeatureEvaluator::updateScaleData( Size imgsz, const std::vector& _s s.ystep = sc >= 2 ? 1 : 2; s.scale = sc; s.szi = Size(sz.width+1, sz.height+1); + + if( i == 0 ) + { + layer_dy = s.szi.height; + } + if( layer_ofs.x + s.szi.width > sbufSize.width ) { layer_ofs = Point(0, layer_ofs.y + layer_dy); From 52535b356c2e14a572086ee2554e9f41156abdb7 Mon Sep 17 00:00:00 2001 From: Andrew Senin Date: Thu, 29 Jan 2015 21:29:57 +0400 Subject: [PATCH 2/9] Fix for assert in compute when subimage is used (see issue #4149) --- modules/objdetect/src/hog.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/objdetect/src/hog.cpp b/modules/objdetect/src/hog.cpp index c078c2deba..32a6a21b92 100644 --- a/modules/objdetect/src/hog.cpp +++ b/modules/objdetect/src/hog.cpp @@ -301,8 +301,10 @@ void HOGDescriptor::computeGradient(const Mat& img, Mat& grad, Mat& qangle, for( y = 0; y < gradsize.height; y++ ) { const uchar* imgPtr = img.ptr(ymap[y]); - const uchar* prevPtr = img.ptr(ymap[y-1]); - const uchar* nextPtr = img.ptr(ymap[y+1]); + //In case subimage is used ptr() generates an assert for next and prev rows + //(see http://code.opencv.org/issues/4149) + const uchar* prevPtr = img.data + img.step*ymap[y-1]; + const uchar* nextPtr = img.data + img.step*ymap[y+1]; float* gradPtr = grad.ptr(y); uchar* qanglePtr = qangle.ptr(y); From c85197da5566e135bb9af5873c440ef0c1a9e7d6 Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Tue, 3 Feb 2015 18:11:25 +0300 Subject: [PATCH 3/9] Fixed allocated vector size in ML ANN algorithm - updated return value of points_classifier sample --- modules/ml/src/ann_mlp.cpp | 2 +- samples/cpp/points_classifier.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/ml/src/ann_mlp.cpp b/modules/ml/src/ann_mlp.cpp index 08b5c5f959..3bc173513b 100644 --- a/modules/ml/src/ann_mlp.cpp +++ b/modules/ml/src/ann_mlp.cpp @@ -731,7 +731,7 @@ public: for( i = 0; i < l_count; i++ ) { int n = layer_sizes[i]; - x[i].resize(n); + x[i].resize(n+1); df[i].resize(n); dw[i].create(weights[i].size(), CV_64F); } diff --git a/samples/cpp/points_classifier.cpp b/samples/cpp/points_classifier.cpp index a91a2e3a93..9b274bac1a 100644 --- a/samples/cpp/points_classifier.cpp +++ b/samples/cpp/points_classifier.cpp @@ -398,5 +398,5 @@ int main() } } - return 1; + return 0; } From f5987c258fe2087125622ae64a201f08a7e42428 Mon Sep 17 00:00:00 2001 From: VBystricky Date: Tue, 3 Feb 2015 21:29:27 +0400 Subject: [PATCH 4/9] Fix small error in traincascade application --- apps/traincascade/boost.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/traincascade/boost.cpp b/apps/traincascade/boost.cpp index ac2303300b..5864022048 100644 --- a/apps/traincascade/boost.cpp +++ b/apps/traincascade/boost.cpp @@ -903,7 +903,7 @@ struct FeatureValAndIdxPrecalc : ParallelLoopBody *(idst + fi*sample_count + si) = si; } if ( is_buf_16u ) - std::sort(idst + fi*sample_count, idst + (fi + 1)*sample_count, LessThanIdx(valCache->ptr(fi)) ); + std::sort(udst + fi*sample_count, udst + (fi + 1)*sample_count, LessThanIdx(valCache->ptr(fi)) ); else std::sort(idst + fi*sample_count, idst + (fi + 1)*sample_count, LessThanIdx(valCache->ptr(fi)) ); } From a9325102a2d15d4acf40fad378b17cdff648a7c3 Mon Sep 17 00:00:00 2001 From: Vladislav Vinogradov Date: Wed, 4 Feb 2015 12:39:51 +0300 Subject: [PATCH 5/9] colorize opencv_run_all_tests_unix.sh script output --- .../templates/opencv_run_all_tests_unix.sh.in | 92 +++++++++++++++++-- 1 file changed, 83 insertions(+), 9 deletions(-) diff --git a/cmake/templates/opencv_run_all_tests_unix.sh.in b/cmake/templates/opencv_run_all_tests_unix.sh.in index 77dc1191a9..2e1b167738 100644 --- a/cmake/templates/opencv_run_all_tests_unix.sh.in +++ b/cmake/templates/opencv_run_all_tests_unix.sh.in @@ -1,25 +1,99 @@ #!/bin/sh +# Text style + +TEXT_RED="$(tput setaf 1)" +TEXT_GREEN="$(tput setaf 2)" +TEXT_CYAN="$(tput setaf 6)" +TEXT_RESET="$(tput sgr0)" + +# Test binaries and data paths + OPENCV_TEST_PATH=@CMAKE_INSTALL_PREFIX@/@OPENCV_TEST_INSTALL_PATH@ +OPENCV_PYTHON_TESTS=@OPENCV_PYTHON_TESTS_LIST@ export OPENCV_TEST_DATA_PATH=@CMAKE_INSTALL_PREFIX@/share/OpenCV/testdata +# Run tests + SUMMARY_STATUS=0 +FAILED_TESTS="" +PASSED_TESTS="" + for t in "$OPENCV_TEST_PATH/"opencv_test_* "$OPENCV_TEST_PATH/"opencv_perf_*; do - report="`basename "$t"`-`date --rfc-3339=date`.xml" - "$t" --perf_min_samples=1 --perf_force_samples=1 --gtest_output=xml:"$report" - TEST_STATUS=$? - if [ $TEST_STATUS -ne 0 ]; then - SUMMARY_STATUS=$TEST_STATUS - fi + test_name=`basename "$t"` + report="$test_name-`date --rfc-3339=date`.xml" + + cmd="$t --perf_min_samples=1 --perf_force_samples=1 --gtest_output=xml:\"$report\"" + + seg_reg="s/^/${TEXT_CYAN}[$test_name]${TEXT_RESET} /" # append test name + seg_reg="${seg_reg};s/\[==========\]/${TEXT_GREEN}&${TEXT_RESET}/g" # green for [==========] + seg_reg="${seg_reg};s/\[----------\]/${TEXT_GREEN}&${TEXT_RESET}/g" # green for [----------] + seg_reg="${seg_reg};s/\[ RUN \]/${TEXT_GREEN}&${TEXT_RESET}/g" # green for [ RUN ] + seg_reg="${seg_reg};s/\[ OK \]/${TEXT_GREEN}&${TEXT_RESET}/g" # green for [ OK ] + seg_reg="${seg_reg};s/\[ FAILED \]/${TEXT_RED}&${TEXT_RESET}/g" # red for [ FAILED ] + seg_reg="${seg_reg};s/\[ PASSED \]/${TEXT_GREEN}&${TEXT_RESET}/g" # green for [ PASSED ] + + echo "${TEXT_CYAN}[$test_name]${TEXT_RESET} RUN : $cmd" + eval "$cmd" | sed -r "$seg_reg" + + ret=${PIPESTATUS[0]} + echo "${TEXT_CYAN}[$test_name]${TEXT_RESET} RETURN_CODE : $ret" + + if [ $ret -ne 0 ]; then + echo "${TEXT_CYAN}[$test_name]${TEXT_RESET} ${TEXT_RED}FAILED${TEXT_RESET}" + SUMMARY_STATUS=1 + FAILED_TESTS="$FAILED_TESTS $test_name" + else + echo "${TEXT_CYAN}[$test_name]${TEXT_RESET} ${TEXT_GREEN}OK${TEXT_RESET}" + PASSED_TESTS="$PASSED_TESTS $test_name" + fi + + echo "" +done + +for t in $OPENCV_PYTHON_TESTS; +do + test_name=`basename "$t"` + report="$test_name-`date --rfc-3339=date`.xml" + + cmd="py.test --junitxml $report \"$OPENCV_TEST_PATH\"/$t" + + seg_reg="s/^/${TEXT_CYAN}[$test_name]${TEXT_RESET} /" # append test name + + echo "${TEXT_CYAN}[$test_name]${TEXT_RESET} RUN : $cmd" + eval "$cmd" | sed -r "$seg_reg" + + ret=${PIPESTATUS[0]} + echo "${TEXT_CYAN}[$test_name]${TEXT_RESET} RETURN_CODE : $ret" + + if [ $ret -ne 0 ]; then + echo "${TEXT_CYAN}[$test_name]${TEXT_RESET} ${TEXT_RED}FAILED${TEXT_RESET}" + SUMMARY_STATUS=1 + FAILED_TESTS="$FAILED_TESTS $test_name" + else + echo "${TEXT_CYAN}[$test_name]${TEXT_RESET} ${TEXT_GREEN}OK${TEXT_RESET}" + PASSED_TESTS="$PASSED_TESTS $test_name" + fi + + echo "" done +# Remove temporary test files + rm -f /tmp/__opencv_temp.* +# Report final status + +echo "${TEXT_CYAN}===============================================================${TEXT_RESET}" +echo "${TEXT_CYAN}PASSED TESTS : $PASSED_TESTS${TEXT_RESET}" +echo "${TEXT_CYAN}FAILED TESTS : $FAILED_TESTS${TEXT_RESET}" if [ $SUMMARY_STATUS -eq 0 ]; then - echo "All OpenCV tests finished successfully" + echo "${TEXT_GREEN}STATUS : OK${TEXT_RESET}" + echo "${TEXT_GREEN}STATUS : All OpenCV tests finished successfully${TEXT_RESET}" else - echo "OpenCV tests finished with status $SUMMARY_STATUS" + echo "${TEXT_RED}STATUS : FAIL${TEXT_RESET}" + echo "${TEXT_RED}STATUS : OpenCV tests finished with status $SUMMARY_STATUS${TEXT_RESET}" fi -return $SUMMARY_STATUS \ No newline at end of file +exit $SUMMARY_STATUS From 2054123890a3b2167e2f845047cacc0f1063afc3 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Wed, 4 Feb 2015 13:03:27 +0300 Subject: [PATCH 6/9] coreTlsData -> getCoreTlsData() --- modules/core/src/ocl.cpp | 8 ++++---- modules/core/src/precomp.hpp | 2 +- modules/core/src/rand.cpp | 2 +- modules/core/src/system.cpp | 24 ++++++++++++++++-------- 4 files changed, 22 insertions(+), 14 deletions(-) diff --git a/modules/core/src/ocl.cpp b/modules/core/src/ocl.cpp index efe3b936d5..f7117d8a71 100644 --- a/modules/core/src/ocl.cpp +++ b/modules/core/src/ocl.cpp @@ -1471,7 +1471,7 @@ bool haveOpenCL() bool useOpenCL() { - CoreTLSData* data = coreTlsData.get(); + CoreTLSData* data = getCoreTlsData().get(); if( data->useOpenCL < 0 ) { try @@ -1490,7 +1490,7 @@ void setUseOpenCL(bool flag) { if( haveOpenCL() ) { - CoreTLSData* data = coreTlsData.get(); + CoreTLSData* data = getCoreTlsData().get(); data->useOpenCL = (flag && Device::getDefault().ptr() != NULL) ? 1 : 0; } } @@ -2161,7 +2161,7 @@ size_t Device::profilingTimerResolution() const const Device& Device::getDefault() { const Context& ctx = Context::getDefault(); - int idx = coreTlsData.get()->device; + int idx = getCoreTlsData().get()->device; const Device& device = ctx.device(idx); return device; } @@ -3040,7 +3040,7 @@ void* Queue::ptr() const Queue& Queue::getDefault() { - Queue& q = coreTlsData.get()->oclQueue; + Queue& q = getCoreTlsData().get()->oclQueue; if( !q.p && haveOpenCL() ) q.create(Context::getDefault()); return q; diff --git a/modules/core/src/precomp.hpp b/modules/core/src/precomp.hpp index 0f85cc5568..b35be6ecc2 100644 --- a/modules/core/src/precomp.hpp +++ b/modules/core/src/precomp.hpp @@ -255,7 +255,7 @@ struct CoreTLSData #endif }; -extern TLSData coreTlsData; +TLSData& getCoreTlsData(); #if defined(BUILD_SHARED_LIBS) #if defined WIN32 || defined _WIN32 || defined WINCE diff --git a/modules/core/src/rand.cpp b/modules/core/src/rand.cpp index 1b71900baa..bd1d80ca2b 100644 --- a/modules/core/src/rand.cpp +++ b/modules/core/src/rand.cpp @@ -731,7 +731,7 @@ void RNG::fill( InputOutputArray _mat, int disttype, cv::RNG& cv::theRNG() { - return coreTlsData.get()->rng; + return getCoreTlsData().get()->rng; } void cv::randu(InputOutputArray dst, InputArray low, InputArray high) diff --git a/modules/core/src/system.cpp b/modules/core/src/system.cpp index 2590f215a9..43d5bd0a0b 100644 --- a/modules/core/src/system.cpp +++ b/modules/core/src/system.cpp @@ -1146,12 +1146,20 @@ TLSStorage::~TLSStorage() tlsData_.clear(); } -TLSData coreTlsData; + + +TLSData& getCoreTlsData() +{ + static TLSData *value = new TLSData(); + return *value; +} + + #ifdef CV_COLLECT_IMPL_DATA void setImpl(int flags) { - CoreTLSData* data = coreTlsData.get(); + CoreTLSData* data = getCoreTlsData().get(); data->implFlags = flags; data->implCode.clear(); data->implFun.clear(); @@ -1159,7 +1167,7 @@ void setImpl(int flags) void addImpl(int flag, const char* func) { - CoreTLSData* data = coreTlsData.get(); + CoreTLSData* data = getCoreTlsData().get(); data->implFlags |= flag; if(func) // use lazy collection if name was not specified { @@ -1174,7 +1182,7 @@ void addImpl(int flag, const char* func) int getImpl(std::vector &impl, std::vector &funName) { - CoreTLSData* data = coreTlsData.get(); + CoreTLSData* data = getCoreTlsData().get(); impl = data->implCode; funName = data->implFun; return data->implFlags; // return actual flags for lazy collection @@ -1182,13 +1190,13 @@ int getImpl(std::vector &impl, std::vector &funName) bool useCollection() { - CoreTLSData* data = coreTlsData.get(); + CoreTLSData* data = getCoreTlsData().get(); return data->useCollection; } void setUseCollection(bool flag) { - CoreTLSData* data = coreTlsData.get(); + CoreTLSData* data = getCoreTlsData().get(); data->useCollection = flag; } #endif @@ -1221,7 +1229,7 @@ String getIppErrorLocation() bool useIPP() { #ifdef HAVE_IPP - CoreTLSData* data = coreTlsData.get(); + CoreTLSData* data = getCoreTlsData().get(); if(data->useIPP < 0) { const char* pIppEnv = getenv("OPENCV_IPP"); @@ -1238,7 +1246,7 @@ bool useIPP() void setUseIPP(bool flag) { - CoreTLSData* data = coreTlsData.get(); + CoreTLSData* data = getCoreTlsData().get(); #ifdef HAVE_IPP data->useIPP = flag; #else From adac8c04bb8dcd07f01fe865b75156dea79419e9 Mon Sep 17 00:00:00 2001 From: Olexa Bilaniuk Date: Sat, 7 Feb 2015 00:56:58 -0500 Subject: [PATCH 7/9] Converted to C++ style, + bugfixes. The code has been refactored in response to feedback on Pull Request Also, outputZeroH() now also zeroes the inlier set, much like outputModel(). --- modules/calib3d/src/fundam.cpp | 9 +- modules/calib3d/src/rhorefc.cpp | 1060 ++++++++++++++++++------------- modules/calib3d/src/rhorefc.h | 114 +--- 3 files changed, 643 insertions(+), 540 deletions(-) diff --git a/modules/calib3d/src/fundam.cpp b/modules/calib3d/src/fundam.cpp index 1366e9baa7..5548275830 100644 --- a/modules/calib3d/src/fundam.cpp +++ b/modules/calib3d/src/fundam.cpp @@ -303,8 +303,7 @@ static bool createAndRunRHORegistrator(double confidence, * initialized, used, then finalized. */ - RHO_HEST_REFC p; - rhoRefCInit(&p); + RHO_HEST_REFC* p = rhoRefCInit(); /** * Optional. Ideally, the context would survive across calls to @@ -312,7 +311,7 @@ static bool createAndRunRHORegistrator(double confidence, * to pay is marginally more computational work than strictly needed. */ - rhoRefCEnsureCapacity(&p, npoints, beta); + rhoRefCEnsureCapacity(p, npoints, beta); /** * The critical call. All parameters are heavily documented in rhorefc.h. @@ -325,7 +324,7 @@ static bool createAndRunRHORegistrator(double confidence, * this behaviour is too problematic. */ - result = !!rhoRefC(&p, + result = !!rhoRefC(p, (const float*)src.data, (const float*)dst.data, (char*) tempMask.data, @@ -344,7 +343,7 @@ static bool createAndRunRHORegistrator(double confidence, * Cleanup. */ - rhoRefCFini(&p); + rhoRefCFini(p); /* Convert float homography to double precision. */ tmpH.convertTo(_H, CV_64FC1); diff --git a/modules/calib3d/src/rhorefc.cpp b/modules/calib3d/src/rhorefc.cpp index 3cc9a8a1c3..167accd97c 100644 --- a/modules/calib3d/src/rhorefc.cpp +++ b/modules/calib3d/src/rhorefc.cpp @@ -44,6 +44,7 @@ */ /* Includes */ +#include #include #include #include @@ -52,88 +53,203 @@ #include #include #include +#include #include "rhorefc.h" /* Defines */ -#define MEM_ALIGN 32 -#define HSIZE (3*3*sizeof(float)) -#define MIN_DELTA_CHNG 0.1 -#define REL_CHNG(a, b) (fabs((a) - (b))/(a)) -#define CHNG_SIGNIFICANT(a, b) (REL_CHNG(a, b) > MIN_DELTA_CHNG) -#define CHI_STAT 2.706 -#define CHI_SQ 1.645 -#define RLO 0.25 -#define RHI 0.75 -#define MAXLEVMARQITERS 100 -#define m 4 /* 4 points required per model */ -#define SPRT_T_M 25 /* Guessing 25 match evlauations / 1 model generation */ -#define SPRT_M_S 1 /* 1 model per sample */ -#define SPRT_EPSILON 0.1 /* No explanation */ -#define SPRT_DELTA 0.01 /* No explanation */ -#define LM_GAIN_LO 0.25 /* See sacLMGain(). */ -#define LM_GAIN_HI 0.75 /* See sacLMGain(). */ +const int MEM_ALIGN = 32; +const size_t HSIZE = (3*3*sizeof(float)); +const double MIN_DELTA_CHNG = 0.1; +const double CHI_STAT = 2.706; +const double CHI_SQ = 1.645; +const double RLO = 0.25; +const double RHI = 0.75; +const int MAXLEVMARQITERS = 100; +const int SMPL_SIZE = 4; /* 4 points required per model */ +const int SPRT_T_M = 25; /* Guessing 25 match evlauations / 1 model generation */ +const int SPRT_M_S = 1; /* 1 model per sample */ +const double SPRT_EPSILON = 0.1; /* No explanation */ +const double SPRT_DELTA = 0.01; /* No explanation */ +const double LM_GAIN_LO = 0.25; /* See sacLMGain(). */ +const double LM_GAIN_HI = 0.75; /* See sacLMGain(). */ + + /* For the sake of cv:: namespace ONLY: */ -#ifdef __cplusplus namespace cv{/* For C support, replace with extern "C" { */ -#endif - /* Data Structures */ +struct RHO_HEST_REFC{ + /** + * Virtual Arguments. + * + * Exactly the same as at function call, except: + * - minInl is enforced to be >= 4. + */ + struct{ + const float* src; + const float* dst; + char* inl; + unsigned N; + float maxD; + unsigned maxI; + unsigned rConvg; + double cfd; + unsigned minInl; + double beta; + unsigned flags; + const float* guessH; + float* finalH; + } arg; + + /* PROSAC Control */ + struct{ + unsigned i; /* Iteration Number */ + unsigned phNum; /* Phase Number */ + unsigned phEndI; /* Phase End Iteration */ + double phEndFpI; /* Phase floating-point End Iteration */ + unsigned phMax; /* Termination phase number */ + unsigned phNumInl; /* Number of inliers for termination phase */ + unsigned numModels; /* Number of models tested */ + unsigned* smpl; /* Sample of match indexes */ + } ctrl; + + /* Current model being tested */ + struct{ + float* pkdPts; /* Packed points */ + float* H; /* Homography */ + char* inl; /* Mask of inliers */ + unsigned numInl; /* Number of inliers */ + } curr; + + /* Best model (so far) */ + struct{ + float* H; /* Homography */ + char* inl; /* Mask of inliers */ + unsigned numInl; /* Number of inliers */ + } best; + + /* Non-randomness criterion */ + struct{ + std::vector tbl; /* Non-Randomness: Table */ + unsigned size; /* Non-Randomness: Size */ + double beta; /* Non-Randomness: Beta */ + } nr; + + /* SPRT Evaluator */ + struct{ + double t_M; /* t_M */ + double m_S; /* m_S */ + double epsilon; /* Epsilon */ + double delta; /* delta */ + double A; /* SPRT Threshold */ + unsigned Ntested; /* Number of points tested */ + unsigned Ntestedtotal; /* Number of points tested in total */ + int good; /* Good/bad flag */ + double lambdaAccept; /* Accept multiplier */ + double lambdaReject; /* Reject multiplier */ + } eval; + + /* Levenberg-Marquardt Refinement */ + struct{ + float* ws; /* Levenberg-Marqhard Workspace */ + float (* JtJ)[8]; /* JtJ matrix */ + float (* tmp1)[8]; /* Temporary 1 */ + float* Jte; /* Jte vector */ + } lm; + + /* Initialized? */ + int init; + + + /* Empty constructors and destructors */ + public: + RHO_HEST_REFC(); + private: /* Forbid copying. */ + RHO_HEST_REFC(const RHO_HEST_REFC&); + public: + ~RHO_HEST_REFC(); + + /* Methods to implement external interface */ + inline int initialize(void); + inline int sacEnsureCapacity(unsigned N, double beta); + inline void finalize(void); + unsigned rhoRefC(const float* src, /* Source points */ + const float* dst, /* Destination points */ + char* inl, /* Inlier mask */ + unsigned N, /* = src.length = dst.length = inl.length */ + float maxD, /* Works: 3.0 */ + unsigned maxI, /* Works: 2000 */ + unsigned rConvg, /* Works: 2000 */ + double cfd, /* Works: 0.995 */ + unsigned minInl, /* Minimum: 4 */ + double beta, /* Works: 0.35 */ + unsigned flags, /* Works: 0 */ + const float* guessH, /* Extrinsic guess, NULL if none provided */ + float* finalH); /* Final result. */ + + + + /* Methods to implement internals */ + inline int initRun(void); + inline void finiRun(void); + inline int haveExtrinsicGuess(void); + inline int hypothesize(void); + inline int verify(void); + inline int isNREnabled(void); + inline int isRefineEnabled(void); + inline int isFinalRefineEnabled(void); + inline int PROSACPhaseEndReached(void); + inline void PROSACGoToNextPhase(void); + inline void getPROSACSample(void); + inline int isSampleDegenerate(void); + inline void generateModel(void); + inline int isModelDegenerate(void); + inline void evaluateModelSPRT(void); + inline void updateSPRT(void); + inline void designSPRTTest(void); + inline int isBestModel(void); + inline int isBestModelGoodEnough(void); + inline void saveBestModel(void); + inline void nStarOptimize(void); + inline void updateBounds(void); + inline void outputModel(void); + inline void outputZeroH(void); + inline int canRefine(void); + inline void refine(void); +}; -/* Prototypes */ -static inline void* almalloc(size_t nBytes); -static inline void alfree(void* ptr); - -static inline int sacInitRun(RHO_HEST_REFC* p); -static inline void sacFiniRun(RHO_HEST_REFC* p); -static inline int sacHaveExtrinsicGuess(RHO_HEST_REFC* p); -static inline int sacHypothesize(RHO_HEST_REFC* p); -static inline int sacVerify(RHO_HEST_REFC* p); -static inline int sacIsNREnabled(RHO_HEST_REFC* p); -static inline int sacIsRefineEnabled(RHO_HEST_REFC* p); -static inline int sacIsFinalRefineEnabled(RHO_HEST_REFC* p); -static inline int sacPROSACPhaseEndReached(RHO_HEST_REFC* p); -static inline void sacPROSACGoToNextPhase(RHO_HEST_REFC* p); -static inline void sacGetPROSACSample(RHO_HEST_REFC* p); -static inline int sacIsSampleDegenerate(RHO_HEST_REFC* p); -static inline void sacGenerateModel(RHO_HEST_REFC* p); -static inline int sacIsModelDegenerate(RHO_HEST_REFC* p); -static inline void sacEvaluateModelSPRT(RHO_HEST_REFC* p); -static inline void sacUpdateSPRT(RHO_HEST_REFC* p); -static inline void sacDesignSPRTTest(RHO_HEST_REFC* p); -static inline int sacIsBestModel(RHO_HEST_REFC* p); -static inline int sacIsBestModelGoodEnough(RHO_HEST_REFC* p); -static inline void sacSaveBestModel(RHO_HEST_REFC* p); -static inline void sacInitNonRand(double beta, - unsigned start, - unsigned N, - unsigned* nonRandMinInl); -static inline void sacNStarOptimize(RHO_HEST_REFC* p); -static inline void sacUpdateBounds(RHO_HEST_REFC* p); -static inline void sacOutputModel(RHO_HEST_REFC* p); -static inline void sacOutputZeroH(RHO_HEST_REFC* p); -static inline double sacInitPEndFpI(const unsigned ransacConvg, - const unsigned n, - const unsigned s); -static inline void sacRndSmpl(unsigned sampleSize, - unsigned* currentSample, - unsigned dataSetSize); -static inline double sacRandom(void); -static inline unsigned sacCalcIterBound(double confidence, - double inlierRate, - unsigned sampleSize, - unsigned maxIterBound); -static inline void hFuncRefC(float* packedPoints, float* H); -static inline int sacCanRefine(RHO_HEST_REFC* p); -static inline void sacRefine(RHO_HEST_REFC* p); + +/** + * 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, + unsigned* nonRandMinInl); +static inline double sacInitPEndFpI (const unsigned ransacConvg, + const unsigned n, + const unsigned s); +static inline void sacRndSmpl (unsigned sampleSize, + unsigned* currentSample, + unsigned dataSetSize); +static inline double sacRandom (void); +static inline unsigned sacCalcIterBound (double confidence, + double inlierRate, + unsigned sampleSize, + unsigned maxIterBound); +static inline void hFuncRefC (float* packedPoints, float* H); static inline void sacCalcJacobianErrors(const float* restrict H, const float* restrict src, const float* restrict dst, @@ -142,25 +258,175 @@ static inline void sacCalcJacobianErrors(const float* restrict H, float (* restrict JtJ)[8], float* restrict Jte, float* restrict Sp); -static inline float sacLMGain(const float* dH, - const float* Jte, - const float S, - const float newS, - const float lambda); -static inline int sacChol8x8Damped (const float (*A)[8], - float lambda, - float (*L)[8]); -static inline void sacTRInv8x8(const float (*L)[8], - float (*M)[8]); -static inline void sacTRISolve8x8(const float (*L)[8], - const float* Jte, - float* dH); -static inline void sacSub8x1(float* Hout, const float* H, const float* dH); +static inline float sacLMGain (const float* dH, + const float* Jte, + const float S, + const float newS, + const float lambda); +static inline int sacChol8x8Damped (const float (*A)[8], + float lambda, + float (*L)[8]); +static inline void sacTRInv8x8 (const float (*L)[8], + float (*M)[8]); +static inline void sacTRISolve8x8 (const float (*L)[8], + const float* Jte, + float* dH); +static inline void sacSub8x1 (float* Hout, + const float* H, + const float* dH); /* Functions */ +/** + * External access to context constructor. + * + * @return A pointer to the context if successful; NULL if an error occured. + */ + +RHO_HEST_REFC* rhoRefCInit(void){ + RHO_HEST_REFC* p = new RHO_HEST_REFC; + + if(!p->initialize()){ + delete p; + p = NULL; + } + + return p; +} + + +/** + * External access to non-randomness table resize. + */ + +int rhoRefCEnsureCapacity(RHO_HEST_REFC* p, unsigned N, double beta){ + return p->sacEnsureCapacity(N, beta); +} + + +/** + * External access to context destructor. + * + * @param [in] p The initialized estimator context to finalize. + */ + +void rhoRefCFini(RHO_HEST_REFC* p){ + delete p; +} + + +/** + * Estimates the homography using the given context, matches and parameters to + * PROSAC. + * + * @param [in/out] p The context to use for homography estimation. Must + * be already initialized. Cannot be NULL. + * @param [in] src The pointer to the source points of the matches. + * Must be aligned to 4 bytes. Cannot be NULL. + * @param [in] dst The pointer to the destination points of the matches. + * Must be aligned to 16 bytes. Cannot be NULL. + * @param [out] inl The pointer to the output mask of inlier matches. + * Must be aligned to 16 bytes. May be NULL. + * @param [in] N The number of matches. + * @param [in] maxD The maximum distance. + * @param [in] maxI The maximum number of PROSAC iterations. + * @param [in] rConvg The RANSAC convergence parameter. + * @param [in] cfd The required confidence in the solution. + * @param [in] minInl The minimum required number of inliers. + * @param [in] beta The beta-parameter for the non-randomness criterion. + * @param [in] flags A union of flags to control the estimation. + * @param [in] guessH An extrinsic guess at the solution H, or NULL if + * none provided. + * @param [out] finalH The final estimation of H, or the zero matrix if + * the minimum number of inliers was not met. + * Cannot be NULL. + * @return The number of inliers if the minimum number of + * inliers for acceptance was reached; 0 otherwise. + */ + +unsigned rhoRefC(RHO_HEST_REFC* p, /* Homography estimation context. */ + const float* src, /* Source points */ + const float* dst, /* Destination points */ + char* inl, /* Inlier mask */ + unsigned N, /* = src.length = dst.length = inl.length */ + float maxD, /* Works: 3.0 */ + unsigned maxI, /* Works: 2000 */ + unsigned rConvg, /* Works: 2000 */ + double cfd, /* Works: 0.995 */ + unsigned minInl, /* Minimum: 4 */ + double beta, /* Works: 0.35 */ + unsigned flags, /* Works: 0 */ + const float* guessH, /* Extrinsic guess, NULL if none provided */ + float* finalH){ /* Final result. */ + return p->rhoRefC(src, dst, inl, N, maxD, maxI, rConvg, cfd, minInl, beta, + flags, guessH, finalH); +} + + + +/** + * 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. + * + * Does nothing. True initialization is done by initialize(). + */ + +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){ + +} + +/** + * Destructor for RHO_HEST_REFC. + */ + +RHO_HEST_REFC::~RHO_HEST_REFC(){ + if(init){ + finalize(); + } +} + + + /** * Initialize the estimator context, by allocating the aligned buffers * internally needed. @@ -172,46 +438,63 @@ static inline void sacSub8x1(float* Hout, const float* H, const float* dH); * - The buffer for the best-so-far homography * - Optionally, the non-randomness criterion table * - * @param [in/out] p The uninitialized estimator context to initialize. - * @return 0 if successful; non-zero if an error occured. + * Returns 0 if unsuccessful and non-0 otherwise. */ -int rhoRefCInit(RHO_HEST_REFC* p){ - memset(p, 0, sizeof(*p)); - - p->ctrl.smpl = (unsigned*)almalloc(m*sizeof(*p->ctrl.smpl)); +inline int RHO_HEST_REFC::initialize(void){ + ctrl.smpl = (unsigned*)almalloc(SMPL_SIZE*sizeof(*ctrl.smpl)); - p->curr.pkdPts = (float*) almalloc(m*2*2*sizeof(*p->curr.pkdPts)); - p->curr.H = (float*) almalloc(HSIZE); - p->curr.inl = NULL; - p->curr.numInl = 0; + curr.pkdPts = (float*) almalloc(SMPL_SIZE*2*2*sizeof(*curr.pkdPts)); + curr.H = (float*) almalloc(HSIZE); + curr.inl = NULL; + curr.numInl = 0; - p->best.H = (float*) almalloc(HSIZE); - p->best.inl = NULL; - p->best.numInl = 0; + best.H = (float*) almalloc(HSIZE); + best.inl = NULL; + best.numInl = 0; - p->nr.tbl = NULL;/* By default this table is not computed. */ - p->nr.size = 0; - p->nr.beta = 0.0; + nr.size = 0; + nr.beta = 0.0; - p->lm.ws = NULL; - p->lm.JtJ = NULL; - p->lm.tmp1 = NULL; - p->lm.Jte = NULL; + lm.ws = NULL; + lm.JtJ = NULL; + lm.tmp1 = NULL; + lm.Jte = NULL; - int areAllAllocsSuccessful = p->ctrl.smpl && - p->curr.H && - p->best.H && - p->curr.pkdPts; + int areAllAllocsSuccessful = ctrl.smpl && + curr.H && + best.H && + curr.pkdPts; if(!areAllAllocsSuccessful){ - rhoRefCFini(p); + finalize(); + }else{ + init = 1; } return areAllAllocsSuccessful; } +/** + * Finalize. + * + * Finalize the estimator context, by freeing the aligned buffers used + * internally. + */ + +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)); + + init = 0; + } +} /** * Ensure that the estimator context's internal table for non-randomness @@ -220,7 +503,6 @@ int rhoRefCInit(RHO_HEST_REFC* p){ * * A value of N of 0 requests deallocation of the table. * - * @param [in] p The initialized estimator context * @param [in] N If 0, deallocate internal table. If > 0, ensure that the * internal table is of at least this size, reallocating if * necessary. @@ -231,84 +513,34 @@ int rhoRefCInit(RHO_HEST_REFC* p){ * Writes: nr.* */ -int rhoRefCEnsureCapacity(RHO_HEST_REFC* p, unsigned N, double beta){ - unsigned* tmp; - - +inline int RHO_HEST_REFC::sacEnsureCapacity(unsigned N, double beta){ if(N == 0){ - /* Deallocate table */ - alfree(p->nr.tbl); - p->nr.tbl = NULL; - p->nr.size = 0; + /* Clear. */ + nr.tbl.clear(); + nr.size = 0; + }else if(nr.beta != beta){ + /* Beta changed. Redo all the work. */ + nr.tbl.resize(N); + nr.beta = beta; + sacInitNonRand(nr.beta, 0, N, &nr.tbl[0]); + nr.size = N; + }else if(N > nr.size){ + /* Work is partially done. Do rest of it. */ + nr.tbl.resize(N); + sacInitNonRand(nr.beta, nr.size, N, &nr.tbl[nr.size]); + nr.size = N; }else{ - /* Ensure table at least as big as N and made for correct beta. */ - if(p->nr.tbl && p->nr.beta == beta && p->nr.size >= N){ - /* Table already correctly set up */ - }else{ - if(p->nr.size < N){ - /* Reallocate table because it is too small. */ - tmp = (unsigned*)almalloc(N*sizeof(unsigned)); - if(!tmp){ - return 0; - } - - /* Must recalculate in whole or part. */ - if(p->nr.beta != beta){ - /* Beta changed; recalculate in whole. */ - sacInitNonRand(beta, 0, N, tmp); - alfree(p->nr.tbl); - }else{ - /* Beta did not change; Copy over any work already done. */ - memcpy(tmp, p->nr.tbl, p->nr.size*sizeof(unsigned)); - sacInitNonRand(beta, p->nr.size, N, tmp); - alfree(p->nr.tbl); - } - - p->nr.tbl = tmp; - p->nr.size = N; - p->nr.beta = beta; - }else{ - /* Might recalculate in whole, or not at all. */ - if(p->nr.beta != beta){ - /* Beta changed; recalculate in whole. */ - sacInitNonRand(beta, 0, p->nr.size, p->nr.tbl); - p->nr.beta = beta; - }else{ - /* Beta did not change; Table was already big enough. Do nothing. */ - /* Besides, this is unreachable. */ - } - } - } + /* Work is already done. Do nothing. */ } return 1; } -/** - * Finalize the estimator context, by freeing the aligned buffers used - * internally. - * - * @param [in] p The initialized estimator context to finalize. - */ - -void rhoRefCFini(RHO_HEST_REFC* p){ - alfree(p->ctrl.smpl); - alfree(p->curr.H); - alfree(p->best.H); - alfree(p->curr.pkdPts); - alfree(p->nr.tbl); - - memset(p, 0, sizeof(*p)); -} - - /** * Estimates the homography using the given context, matches and parameters to * PROSAC. * - * @param [in/out] p The context to use for homography estimation. Must - * be already initialized. Cannot be NULL. * @param [in] src The pointer to the source points of the matches. * Must be aligned to 4 bytes. Cannot be NULL. * @param [in] dst The pointer to the destination points of the matches. @@ -332,41 +564,40 @@ void rhoRefCFini(RHO_HEST_REFC* p){ * inliers for acceptance was reached; 0 otherwise. */ -unsigned rhoRefC(RHO_HEST_REFC* restrict p, /* Homography estimation context. */ - const float* restrict src, /* Source points */ - const float* restrict dst, /* Destination points */ - char* restrict inl, /* Inlier mask */ - unsigned N, /* = src.length = dst.length = inl.length */ - float maxD, /* Works: 3.0 */ - unsigned maxI, /* Works: 2000 */ - unsigned rConvg, /* Works: 2000 */ - double cfd, /* Works: 0.995 */ - unsigned minInl, /* Minimum: 4 */ - double beta, /* Works: 0.35 */ - unsigned flags, /* Works: 0 */ - const float* guessH, /* Extrinsic guess, NULL if none provided */ - float* finalH){ /* Final result. */ +unsigned RHO_HEST_REFC::rhoRefC(const float* src, /* Source points */ + const float* dst, /* Destination points */ + char* inl, /* Inlier mask */ + unsigned N, /* = src.length = dst.length = inl.length */ + float maxD, /* Works: 3.0 */ + unsigned maxI, /* Works: 2000 */ + unsigned rConvg, /* Works: 2000 */ + double cfd, /* Works: 0.995 */ + unsigned minInl, /* Minimum: 4 */ + double beta, /* Works: 0.35 */ + unsigned flags, /* Works: 0 */ + const float* guessH, /* Extrinsic guess, NULL if none provided */ + float* finalH){ /* Final result. */ /** * Setup */ - p->arg.src = src; - p->arg.dst = dst; - p->arg.inl = inl; - p->arg.N = N; - p->arg.maxD = maxD; - p->arg.maxI = maxI; - p->arg.rConvg = rConvg; - p->arg.cfd = cfd; - p->arg.minInl = minInl; - p->arg.beta = beta; - p->arg.flags = flags; - p->arg.guessH = guessH; - p->arg.finalH = finalH; - if(!sacInitRun(p)){ - sacOutputZeroH(p); - sacFiniRun(p); + arg.src = src; + arg.dst = dst; + arg.inl = inl; + arg.N = N; + arg.maxD = maxD; + arg.maxI = maxI; + arg.rConvg = rConvg; + arg.cfd = cfd; + arg.minInl = minInl; + arg.beta = beta; + arg.flags = flags; + arg.guessH = guessH; + arg.finalH = finalH; + if(!initRun()){ + outputZeroH(); + finiRun(); return 0; } @@ -374,8 +605,8 @@ unsigned rhoRefC(RHO_HEST_REFC* restrict p, /* Homography estimation conte * Extrinsic Guess */ - if(sacHaveExtrinsicGuess(p)){ - sacVerify(p); + if(haveExtrinsicGuess()){ + verify(); } @@ -383,8 +614,8 @@ unsigned rhoRefC(RHO_HEST_REFC* restrict p, /* Homography estimation conte * PROSAC Loop */ - for(p->ctrl.i=0; p->ctrl.i < p->arg.maxI; p->ctrl.i++){ - sacHypothesize(p) && sacVerify(p); + for(ctrl.i=0; ctrl.i < arg.maxI; ctrl.i++){ + hypothesize() && verify(); } @@ -392,45 +623,13 @@ unsigned rhoRefC(RHO_HEST_REFC* restrict p, /* Homography estimation conte * Teardown */ - if(sacIsFinalRefineEnabled(p) && sacCanRefine(p)){ - sacRefine(p); - } - - sacOutputModel(p); - sacFiniRun(p); - return sacIsBestModelGoodEnough(p) ? p->best.numInl : 0; -} - - -/** - * 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; - } + if(isFinalRefineEnabled() && canRefine()){ + refine(); } - 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); - } + outputModel(); + finiRun(); + return isBestModelGoodEnough() ? best.numInl : 0; } @@ -446,7 +645,7 @@ static inline void alfree(void* ptr){ * Writes: curr.*, best.*, ctrl.*, eval.* */ -static inline int sacInitRun(RHO_HEST_REFC* p){ +inline int RHO_HEST_REFC::initRun(void){ /** * Sanitize arguments. * @@ -454,29 +653,29 @@ static inline int sacInitRun(RHO_HEST_REFC* p){ * mean something or other. */ - if(!p->arg.src || !p->arg.dst){ + if(!arg.src || !arg.dst){ /* Arguments src or dst are insane, must be != NULL */ return 0; } - if(p->arg.N < m){ + if(arg.N < SMPL_SIZE){ /* Argument N is insane, must be >= 4. */ return 0; } - if(p->arg.maxD < 0){ + if(arg.maxD < 0){ /* Argument maxD is insane, must be >= 0. */ return 0; } - if(p->arg.cfd < 0 || p->arg.cfd > 1){ + if(arg.cfd < 0 || arg.cfd > 1){ /* Argument cfd is insane, must be in [0, 1]. */ return 0; } /* Clamp minInl to 4 or higher. */ - p->arg.minInl = p->arg.minInl < m ? m : p->arg.minInl; - if(sacIsNREnabled(p) && (p->arg.beta <= 0 || p->arg.beta >= 1)){ + arg.minInl = arg.minInl < SMPL_SIZE ? SMPL_SIZE : arg.minInl; + if(isNREnabled() && (arg.beta <= 0 || arg.beta >= 1)){ /* Argument beta is insane, must be in (0, 1). */ return 0; } - if(!p->arg.finalH){ + if(!arg.finalH){ /* Argument finalH is insane, must be != NULL */ return 0; } @@ -491,7 +690,7 @@ static inline int sacInitRun(RHO_HEST_REFC* p){ * substruct and the sanity-checked N and beta arguments from above. */ - if(sacIsNREnabled(p) && !rhoRefCEnsureCapacity(p, p->arg.N, p->arg.beta)){ + if(isNREnabled() && !sacEnsureCapacity(arg.N, arg.beta)){ return 0; } @@ -505,15 +704,15 @@ static inline int sacInitRun(RHO_HEST_REFC* p){ * not, allocate one anyways internally. */ - p->best.inl = p->arg.inl ? p->arg.inl : (char*)almalloc(p->arg.N); - p->curr.inl = (char*)almalloc(p->arg.N); + best.inl = arg.inl ? arg.inl : (char*)almalloc(arg.N); + curr.inl = (char*)almalloc(arg.N); - if(!p->curr.inl || !p->best.inl){ + if(!curr.inl || !best.inl){ return 0; } - memset(p->best.inl, 0, p->arg.N); - memset(p->curr.inl, 0, p->arg.N); + memset(best.inl, 0, arg.N); + memset(curr.inl, 0, arg.N); /** * LevMarq workspace alloc. @@ -522,17 +721,17 @@ static inline int sacInitRun(RHO_HEST_REFC* p){ * we wish to quit before doing any serious work. */ - if(sacIsRefineEnabled(p) || sacIsFinalRefineEnabled(p)){ - p->lm.ws = (float*)almalloc(2*8*8*sizeof(float) + 1*8*sizeof(float)); - if(!p->lm.ws){ + if(isRefineEnabled() || isFinalRefineEnabled()){ + lm.ws = (float*)almalloc(2*8*8*sizeof(float) + 1*8*sizeof(float)); + if(!lm.ws){ return 0; } - p->lm.JtJ = (float(*)[8])(p->lm.ws + 0*8*8); - p->lm.tmp1 = (float(*)[8])(p->lm.ws + 1*8*8); - p->lm.Jte = (float*) (p->lm.ws + 2*8*8); + 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{ - p->lm.ws = NULL; + lm.ws = NULL; } /** @@ -542,32 +741,32 @@ static inline int sacInitRun(RHO_HEST_REFC* p){ * number of fields if something in the above junk failed. */ - p->ctrl.i = 0; - p->ctrl.phNum = m; - p->ctrl.phEndI = 1; - p->ctrl.phEndFpI = sacInitPEndFpI(p->arg.rConvg, p->arg.N, m); - p->ctrl.phMax = p->arg.N; - p->ctrl.phNumInl = 0; - p->ctrl.numModels = 0; + ctrl.i = 0; + ctrl.phNum = SMPL_SIZE; + ctrl.phEndI = 1; + ctrl.phEndFpI = sacInitPEndFpI(arg.rConvg, arg.N, SMPL_SIZE); + ctrl.phMax = arg.N; + ctrl.phNumInl = 0; + ctrl.numModels = 0; - if(sacHaveExtrinsicGuess(p)){ - memcpy(p->curr.H, p->arg.guessH, HSIZE); + if(haveExtrinsicGuess()){ + memcpy(curr.H, arg.guessH, HSIZE); }else{ - memset(p->curr.H, 0, HSIZE); + memset(curr.H, 0, HSIZE); } - p->curr.numInl = 0; + curr.numInl = 0; - memset(p->best.H, 0, HSIZE); - p->best.numInl = 0; + memset(best.H, 0, HSIZE); + best.numInl = 0; - p->eval.Ntested = 0; - p->eval.Ntestedtotal = 0; - p->eval.good = 1; - p->eval.t_M = SPRT_T_M; - p->eval.m_S = SPRT_M_S; - p->eval.epsilon = SPRT_EPSILON; - p->eval.delta = SPRT_DELTA; - sacDesignSPRTTest(p); + eval.Ntested = 0; + eval.Ntestedtotal = 0; + eval.good = 1; + eval.t_M = SPRT_T_M; + eval.m_S = SPRT_M_S; + eval.epsilon = SPRT_EPSILON; + eval.delta = SPRT_DELTA; + designSPRTTest(); return 1; } @@ -583,33 +782,33 @@ static inline int sacInitRun(RHO_HEST_REFC* p){ * Writes: curr.inl, best.inl */ -static inline void sacFiniRun(RHO_HEST_REFC* p){ +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(p->arg.inl){ - if(p->arg.inl == p->best.inl){ - alfree(p->curr.inl); + if(arg.inl){ + if(arg.inl == best.inl){ + alfree(curr.inl); }else{ - alfree(p->best.inl); + alfree(best.inl); } }else{ - alfree(p->best.inl); - alfree(p->curr.inl); + alfree(best.inl); + alfree(curr.inl); } - p->best.inl = NULL; - p->curr.inl = NULL; + best.inl = NULL; + curr.inl = NULL; /** * â‚£ree the Levenberg-Marquardt workspace. */ - alfree(p->lm.ws); - p->lm.ws = NULL; + alfree(lm.ws); + lm.ws = NULL; } /** @@ -622,18 +821,18 @@ static inline void sacFiniRun(RHO_HEST_REFC* p){ * non-zero otherwise. */ -static inline int sacHypothesize(RHO_HEST_REFC* p){ - if(sacPROSACPhaseEndReached(p)){ - sacPROSACGoToNextPhase(p); +inline int RHO_HEST_REFC::hypothesize(void){ + if(PROSACPhaseEndReached()){ + PROSACGoToNextPhase(); } - sacGetPROSACSample(p); - if(sacIsSampleDegenerate(p)){ + getPROSACSample(); + if(isSampleDegenerate()){ return 0; } - sacGenerateModel(p); - if(sacIsModelDegenerate(p)){ + generateModel(); + if(isModelDegenerate()){ return 0; } @@ -649,21 +848,21 @@ static inline int sacHypothesize(RHO_HEST_REFC* p){ * Returns 1. */ -static inline int sacVerify(RHO_HEST_REFC* p){ - sacEvaluateModelSPRT(p); - sacUpdateSPRT(p); +inline int RHO_HEST_REFC::verify(void){ + evaluateModelSPRT(); + updateSPRT(); - if(sacIsBestModel(p)){ - sacSaveBestModel(p); + if(isBestModel()){ + saveBestModel(); - if(sacIsRefineEnabled(p) && sacCanRefine(p)){ - sacRefine(p); + if(isRefineEnabled() && canRefine()){ + refine(); } - sacUpdateBounds(p); + updateBounds(); - if(sacIsNREnabled(p)){ - sacNStarOptimize(p); + if(isNREnabled()){ + nStarOptimize(); } } @@ -676,8 +875,8 @@ static inline int sacVerify(RHO_HEST_REFC* p){ * @return Zero if no extrinsic guess was provided; non-zero otherwiseEE. */ -static inline int sacHaveExtrinsicGuess(RHO_HEST_REFC* p){ - return !!p->arg.guessH; +inline int RHO_HEST_REFC::haveExtrinsicGuess(void){ + return !!arg.guessH; } /** @@ -686,8 +885,8 @@ static inline int sacHaveExtrinsicGuess(RHO_HEST_REFC* p){ * @return Zero if non-randomness criterion disabled; non-zero if not. */ -static inline int sacIsNREnabled(RHO_HEST_REFC* p){ - return p->arg.flags & RHO_FLAG_ENABLE_NR; +inline int RHO_HEST_REFC::isNREnabled(void){ + return arg.flags & RHO_FLAG_ENABLE_NR; } /** @@ -696,8 +895,8 @@ static inline int sacIsNREnabled(RHO_HEST_REFC* p){ * @return Zero if best-model-so-far refinement disabled; non-zero if not. */ -static inline int sacIsRefineEnabled(RHO_HEST_REFC* p){ - return p->arg.flags & RHO_FLAG_ENABLE_REFINEMENT; +inline int RHO_HEST_REFC::isRefineEnabled(void){ + return arg.flags & RHO_FLAG_ENABLE_REFINEMENT; } /** @@ -706,8 +905,8 @@ static inline int sacIsRefineEnabled(RHO_HEST_REFC* p){ * @return Zero if final-model refinement disabled; non-zero if not. */ -static inline int sacIsFinalRefineEnabled(RHO_HEST_REFC* p){ - return p->arg.flags & RHO_FLAG_ENABLE_FINAL_REFINEMENT; +inline int RHO_HEST_REFC::isFinalRefineEnabled(void){ + return arg.flags & RHO_FLAG_ENABLE_FINAL_REFINEMENT; } /** @@ -718,8 +917,8 @@ static inline int sacIsFinalRefineEnabled(RHO_HEST_REFC* p){ * Read: i, phEndI, phNum, phMax. */ -static inline int sacPROSACPhaseEndReached(RHO_HEST_REFC* p){ - return p->ctrl.i >= p->ctrl.phEndI && p->ctrl.phNum < p->ctrl.phMax; +inline int RHO_HEST_REFC::PROSACPhaseEndReached(void){ + return ctrl.i >= ctrl.phEndI && ctrl.phNum < ctrl.phMax; } /** @@ -733,13 +932,13 @@ static inline int sacPROSACPhaseEndReached(RHO_HEST_REFC* p){ * Write: phNum, phEndFpI, phEndI */ -static inline void sacPROSACGoToNextPhase(RHO_HEST_REFC* p){ +inline void RHO_HEST_REFC::PROSACGoToNextPhase(void){ double next; - p->ctrl.phNum++; - next = (p->ctrl.phEndFpI * p->ctrl.phNum)/(p->ctrl.phNum - m); - p->ctrl.phEndI += (unsigned)ceil(next - p->ctrl.phEndFpI); - p->ctrl.phEndFpI = next; + ctrl.phNum++; + next = (ctrl.phEndFpI * ctrl.phNum)/(ctrl.phNum - SMPL_SIZE); + ctrl.phEndI += (unsigned)ceil(next - ctrl.phEndFpI); + ctrl.phEndFpI = next; } /** @@ -750,12 +949,13 @@ static inline void sacPROSACGoToNextPhase(RHO_HEST_REFC* p){ * the first phNum-1 matches. */ -static inline void sacGetPROSACSample(RHO_HEST_REFC* p){ - if(p->ctrl.i > p->ctrl.phEndI){ - sacRndSmpl(4, p->ctrl.smpl, p->ctrl.phNum);/* Used to be phMax */ +inline void RHO_HEST_REFC::getPROSACSample(void){ + if(ctrl.i > ctrl.phEndI){ + /* FIXME: Dubious. Review. */ + sacRndSmpl(4, ctrl.smpl, ctrl.phNum);/* Used to be phMax */ }else{ - sacRndSmpl(3, p->ctrl.smpl, p->ctrl.phNum-1); - p->ctrl.smpl[3] = p->ctrl.phNum-1; + sacRndSmpl(3, ctrl.smpl, ctrl.phNum-1); + ctrl.smpl[3] = ctrl.phNum-1; } } @@ -767,10 +967,10 @@ static inline void sacGetPROSACSample(RHO_HEST_REFC* p){ * bad samples. */ -static inline int sacIsSampleDegenerate(RHO_HEST_REFC* p){ - unsigned i0 = p->ctrl.smpl[0], i1 = p->ctrl.smpl[1], i2 = p->ctrl.smpl[2], i3 = p->ctrl.smpl[3]; +inline int RHO_HEST_REFC::isSampleDegenerate(void){ + unsigned i0 = ctrl.smpl[0], i1 = ctrl.smpl[1], i2 = ctrl.smpl[2], i3 = ctrl.smpl[3]; typedef struct{float x,y;} MyPt2f; - MyPt2f* pkdPts = (MyPt2f*)p->curr.pkdPts, *src = (MyPt2f*)p->arg.src, *dst = (MyPt2f*)p->arg.dst; + MyPt2f* pkdPts = (MyPt2f*)curr.pkdPts, *src = (MyPt2f*)arg.src, *dst = (MyPt2f*)arg.dst; /** * Pack the matches selected by the SAC algorithm. @@ -860,8 +1060,8 @@ static inline int sacIsSampleDegenerate(RHO_HEST_REFC* p){ * current homography. */ -static inline void sacGenerateModel(RHO_HEST_REFC* p){ - hFuncRefC(p->curr.pkdPts, p->curr.H); +inline void RHO_HEST_REFC::generateModel(void){ + hFuncRefC(curr.pkdPts, curr.H); } /** @@ -870,9 +1070,9 @@ static inline void sacGenerateModel(RHO_HEST_REFC* p){ * NaN the homography is rejected. */ -static inline int sacIsModelDegenerate(RHO_HEST_REFC* p){ +inline int RHO_HEST_REFC::isModelDegenerate(void){ int degenerate; - float* H = p->curr.H; + float* H = curr.H; float f=H[0]+H[1]+H[2]+H[3]+H[4]+H[5]+H[6]+H[7]; /* degenerate = isnan(f); */ @@ -890,26 +1090,26 @@ static inline int sacIsModelDegenerate(RHO_HEST_REFC* p){ * Writes: eval.*, curr.inl, curr.numInl */ -static inline void sacEvaluateModelSPRT(RHO_HEST_REFC* p){ +inline void RHO_HEST_REFC::evaluateModelSPRT(void){ unsigned i; unsigned isInlier; double lambda = 1.0; - float distSq = p->arg.maxD*p->arg.maxD; - const float* src = p->arg.src; - const float* dst = p->arg.dst; - char* inl = p->curr.inl; - const float* H = p->curr.H; + float distSq = arg.maxD*arg.maxD; + const float* src = arg.src; + const float* dst = arg.dst; + char* inl = curr.inl; + const float* H = curr.H; - p->ctrl.numModels++; + ctrl.numModels++; - p->curr.numInl = 0; - p->eval.Ntested = 0; - p->eval.good = 1; + curr.numInl = 0; + eval.Ntested = 0; + eval.good = 1; /* SCALAR */ - for(i=0;iarg.N && p->eval.good;i++){ + for(i=0;icurr.numInl += isInlier; + curr.numInl += isInlier; *inl++ = (char)isInlier; /* SPRT */ - lambda *= isInlier ? p->eval.lambdaAccept : p->eval.lambdaReject; - p->eval.good = lambda <= p->eval.A; - /* If !p->good, the threshold A was exceeded, so we're rejecting */ + lambda *= isInlier ? eval.lambdaAccept : eval.lambdaReject; + eval.good = lambda <= eval.A; + /* If !good, the threshold A was exceeded, so we're rejecting */ } - p->eval.Ntested = i; - p->eval.Ntestedtotal += i; + eval.Ntested = i; + eval.Ntestedtotal += i; } /** @@ -959,18 +1159,21 @@ static inline void sacEvaluateModelSPRT(RHO_HEST_REFC* p){ * eval.lambdaReject */ -static inline void sacUpdateSPRT(RHO_HEST_REFC* p){ - if(p->eval.good){ - if(sacIsBestModel(p)){ - p->eval.epsilon = (double)p->curr.numInl/p->arg.N; - sacDesignSPRTTest(p); +inline void RHO_HEST_REFC::updateSPRT(void){ + if(eval.good){ + if(isBestModel()){ + eval.epsilon = (double)curr.numInl/arg.N; + designSPRTTest(); } }else{ - double newDelta = (double)p->curr.numInl/p->eval.Ntested; + double newDelta = (double)curr.numInl/eval.Ntested; - if(newDelta > 0 && CHNG_SIGNIFICANT(p->eval.delta, newDelta)){ - p->eval.delta = newDelta; - sacDesignSPRTTest(p); + if(newDelta > 0){ + double relChange = fabs(eval.delta - newDelta)/ eval.delta; + if(relChange > MIN_DELTA_CHNG){ + eval.delta = newDelta; + designSPRTTest(); + } } } } @@ -1044,18 +1247,18 @@ static inline double designSPRTTest(double delta, double epsilon, double t_M, do * Writes: eval.A, eval.lambdaAccept, eval.lambdaReject */ -static inline void sacDesignSPRTTest(RHO_HEST_REFC* p){ - p->eval.A = designSPRTTest(p->eval.delta, p->eval.epsilon, p->eval.t_M, p->eval.m_S); - p->eval.lambdaReject = ((1.0 - p->eval.delta) / (1.0 - p->eval.epsilon)); - p->eval.lambdaAccept = (( p->eval.delta ) / ( p->eval.epsilon )); +inline void RHO_HEST_REFC::designSPRTTest(void){ + eval.A = designSPRTTest(eval.delta, eval.epsilon, eval.t_M, eval.m_S); + eval.lambdaReject = ((1.0 - eval.delta) / (1.0 - eval.epsilon)); + eval.lambdaAccept = (( eval.delta ) / ( eval.epsilon )); } /** * Return whether the current model is the best model so far. */ -static inline int sacIsBestModel(RHO_HEST_REFC* p){ - return p->curr.numInl > p->best.numInl; +inline int RHO_HEST_REFC::isBestModel(void){ + return curr.numInl > best.numInl; } /** @@ -1064,8 +1267,8 @@ static inline int sacIsBestModel(RHO_HEST_REFC* p){ * number of inliers. */ -static inline int sacIsBestModelGoodEnough(RHO_HEST_REFC* p){ - return p->best.numInl >= p->arg.minInl; +inline int RHO_HEST_REFC::isBestModelGoodEnough(void){ + return best.numInl >= arg.minInl; } /** @@ -1073,18 +1276,18 @@ static inline int sacIsBestModelGoodEnough(RHO_HEST_REFC* p){ * and count of inliers between the current and best models. */ -static inline void sacSaveBestModel(RHO_HEST_REFC* p){ - float* H = p->curr.H; - char* inl = p->curr.inl; - unsigned numInl = p->curr.numInl; +inline void RHO_HEST_REFC::saveBestModel(void){ + float* H = curr.H; + char* inl = curr.inl; + unsigned numInl = curr.numInl; - p->curr.H = p->best.H; - p->curr.inl = p->best.inl; - p->curr.numInl = p->best.numInl; + curr.H = best.H; + curr.inl = best.inl; + curr.numInl = best.numInl; - p->best.H = H; - p->best.inl = inl; - p->best.numInl = numInl; + best.H = H; + best.inl = inl; + best.numInl = numInl; } /** @@ -1095,13 +1298,13 @@ static inline void sacInitNonRand(double beta, unsigned start, unsigned N, unsigned* nonRandMinInl){ - unsigned n = m+1 > start ? m+1 : start; + unsigned n = SMPL_SIZE+1 > start ? SMPL_SIZE+1 : start; double beta_beta1_sq_chi = sqrt(beta*(1.0-beta)) * CHI_SQ; for(; n < N; n++){ double mu = n * beta; double sigma = sqrt(n)* beta_beta1_sq_chi; - unsigned i_min = (unsigned)ceil(m + mu + sigma); + unsigned i_min = (unsigned)ceil(SMPL_SIZE + mu + sigma); nonRandMinInl[n] = i_min; } @@ -1112,31 +1315,31 @@ static inline void sacInitNonRand(double beta, * of PROSAC. */ -static inline void sacNStarOptimize(RHO_HEST_REFC* p){ - unsigned min_sample_length = 10*2; /*(p->N * INLIERS_RATIO) */ - unsigned best_n = p->arg.N; +inline void RHO_HEST_REFC::nStarOptimize(void){ + unsigned min_sample_length = 10*2; /*(N * INLIERS_RATIO) */ + unsigned best_n = arg.N; unsigned test_n = best_n; - unsigned bestNumInl = p->best.numInl; + unsigned bestNumInl = best.numInl; unsigned testNumInl = bestNumInl; for(;test_n > min_sample_length && testNumInl;test_n--){ if(testNumInl*best_n > bestNumInl*test_n){ - if(testNumInl < p->nr.tbl[test_n]){ + if(testNumInl < nr.tbl[test_n]){ break; } best_n = test_n; bestNumInl = testNumInl; } - testNumInl -= !!p->arg.inl[test_n-1]; + testNumInl -= !!arg.inl[test_n-1]; } - if(bestNumInl*p->ctrl.phMax > p->ctrl.phNumInl*best_n){ - p->ctrl.phMax = best_n; - p->ctrl.phNumInl = bestNumInl; - p->arg.maxI = sacCalcIterBound(p->arg.cfd, - (double)p->ctrl.phNumInl/p->ctrl.phMax, - m, - p->arg.maxI); + if(bestNumInl*ctrl.phMax > ctrl.phNumInl*best_n){ + ctrl.phMax = best_n; + ctrl.phNumInl = bestNumInl; + arg.maxI = sacCalcIterBound(arg.cfd, + (double)ctrl.phNumInl/ctrl.phMax, + SMPL_SIZE, + arg.maxI); } } @@ -1144,25 +1347,25 @@ static inline void sacNStarOptimize(RHO_HEST_REFC* p){ * Classic RANSAC iteration bound based on largest # of inliers. */ -static inline void sacUpdateBounds(RHO_HEST_REFC* p){ - p->arg.maxI = sacCalcIterBound(p->arg.cfd, - (double)p->best.numInl/p->arg.N, - m, - p->arg.maxI); +inline void RHO_HEST_REFC::updateBounds(void){ + arg.maxI = sacCalcIterBound(arg.cfd, + (double)best.numInl/arg.N, + SMPL_SIZE, + arg.maxI); } /** * Ouput the best model so far to the output argument. */ -static inline void sacOutputModel(RHO_HEST_REFC* p){ - if(sacIsBestModelGoodEnough(p)){ - memcpy(p->arg.finalH, p->best.H, HSIZE); - if(p->arg.inl != p->best.inl){ - memcpy(p->arg.inl, p->best.inl, p->arg.N); +inline void RHO_HEST_REFC::outputModel(void){ + if(isBestModelGoodEnough()){ + memcpy(arg.finalH, best.H, HSIZE); + if(arg.inl != best.inl){ + memcpy(arg.inl, best.inl, arg.N); } }else{ - sacOutputZeroH(p); + outputZeroH(); } } @@ -1170,8 +1373,9 @@ static inline void sacOutputModel(RHO_HEST_REFC* p){ * Ouput a zeroed H to the output argument. */ -static inline void sacOutputZeroH(RHO_HEST_REFC* p){ - memset(p->arg.finalH, 0, HSIZE); +inline void RHO_HEST_REFC::outputZeroH(void){ + memset(arg.finalH, 0, HSIZE); + memset(arg.inl, 0, arg.N); } /** @@ -1572,20 +1776,20 @@ static void hFuncRefC(float* packedPoints,/* Source (four x,y float coordinates) * NB This is separate from whether it is *enabled*. */ -static inline int sacCanRefine(RHO_HEST_REFC* p){ +inline int RHO_HEST_REFC::canRefine(void){ /** * If we only have 4 matches, GE's result is already optimal and cannot * be refined any further. */ - return p->best.numInl > m; + return best.numInl > SMPL_SIZE; } /** * Refines the best-so-far homography (p->best.H). */ -static inline void sacRefine(RHO_HEST_REFC* p){ +inline void RHO_HEST_REFC::refine(void){ int i; float S, newS; /* Sum of squared errors */ float gain; /* Gain-parameter. */ @@ -1597,8 +1801,8 @@ static inline void sacRefine(RHO_HEST_REFC* p){ */ /* Find initial conditions */ - sacCalcJacobianErrors(p->best.H, p->arg.src, p->arg.dst, p->arg.inl, p->arg.N, - p->lm.JtJ, p->lm.Jte, &S); + sacCalcJacobianErrors(best.H, arg.src, arg.dst, arg.inl, arg.N, + lm.JtJ, lm.Jte, &S); /*Levenberg-Marquardt Loop.*/ for(i=0;ilm.JtJ, L, p->lm.tmp1)){ + while(!sacChol8x8Damped(lm.JtJ, L, lm.tmp1)){ L *= 2.0f; } - sacTRInv8x8 (p->lm.tmp1, p->lm.tmp1); - sacTRISolve8x8(p->lm.tmp1, p->lm.Jte, dH); - sacSub8x1 (newH, p->best.H, dH); - sacCalcJacobianErrors(newH, p->arg.src, p->arg.dst, p->arg.inl, p->arg.N, + sacTRInv8x8 (lm.tmp1, lm.tmp1); + sacTRISolve8x8(lm.tmp1, lm.Jte, dH); + sacSub8x1 (newH, best.H, dH); + sacCalcJacobianErrors(newH, arg.src, arg.dst, arg.inl, arg.N, NULL, NULL, &newS); - gain = sacLMGain(dH, p->lm.Jte, S, newS, L); + gain = sacLMGain(dH, lm.Jte, S, newS, L); /*printf("Lambda: %12.6f S: %12.6f newS: %12.6f Gain: %12.6f\n", L, S, newS, gain);*/ @@ -1656,9 +1860,9 @@ static inline void sacRefine(RHO_HEST_REFC* p){ if(gain > 0){ S = newS; - memcpy(p->best.H, newH, sizeof(newH)); - sacCalcJacobianErrors(p->best.H, p->arg.src, p->arg.dst, p->arg.inl, p->arg.N, - p->lm.JtJ, p->lm.Jte, &S); + memcpy(best.H, newH, sizeof(newH)); + sacCalcJacobianErrors(best.H, arg.src, arg.dst, arg.inl, arg.N, + lm.JtJ, lm.Jte, &S); } } } @@ -2165,7 +2369,5 @@ static inline void sacSub8x1(float* Hout, const float* H, const float* dH){ } - -#ifdef __cplusplus +/* End namespace cv */ } -#endif diff --git a/modules/calib3d/src/rhorefc.h b/modules/calib3d/src/rhorefc.h index be7012f002..49bc58a863 100644 --- a/modules/calib3d/src/rhorefc.h +++ b/modules/calib3d/src/rhorefc.h @@ -56,7 +56,6 @@ /* Defines */ -#ifdef __cplusplus /* C++ does not have the restrict keyword. */ #ifdef restrict @@ -64,15 +63,6 @@ #endif #define restrict -#else - -/* C99 and over has the restrict keyword. */ -#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L -#define restrict -#endif - -#endif - /* Flags */ #ifndef RHO_FLAG_NONE @@ -90,101 +80,17 @@ +/* Namespace cv */ +namespace cv{ + /* Data structures */ /** * Homography Estimation context. */ -typedef struct{ - /** - * Virtual Arguments. - * - * Exactly the same as at function call, except: - * - minInl is enforced to be >= 4. - */ - - struct{ - const float* restrict src; - const float* restrict dst; - char* restrict inl; - unsigned N; - float maxD; - unsigned maxI; - unsigned rConvg; - double cfd; - unsigned minInl; - double beta; - unsigned flags; - const float* guessH; - float* finalH; - } arg; - - /* PROSAC Control */ - struct{ - unsigned i; /* Iteration Number */ - unsigned phNum; /* Phase Number */ - unsigned phEndI; /* Phase End Iteration */ - double phEndFpI; /* Phase floating-point End Iteration */ - unsigned phMax; /* Termination phase number */ - unsigned phNumInl; /* Number of inliers for termination phase */ - unsigned numModels; /* Number of models tested */ - unsigned* restrict smpl; /* Sample of match indexes */ - } ctrl; - - /* Current model being tested */ - struct{ - float* restrict pkdPts; /* Packed points */ - float* restrict H; /* Homography */ - char* restrict inl; /* Mask of inliers */ - unsigned numInl; /* Number of inliers */ - } curr; - - /* Best model (so far) */ - struct{ - float* restrict H; /* Homography */ - char* restrict inl; /* Mask of inliers */ - unsigned numInl; /* Number of inliers */ - } best; - - /* Non-randomness criterion */ - struct{ - unsigned* restrict tbl; /* Non-Randomness: Table */ - unsigned size; /* Non-Randomness: Size */ - double beta; /* Non-Randomness: Beta */ - } nr; - - /* SPRT Evaluator */ - struct{ - double t_M; /* t_M */ - double m_S; /* m_S */ - double epsilon; /* Epsilon */ - double delta; /* delta */ - double A; /* SPRT Threshold */ - unsigned Ntested; /* Number of points tested */ - unsigned Ntestedtotal; /* Number of points tested in total */ - int good; /* Good/bad flag */ - double lambdaAccept; /* Accept multiplier */ - double lambdaReject; /* Reject multiplier */ - } eval; - - /* Levenberg-Marquardt Refinement */ - struct{ - float* ws; /* Levenberg-Marqhard Workspace */ - float (* restrict JtJ)[8]; /* JtJ matrix */ - float (* restrict tmp1)[8]; /* Temporary 1 */ - float* restrict Jte; /* Jte vector */ - } lm; -} RHO_HEST_REFC; - - - -/* Extern C */ -#ifdef __cplusplus -namespace cv{ -/* extern "C" { */ -#endif - +struct RHO_HEST_REFC; +typedef struct RHO_HEST_REFC RHO_HEST_REFC; /* Functions */ @@ -193,11 +99,10 @@ namespace cv{ * Initialize the estimator context, by allocating the aligned buffers * internally needed. * - * @param [in/out] p The uninitialized estimator context to initialize. - * @return 0 if successful; non-zero if an error occured. + * @return A pointer to the context if successful; NULL if an error occured. */ -int rhoRefCInit(RHO_HEST_REFC* p); +RHO_HEST_REFC* rhoRefCInit(void); /** @@ -355,11 +260,8 @@ unsigned rhoRefC(RHO_HEST_REFC* restrict p, /* Homography estimation conte -/* Extern C */ -#ifdef __cplusplus -/* } *//* End extern "C" */ +/* End Namespace cv */ } -#endif From ccd33a721e6b45ab2c392293200d02edf7923a7b Mon Sep 17 00:00:00 2001 From: Olexa Bilaniuk Date: Sat, 7 Feb 2015 01:19:40 -0500 Subject: [PATCH 8/9] Fixed build failures related to designSPRTTest(). --- modules/calib3d/src/rhorefc.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/calib3d/src/rhorefc.cpp b/modules/calib3d/src/rhorefc.cpp index 167accd97c..03ec79ebe5 100644 --- a/modules/calib3d/src/rhorefc.cpp +++ b/modules/calib3d/src/rhorefc.cpp @@ -1192,7 +1192,7 @@ inline void RHO_HEST_REFC::updateSPRT(void){ * m_S: The number of models that are verified per sample. */ -static inline double designSPRTTest(double delta, double epsilon, double t_M, double m_S){ +static inline double sacDesignSPRTTest(double delta, double epsilon, double t_M, double m_S){ double An, C, K, prevAn; unsigned i; @@ -1248,7 +1248,7 @@ static inline double designSPRTTest(double delta, double epsilon, double t_M, do */ inline void RHO_HEST_REFC::designSPRTTest(void){ - eval.A = designSPRTTest(eval.delta, eval.epsilon, eval.t_M, eval.m_S); + eval.A = sacDesignSPRTTest(eval.delta, eval.epsilon, eval.t_M, eval.m_S); eval.lambdaReject = ((1.0 - eval.delta) / (1.0 - eval.epsilon)); eval.lambdaAccept = (( eval.delta ) / ( eval.epsilon )); } From ff2509af56bb694c07edd80eb102e5e1edff41c3 Mon Sep 17 00:00:00 2001 From: Olexa Bilaniuk Date: Thu, 12 Feb 2015 14:42:37 -0500 Subject: [PATCH 9/9] Fixed printouts in testcase to blame the correct method for a failure. Previously, certain test failures by the method RHO would result in an error blaming RANSAC instead. The fix involves a parameter change to several functions in test_homography.cpp. --- modules/calib3d/test/test_homography.cpp | 34 ++++++++++++------------ 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/modules/calib3d/test/test_homography.cpp b/modules/calib3d/test/test_homography.cpp index 1199cd6cd0..a31b75d2b7 100644 --- a/modules/calib3d/test/test_homography.cpp +++ b/modules/calib3d/test/test_homography.cpp @@ -94,12 +94,12 @@ private: void print_information_1(int j, int N, int method, const Mat& H); void print_information_2(int j, int N, int method, const Mat& H, const Mat& H_res, int k, double diff); - void print_information_3(int j, int N, const Mat& mask); + void print_information_3(int method, int j, int N, const Mat& mask); void print_information_4(int method, int j, int N, int k, int l, double diff); void print_information_5(int method, int j, int N, int l, double diff); - void print_information_6(int j, int N, int k, double diff, bool value); - void print_information_7(int j, int N, int k, double diff, bool original_value, bool found_value); - void print_information_8(int j, int N, int k, int l, double diff); + void print_information_6(int method, int j, int N, int k, double diff, bool value); + void print_information_7(int method, int j, int N, int k, double diff, bool original_value, bool found_value); + void print_information_8(int method, int j, int N, int k, int l, double diff); }; CV_HomographyTest::CV_HomographyTest() : max_diff(1e-2f), max_2diff(2e-2f) @@ -166,13 +166,13 @@ void CV_HomographyTest::print_information_2(int j, int N, int _method, const Mat cout << "Maximum allowed difference: " << max_diff << endl; cout << endl; } -void CV_HomographyTest::print_information_3(int j, int N, const Mat& mask) +void CV_HomographyTest::print_information_3(int _method, int j, int N, const Mat& mask) { cout << endl; cout << "Checking for inliers/outliers mask..." << endl; cout << endl; cout << "Type of srcPoints: "; if ((j>-1) && (j<2)) cout << "Mat of CV_32FC2"; else cout << "vector "; cout << " Type of dstPoints: "; if (j % 2 == 0) cout << "Mat of CV_32FC2"; else cout << "vector "; cout << endl; cout << "Count of points: " << N << endl; cout << endl; - cout << "Method: RANSAC" << endl; + cout << "Method: "; if (_method == RANSAC) cout << "RANSAC" << endl; else if (_method == cv::RHO) cout << "RHO" << endl; else cout << _method << endl; cout << "Found mask:" << endl; cout << endl; cout << mask << endl; cout << endl; cout << "Number of rows: " << mask.rows << " Number of cols: " << mask.cols << endl; cout << endl; @@ -205,10 +205,10 @@ void CV_HomographyTest::print_information_5(int _method, int j, int N, int l, do cout << "Maxumum allowed difference: " << max_diff << endl; cout << endl; } -void CV_HomographyTest::print_information_6(int j, int N, int k, double diff, bool value) +void CV_HomographyTest::print_information_6(int _method, int j, int N, int k, double diff, bool value) { cout << endl; cout << "Checking for inliers/outliers mask..." << endl; cout << endl; - cout << "Method: RANSAC" << endl; + cout << "Method: "; if (_method == RANSAC) cout << "RANSAC" << endl; else if (_method == cv::RHO) cout << "RHO" << endl; else cout << _method << endl; cout << "Type of srcPoints: "; if ((j>-1) && (j<2)) cout << "Mat of CV_32FC2"; else cout << "vector "; cout << " Type of dstPoints: "; if (j % 2 == 0) cout << "Mat of CV_32FC2"; else cout << "vector "; cout << endl; cout << "Count of points: " << N << " " << endl; @@ -218,10 +218,10 @@ void CV_HomographyTest::print_information_6(int j, int N, int k, double diff, bo cout << "Value of found mask: "<< value << endl; cout << endl; } -void CV_HomographyTest::print_information_7(int j, int N, int k, double diff, bool original_value, bool found_value) +void CV_HomographyTest::print_information_7(int _method, int j, int N, int k, double diff, bool original_value, bool found_value) { cout << endl; cout << "Checking for inliers/outliers mask..." << endl; cout << endl; - cout << "Method: RANSAC" << endl; + cout << "Method: "; if (_method == RANSAC) cout << "RANSAC" << endl; else if (_method == cv::RHO) cout << "RHO" << endl; else cout << _method << endl; cout << "Type of srcPoints: "; if ((j>-1) && (j<2)) cout << "Mat of CV_32FC2"; else cout << "vector "; cout << " Type of dstPoints: "; if (j % 2 == 0) cout << "Mat of CV_32FC2"; else cout << "vector "; cout << endl; cout << "Count of points: " << N << " " << endl; @@ -231,10 +231,10 @@ void CV_HomographyTest::print_information_7(int j, int N, int k, double diff, bo cout << "Value of original mask: "<< original_value << " Value of found mask: " << found_value << endl; cout << endl; } -void CV_HomographyTest::print_information_8(int j, int N, int k, int l, double diff) +void CV_HomographyTest::print_information_8(int _method, int j, int N, int k, int l, double diff) { cout << endl; cout << "Checking for reprojection error of inlier..." << endl; cout << endl; - cout << "Method: RANSAC" << endl; + cout << "Method: "; if (_method == RANSAC) cout << "RANSAC" << endl; else if (_method == cv::RHO) cout << "RHO" << endl; else cout << _method << endl; cout << "Sigma of normal noise: " << sigma << endl; cout << "Type of srcPoints: "; if ((j>-1) && (j<2)) cout << "Mat of CV_32FC2"; else cout << "vector "; cout << " Type of dstPoints: "; if (j % 2 == 0) cout << "Mat of CV_32FC2"; else cout << "vector "; cout << endl; @@ -371,7 +371,7 @@ void CV_HomographyTest::run(int) if (code) { - print_information_3(j, N, mask[j]); + print_information_3(method, j, N, mask[j]); switch (code) { @@ -490,7 +490,7 @@ void CV_HomographyTest::run(int) if (code) { - print_information_3(j, N, mask_res[j]); + print_information_3(method, j, N, mask_res[j]); switch (code) { @@ -522,14 +522,14 @@ void CV_HomographyTest::run(int) if (mask_res[j].at(k, 0) != (diff <= reproj_threshold)) { - print_information_6(j, N, k, diff, mask_res[j].at(k, 0)); + print_information_6(method, j, N, k, diff, mask_res[j].at(k, 0)); CV_Error(CALIB3D_HOMOGRAPHY_ERROR_RANSAC_MASK, MESSAGE_RANSAC_MASK_4); return; } if (mask.at(k, 0) && !mask_res[j].at(k, 0)) { - print_information_7(j, N, k, diff, mask.at(k, 0), mask_res[j].at(k, 0)); + print_information_7(method, j, N, k, diff, mask.at(k, 0), mask_res[j].at(k, 0)); CV_Error(CALIB3D_HOMOGRAPHY_ERROR_RANSAC_MASK, MESSAGE_RANSAC_MASK_5); return; } @@ -549,7 +549,7 @@ void CV_HomographyTest::run(int) if (diff - cv::norm(noise_2d, NORM_TYPE[l]) > max_2diff) { - print_information_8(j, N, k, l, diff - cv::norm(noise_2d, NORM_TYPE[l])); + print_information_8(method, j, N, k, l, diff - cv::norm(noise_2d, NORM_TYPE[l])); CV_Error(CALIB3D_HOMOGRAPHY_ERROR_RANSAC_DIFF, MESSAGE_RANSAC_DIFF); return; }