opencv_traincascade crashing with maxDepth > 3 (Bug #2991)
Description
I used opencv_traincascade with a clean clone from git opencv master, as well as 2.4.5.
If you set the maxDepth parameter > 3 opencv_traincascade segfaults when writing the trained stage.
I was able to hack-fix it and remove training, but someone with a deeper knowlegde of the code should find a cleaner fix.
Using gdb and valgrind I found 3 bugs related to the problem which are:
1)
==3024== Conditional jump or move depends on uninitialised value(s) ==3024== at 0x528CD9F: CvBoostTree::find_split_cat_class(CvDTreeNode*, int, float, CvDTreeSplit*, unsigned char*) (boost.cpp:410) ==3024== by 0x52766D3: cv::DTreeBestSplitFinder::operator()(cv::BlockedRange const&) (tree.cpp:1918) ==3024== by 0x527680E: CvDTree::find_best_split(CvDTreeNode*) (internal.hpp:251) ==3024== by 0x526FACF: CvDTree::try_split_node(CvDTreeNode*) (tree.cpp:1699) ==3024== by 0x528AAB5: CvBoostTree::try_split_node(CvDTreeNode*) (boost.cpp:163) ==3024== by 0x526F02F: CvDTree::do_train(CvMat const*) (tree.cpp:1645) ==3024== by 0x41C9A5: CvCascadeBoost::train(CvFeatureEvaluator const*, int, int, int, CvCascadeBoostParams const&) (boost.cpp:1302) ==3024== by 0x41318A: CvCascadeClassifier::train(std::string, std::string, std::string, int, int, int, int, int, CvCascadeParams const&, CvFeatureParams const&, CvCascadeBoostParams const&, bool) (cascadeclassifier.cpp:213) ==3024== by 0x40BD84: main (traincascade.cpp:110) ==3024==
This is just a minor issue caused by split_criteria not being initialized properly. I fixed it by
CvBoostParams::CvBoostParams() { split_criteria = CvBoost::DEFAULT; boost_type = CvBoost::REAL; weak_count = 100; weight_trim_rate = 0.95; cv_folds = 0; max_depth = 1; }
2) valgrind furthermore reported several invalid writes during tree-export all looking like this:
==3024== Invalid write of size 4 ==3024== at 0x41D981: CvCascadeBoostTree::write(cv::FileStorage&, cv::Mat const&) (boost.cpp:927) ==3024== by 0x41ED11: CvCascadeBoost::write(cv::FileStorage&, cv::Mat const&) const (boost.cpp:1645) ==3024== by 0x413624: CvCascadeClassifier::train(std::string, std::string, std::string, int, int, int, int, int, CvCascadeParams const&, CvFeatureParams const&, CvCascadeBoostParams const&, bool) (cascadeclassifier.cpp:248) ==3024== by 0x40BD84: main (traincascade.cpp:110) ==3024== Address 0xa279538 is 0 bytes after a block of size 8 alloc'd ==3024== at 0x4C225BA: operator new[](unsigned long) (vg_replace_malloc.c:264) ==3024== by 0x41D1C2: CvCascadeBoostTree::write(cv::FileStorage&, cv::Mat const&) (boost.cpp:911) ==3024== by 0x41ED11: CvCascadeBoost::write(cv::FileStorage&, cv::Mat const&) const (boost.cpp:1645) ==3024== by 0x413624: CvCascadeClassifier::train(std::string, std::string, std::string, int, int, int, int, int, CvCascadeParams const&, CvFeatureParams const&, CvCascadeBoostParams const&, bool) (cascadeclassifier.cpp:248) ==3024== by 0x40BD84: main (traincascade.cpp:110)
This is caused by a wrong calculation of the number of to be expected tree nodes in function
void CvCascadeBoostTree::write( FileStorage &fs, const Mat& featureMap )
When I changed
int size = (int)pow( 2.f, (float)ensemble->get_params().max_depth); Ptr<float> leafVals = new float[size];
to
int size = (int)pow( 2.f, (float)ensemble->get_params().max_depth) * 50; Ptr<float> leafVals = new float[size];
it worked again - valgrind reported no more illegal writes.
This is obviously a bad hack and should be fixed by someone who better knows how to calculate this value correctly.
3) valgrind reported another issue:
==4327== Mismatched free() / delete / delete [] ==4327== at 0x4C21A33: operator delete(void*) (vg_replace_malloc.c:346) ==4327== by 0x41A656: CvCascadeBoostTree::write(cv::FileStorage&, cv::Mat const&) (cvstd.hpp:392) ==4327== by 0x41AB4F: CvCascadeBoost::write(cv::FileStorage&, cv::Mat const&) const (boost.cpp:1697) ==4327== by 0x413D08: CvCascadeClassifier::train(std::string, std::string, std::string, int, int, int, int, int, CvCascadeParams const&, CvFeatureParams const&, CvCascadeBoostParams const&, bool) (cascadeclassifier.cpp:247) ==4327== by 0x40CA54: main (traincascade.cpp:109) ==4327== Address 0xa4dbbb0 is 0 bytes inside a block of size 400 alloc'd ==4327== at 0x4C225BA: operator new[](unsigned long) (vg_replace_malloc.c:264) ==4327== by 0x419A4C: CvCascadeBoostTree::write(cv::FileStorage&, cv::Mat const&) (boost.cpp:960) ==4327== by 0x41AB4F: CvCascadeBoost::write(cv::FileStorage&, cv::Mat const&) const (boost.cpp:1697) ==4327== by 0x413D08: CvCascadeClassifier::train(std::string, std::string, std::string, int, int, int, int, int, CvCascadeParams const&, CvFeatureParams const&, CvCascadeBoostParams const&, bool) (cascadeclassifier.cpp:247) ==4327== by 0x40CA54: main (traincascade.cpp:109) ==4327==
I did not further investigate it because the problem has been hack-fixed with fix 1) and 2), but that should be fixed aswell.
Hope that helps, seeing forward to a fix soon.
Associated revisions
updated debevec.csv to match pull request result #2991
Merge pull request #2991 from kovand11:calibrateDebevecFix
History
Updated by Shengyin Wu almost 12 years ago
i have try maxDepth parameter > 3, but the program run correctlly.
Updated by Anna Kogan almost 12 years ago
Hello Shengyin,
Thank you for the full description of the problem. If you find solution on your side, please send a pull request in our GitHub repo.
- Category set to objdetect
- Assignee set to Marina Kolpakova
Updated by Maksim Shabunin over 9 years ago
Issue has been transferred to GitHub: https://github.com/Itseez/opencv/issues/4557