1793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/*M///////////////////////////////////////////////////////////////////////////////////////
2793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//
3793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//
5793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//  By downloading, copying, installing or using the software you agree to this license.
6793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//  If you do not agree to this license, do not download, install,
7793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//  copy or use the software.
8793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//
9793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//
10793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//                           License Agreement
11793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//                For Open Source Computer Vision Library
12793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//
13793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// Copyright (C) 2013, Itseez Inc, all rights reserved.
14793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// Third party copyrights are property of their respective owners.
15793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//
16793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// Redistribution and use in source and binary forms, with or without modification,
17793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// are permitted provided that the following conditions are met:
18793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//
19793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//   * Redistribution's of source code must retain the above copyright notice,
20793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//     this list of conditions and the following disclaimer.
21793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//
22793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//   * Redistribution's in binary form must reproduce the above copyright notice,
23793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//     this list of conditions and the following disclaimer in the documentation
24793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//     and/or other materials provided with the distribution.
25793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//
26793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//   * The name of Intel Corporation may not be used to endorse or promote products
27793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//     derived from this software without specific prior written permission.
28793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//
29793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// This software is provided by the copyright holders and contributors "as is" and
30793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// any express or implied warranties, including, but not limited to, the implied
31793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// warranties of merchantability and fitness for a particular purpose are disclaimed.
32793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// In no event shall the Intel Corporation or contributors be liable for any direct,
33793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// indirect, incidental, special, exemplary, or consequential damages
34793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// (including, but not limited to, procurement of substitute goods or services;
35793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// loss of use, data, or profits; or business interruption) however caused
36793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// and on any theory of liability, whether in contract, strict liability,
37793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// or tort (including negligence or otherwise) arising in any way out of
38793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// the use of this software, even if advised of the possibility of such damage.
39793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//
40793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//M*/
41793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
42793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* Haar features calculation */
43793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
44793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include "precomp.hpp"
45793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include <stdio.h>
46793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
47793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslernamespace cv
48793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
49793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
50793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* field names */
51793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
52793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define ICV_HAAR_SIZE_NAME            "size"
53793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define ICV_HAAR_STAGES_NAME          "stages"
54793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define ICV_HAAR_TREES_NAME           "trees"
55793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define ICV_HAAR_FEATURE_NAME         "feature"
56793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define ICV_HAAR_RECTS_NAME           "rects"
57793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define ICV_HAAR_TILTED_NAME          "tilted"
58793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define ICV_HAAR_THRESHOLD_NAME       "threshold"
59793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define ICV_HAAR_LEFT_NODE_NAME       "left_node"
60793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define ICV_HAAR_LEFT_VAL_NAME        "left_val"
61793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define ICV_HAAR_RIGHT_NODE_NAME      "right_node"
62793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define ICV_HAAR_RIGHT_VAL_NAME       "right_val"
63793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define ICV_HAAR_STAGE_THRESHOLD_NAME "stage_threshold"
64793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define ICV_HAAR_PARENT_NAME          "parent"
65793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define ICV_HAAR_NEXT_NAME            "next"
66793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
67793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslernamespace haar_cvt
68793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
69793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
70793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstruct HaarFeature
71793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
72793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    enum { RECT_NUM = 3 };
73793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
74793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    HaarFeature()
75793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
76793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        tilted = false;
77793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        for( int i = 0; i < RECT_NUM; i++ )
78793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
79793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            rect[i].r = Rect(0,0,0,0);
80793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            rect[i].weight = 0.f;
81793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
82793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
83793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    bool tilted;
84793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    struct
85793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
86793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        Rect r;
87793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        float weight;
88793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    } rect[RECT_NUM];
89793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler};
90793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
91793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstruct HaarClassifierNode
92793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
93793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    HaarClassifierNode()
94793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
95793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        f = left = right = 0;
96793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        threshold = 0.f;
97793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
98793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int f, left, right;
99793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    float threshold;
100793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler};
101793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
102793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstruct HaarClassifier
103793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
104793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    std::vector<HaarClassifierNode> nodes;
105793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    std::vector<float> leaves;
106793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler};
107793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
108793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstruct HaarStageClassifier
109793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
110793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    double threshold;
111793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    std::vector<HaarClassifier> weaks;
112793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler};
113793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
114793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic bool convert(const String& oldcascade, const String& newcascade)
115793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
116793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    FileStorage oldfs(oldcascade, FileStorage::READ);
117793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if( !oldfs.isOpened() )
118793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return false;
119793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    FileNode oldroot = oldfs.getFirstTopLevelNode();
120793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
121793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    FileNode sznode = oldroot[ICV_HAAR_SIZE_NAME];
122793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if( sznode.empty() )
123793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return false;
124793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Size cascadesize;
125793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    cascadesize.width = (int)sznode[0];
126793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    cascadesize.height = (int)sznode[1];
127793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    std::vector<HaarFeature> features;
128793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
129793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int i, j, k, n;
130793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
131793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    FileNode stages_seq = oldroot[ICV_HAAR_STAGES_NAME];
132793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int nstages = (int)stages_seq.size();
133793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    std::vector<HaarStageClassifier> stages(nstages);
134793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
135793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    for( i = 0; i < nstages; i++ )
136793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
137793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        FileNode stagenode = stages_seq[i];
138793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        HaarStageClassifier& stage = stages[i];
139793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        stage.threshold = (double)stagenode[ICV_HAAR_STAGE_THRESHOLD_NAME];
140793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        FileNode weaks_seq = stagenode[ICV_HAAR_TREES_NAME];
141793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        int nweaks = (int)weaks_seq.size();
142793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        stage.weaks.resize(nweaks);
143793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
144793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        for( j = 0; j < nweaks; j++ )
145793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
146793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            HaarClassifier& weak = stage.weaks[j];
147793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            FileNode weaknode = weaks_seq[j];
148793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            int nnodes = (int)weaknode.size();
149793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
150793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            for( n = 0; n < nnodes; n++ )
151793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            {
152793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                FileNode nnode = weaknode[n];
153793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                FileNode fnode = nnode[ICV_HAAR_FEATURE_NAME];
154793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                HaarFeature f;
155793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                HaarClassifierNode node;
156793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                node.f = (int)features.size();
157793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                f.tilted = (int)fnode[ICV_HAAR_TILTED_NAME] != 0;
158793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                FileNode rects_seq = fnode[ICV_HAAR_RECTS_NAME];
159793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                int nrects = (int)rects_seq.size();
160793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
161793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                for( k = 0; k < nrects; k++ )
162793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                {
163793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    FileNode rnode = rects_seq[k];
164793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    f.rect[k].r.x = (int)rnode[0];
165793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    f.rect[k].r.y = (int)rnode[1];
166793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    f.rect[k].r.width = (int)rnode[2];
167793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    f.rect[k].r.height = (int)rnode[3];
168793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    f.rect[k].weight = (float)rnode[4];
169793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                }
170793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                features.push_back(f);
171793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                node.threshold = nnode[ICV_HAAR_THRESHOLD_NAME];
172793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                FileNode leftValNode = nnode[ICV_HAAR_LEFT_VAL_NAME];
173793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                if( !leftValNode.empty() )
174793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                {
175793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    node.left = -(int)weak.leaves.size();
176793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    weak.leaves.push_back((float)leftValNode);
177793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                }
178793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                else
179793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                {
180793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    node.left = (int)nnode[ICV_HAAR_LEFT_NODE_NAME];
181793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                }
182793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                FileNode rightValNode = nnode[ICV_HAAR_RIGHT_VAL_NAME];
183793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                if( !rightValNode.empty() )
184793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                {
185793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    node.right = -(int)weak.leaves.size();
186793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    weak.leaves.push_back((float)rightValNode);
187793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                }
188793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                else
189793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                {
190793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    node.right = (int)nnode[ICV_HAAR_RIGHT_NODE_NAME];
191793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                }
192793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                weak.nodes.push_back(node);
193793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
194793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
195793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
196793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
197793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    FileStorage newfs(newcascade, FileStorage::WRITE);
198793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if( !newfs.isOpened() )
199793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return false;
200793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
201793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int maxWeakCount = 0, nfeatures = (int)features.size();
202793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    for( i = 0; i < nstages; i++ )
203793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        maxWeakCount = std::max(maxWeakCount, (int)stages[i].weaks.size());
204793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
205793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    newfs << "cascade" << "{:opencv-cascade-classifier"
206793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    << "stageType" << "BOOST"
207793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    << "featureType" << "HAAR"
208793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    << "height" << cascadesize.width
209793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    << "width" << cascadesize.height
210793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    << "stageParams" << "{"
211793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        << "maxWeakCount" << (int)maxWeakCount
212793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    << "}"
213793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    << "featureParams" << "{"
214793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        << "maxCatCount" << 0
215793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    << "}"
216793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    << "stageNum" << (int)nstages
217793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    << "stages" << "[";
218793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
219793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    for( i = 0; i < nstages; i++ )
220793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
221793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        int nweaks = (int)stages[i].weaks.size();
222793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        newfs << "{" << "maxWeakCount" << (int)nweaks
223793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            << "stageThreshold" << stages[i].threshold
224793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            << "weakClassifiers" << "[";
225793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        for( j = 0; j < nweaks; j++ )
226793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
227793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            const HaarClassifier& c = stages[i].weaks[j];
228793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            newfs << "{" << "internalNodes" << "[";
229793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            int nnodes = (int)c.nodes.size(), nleaves = (int)c.leaves.size();
230793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            for( k = 0; k < nnodes; k++ )
231793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                newfs << c.nodes[k].left << c.nodes[k].right
232793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    << c.nodes[k].f << c.nodes[k].threshold;
233793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            newfs << "]" << "leafValues" << "[";
234793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            for( k = 0; k < nleaves; k++ )
235793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                newfs << c.leaves[k];
236793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            newfs << "]" << "}";
237793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
238793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        newfs << "]" << "}";
239793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
240793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
241793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    newfs << "]"
242793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        << "features" << "[";
243793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
244793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    for( i = 0; i < nfeatures; i++ )
245793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
246793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        const HaarFeature& f = features[i];
247793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        newfs << "{" << "rects" << "[";
248793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        for( j = 0; j < HaarFeature::RECT_NUM; j++ )
249793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
250793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            if( j >= 2 && fabs(f.rect[j].weight) < FLT_EPSILON )
251793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                break;
252793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            newfs << "[" << f.rect[j].r.x << f.rect[j].r.y <<
253793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                f.rect[j].r.width << f.rect[j].r.height << f.rect[j].weight << "]";
254793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
255793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        newfs << "]";
256793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if( f.tilted )
257793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            newfs << "tilted" << 1;
258793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        newfs << "}";
259793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
260793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
261793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    newfs << "]" << "}";
262793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return true;
263793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
264793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
265793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
266793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
267793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerbool CascadeClassifier::convert(const String& oldcascade, const String& newcascade)
268793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
269793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    bool ok = haar_cvt::convert(oldcascade, newcascade);
270793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if( !ok && newcascade.size() > 0 )
271793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        remove(newcascade.c_str());
272793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return ok;
273793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
274793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
275793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
276