Repository: opencv
Issue: opencv_traincascade crashing with maxDepth > 3
Labels: bug,auto-transferred,priority: normal,affected: 2.4,category: objdetect

Transferred from http://code.opencv.org/issues/2991

```
|| Arvid Terzibaschian on 2013-04-26 14:52
|| Priority: Normal
|| Affected: 2.4.5 (latest release)
|| Category: objdetect
|| Tracker: Bug
|| Difficulty: None
|| PR: 
|| Platform: None / None
```
## opencv_traincascade crashing with maxDepth > 3

```
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) 
<pre>
==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==
</pre>

This is just a minor issue caused by split_criteria not being initialized properly. I fixed it by
<pre>
CvBoostParams::CvBoostParams()
{
    split_criteria = CvBoost::DEFAULT;
    boost_type = CvBoost::REAL;
    weak_count = 100;
    weight_trim_rate = 0.95;
    cv_folds = 0;
    max_depth = 1;
}
</pre>

2) valgrind furthermore reported several invalid writes during tree-export all looking like this:
<pre>
==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)
</pre>

This is caused by a wrong calculation of the number of to be expected tree nodes in function
<pre>
void CvCascadeBoostTree::write( FileStorage &fs, const Mat& featureMap )
</pre>

When I changed
<pre>
int size = (int)pow( 2.f, (float)ensemble->get_params().max_depth);
Ptr<float> leafVals = new float[size];
</pre>
to
<pre>
int size = (int)pow( 2.f, (float)ensemble->get_params().max_depth) * 50;
Ptr<float> leafVals = new float[size];
</pre>
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:

<pre>
==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==
</pre>

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.
```
## History
##### Shengyin Wu on 2013-04-30 02:04

```
i have try maxDepth parameter > 3, but the program run correctlly.
```
##### Anna Kogan on 2013-05-07 08:29

```
Hello Shengyin,
Thank you for the full description of the problem. If you find solution on your side, please send a "pull request":http://www.code.opencv.org/projects/opencv/wiki/How_to_contribute in our GitHub repo.
-   Assignee set to Marina Kolpakova
-   Category set to objdetect
```