Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/objdetect/src/cascadedetect_convert.cpp
16337 views
1
/*M///////////////////////////////////////////////////////////////////////////////////////
2
//
3
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4
//
5
// By downloading, copying, installing or using the software you agree to this license.
6
// If you do not agree to this license, do not download, install,
7
// copy or use the software.
8
//
9
//
10
// License Agreement
11
// For Open Source Computer Vision Library
12
//
13
// Copyright (C) 2013, Itseez Inc, all rights reserved.
14
// Third party copyrights are property of their respective owners.
15
//
16
// Redistribution and use in source and binary forms, with or without modification,
17
// are permitted provided that the following conditions are met:
18
//
19
// * Redistribution's of source code must retain the above copyright notice,
20
// this list of conditions and the following disclaimer.
21
//
22
// * Redistribution's in binary form must reproduce the above copyright notice,
23
// this list of conditions and the following disclaimer in the documentation
24
// and/or other materials provided with the distribution.
25
//
26
// * The name of Intel Corporation may not be used to endorse or promote products
27
// derived from this software without specific prior written permission.
28
//
29
// This software is provided by the copyright holders and contributors "as is" and
30
// any express or implied warranties, including, but not limited to, the implied
31
// warranties of merchantability and fitness for a particular purpose are disclaimed.
32
// In no event shall the Intel Corporation or contributors be liable for any direct,
33
// indirect, incidental, special, exemplary, or consequential damages
34
// (including, but not limited to, procurement of substitute goods or services;
35
// loss of use, data, or profits; or business interruption) however caused
36
// and on any theory of liability, whether in contract, strict liability,
37
// or tort (including negligence or otherwise) arising in any way out of
38
// the use of this software, even if advised of the possibility of such damage.
39
//
40
//M*/
41
42
/* Haar features calculation */
43
44
#include "precomp.hpp"
45
#include <stdio.h>
46
47
namespace cv
48
{
49
50
/* field names */
51
52
#define ICV_HAAR_SIZE_NAME "size"
53
#define ICV_HAAR_STAGES_NAME "stages"
54
#define ICV_HAAR_TREES_NAME "trees"
55
#define ICV_HAAR_FEATURE_NAME "feature"
56
#define ICV_HAAR_RECTS_NAME "rects"
57
#define ICV_HAAR_TILTED_NAME "tilted"
58
#define ICV_HAAR_THRESHOLD_NAME "threshold"
59
#define ICV_HAAR_LEFT_NODE_NAME "left_node"
60
#define ICV_HAAR_LEFT_VAL_NAME "left_val"
61
#define ICV_HAAR_RIGHT_NODE_NAME "right_node"
62
#define ICV_HAAR_RIGHT_VAL_NAME "right_val"
63
#define ICV_HAAR_STAGE_THRESHOLD_NAME "stage_threshold"
64
#define ICV_HAAR_PARENT_NAME "parent"
65
#define ICV_HAAR_NEXT_NAME "next"
66
67
namespace haar_cvt
68
{
69
70
struct HaarFeature
71
{
72
enum { RECT_NUM = 3 };
73
74
HaarFeature()
75
{
76
tilted = false;
77
for( int i = 0; i < RECT_NUM; i++ )
78
{
79
rect[i].r = Rect(0,0,0,0);
80
rect[i].weight = 0.f;
81
}
82
}
83
bool tilted;
84
struct
85
{
86
Rect r;
87
float weight;
88
} rect[RECT_NUM];
89
};
90
91
struct HaarClassifierNode
92
{
93
HaarClassifierNode()
94
{
95
f = left = right = 0;
96
threshold = 0.f;
97
}
98
int f, left, right;
99
float threshold;
100
};
101
102
struct HaarClassifier
103
{
104
std::vector<HaarClassifierNode> nodes;
105
std::vector<float> leaves;
106
};
107
108
struct HaarStageClassifier
109
{
110
double threshold;
111
std::vector<HaarClassifier> weaks;
112
};
113
114
static bool convert(const String& oldcascade, const String& newcascade)
115
{
116
FileStorage oldfs(oldcascade, FileStorage::READ);
117
if( !oldfs.isOpened() )
118
return false;
119
FileNode oldroot = oldfs.getFirstTopLevelNode();
120
121
FileNode sznode = oldroot[ICV_HAAR_SIZE_NAME];
122
if( sznode.empty() )
123
return false;
124
Size cascadesize;
125
cascadesize.width = (int)sznode[0];
126
cascadesize.height = (int)sznode[1];
127
std::vector<HaarFeature> features;
128
129
int i, j, k, n;
130
131
FileNode stages_seq = oldroot[ICV_HAAR_STAGES_NAME];
132
int nstages = (int)stages_seq.size();
133
std::vector<HaarStageClassifier> stages(nstages);
134
135
for( i = 0; i < nstages; i++ )
136
{
137
FileNode stagenode = stages_seq[i];
138
HaarStageClassifier& stage = stages[i];
139
stage.threshold = (double)stagenode[ICV_HAAR_STAGE_THRESHOLD_NAME];
140
FileNode weaks_seq = stagenode[ICV_HAAR_TREES_NAME];
141
int nweaks = (int)weaks_seq.size();
142
stage.weaks.resize(nweaks);
143
144
for( j = 0; j < nweaks; j++ )
145
{
146
HaarClassifier& weak = stage.weaks[j];
147
FileNode weaknode = weaks_seq[j];
148
int nnodes = (int)weaknode.size();
149
150
for( n = 0; n < nnodes; n++ )
151
{
152
FileNode nnode = weaknode[n];
153
FileNode fnode = nnode[ICV_HAAR_FEATURE_NAME];
154
HaarFeature f;
155
HaarClassifierNode node;
156
node.f = (int)features.size();
157
f.tilted = (int)fnode[ICV_HAAR_TILTED_NAME] != 0;
158
FileNode rects_seq = fnode[ICV_HAAR_RECTS_NAME];
159
int nrects = (int)rects_seq.size();
160
161
for( k = 0; k < nrects; k++ )
162
{
163
FileNode rnode = rects_seq[k];
164
f.rect[k].r.x = (int)rnode[0];
165
f.rect[k].r.y = (int)rnode[1];
166
f.rect[k].r.width = (int)rnode[2];
167
f.rect[k].r.height = (int)rnode[3];
168
f.rect[k].weight = (float)rnode[4];
169
}
170
features.push_back(f);
171
node.threshold = nnode[ICV_HAAR_THRESHOLD_NAME];
172
FileNode leftValNode = nnode[ICV_HAAR_LEFT_VAL_NAME];
173
if( !leftValNode.empty() )
174
{
175
node.left = -(int)weak.leaves.size();
176
weak.leaves.push_back((float)leftValNode);
177
}
178
else
179
{
180
node.left = (int)nnode[ICV_HAAR_LEFT_NODE_NAME];
181
}
182
FileNode rightValNode = nnode[ICV_HAAR_RIGHT_VAL_NAME];
183
if( !rightValNode.empty() )
184
{
185
node.right = -(int)weak.leaves.size();
186
weak.leaves.push_back((float)rightValNode);
187
}
188
else
189
{
190
node.right = (int)nnode[ICV_HAAR_RIGHT_NODE_NAME];
191
}
192
weak.nodes.push_back(node);
193
}
194
}
195
}
196
197
FileStorage newfs(newcascade, FileStorage::WRITE);
198
if( !newfs.isOpened() )
199
return false;
200
201
int maxWeakCount = 0, nfeatures = (int)features.size();
202
for( i = 0; i < nstages; i++ )
203
maxWeakCount = std::max(maxWeakCount, (int)stages[i].weaks.size());
204
205
newfs << "cascade" << "{:opencv-cascade-classifier"
206
<< "stageType" << "BOOST"
207
<< "featureType" << "HAAR"
208
<< "height" << cascadesize.width
209
<< "width" << cascadesize.height
210
<< "stageParams" << "{"
211
<< "maxWeakCount" << (int)maxWeakCount
212
<< "}"
213
<< "featureParams" << "{"
214
<< "maxCatCount" << 0
215
<< "}"
216
<< "stageNum" << (int)nstages
217
<< "stages" << "[";
218
219
for( i = 0; i < nstages; i++ )
220
{
221
int nweaks = (int)stages[i].weaks.size();
222
newfs << "{" << "maxWeakCount" << (int)nweaks
223
<< "stageThreshold" << stages[i].threshold
224
<< "weakClassifiers" << "[";
225
for( j = 0; j < nweaks; j++ )
226
{
227
const HaarClassifier& c = stages[i].weaks[j];
228
newfs << "{" << "internalNodes" << "[";
229
int nnodes = (int)c.nodes.size(), nleaves = (int)c.leaves.size();
230
for( k = 0; k < nnodes; k++ )
231
newfs << c.nodes[k].left << c.nodes[k].right
232
<< c.nodes[k].f << c.nodes[k].threshold;
233
newfs << "]" << "leafValues" << "[";
234
for( k = 0; k < nleaves; k++ )
235
newfs << c.leaves[k];
236
newfs << "]" << "}";
237
}
238
newfs << "]" << "}";
239
}
240
241
newfs << "]"
242
<< "features" << "[";
243
244
for( i = 0; i < nfeatures; i++ )
245
{
246
const HaarFeature& f = features[i];
247
newfs << "{" << "rects" << "[";
248
for( j = 0; j < HaarFeature::RECT_NUM; j++ )
249
{
250
if( j >= 2 && fabs(f.rect[j].weight) < FLT_EPSILON )
251
break;
252
newfs << "[" << f.rect[j].r.x << f.rect[j].r.y <<
253
f.rect[j].r.width << f.rect[j].r.height << f.rect[j].weight << "]";
254
}
255
newfs << "]";
256
if( f.tilted )
257
newfs << "tilted" << 1;
258
newfs << "}";
259
}
260
261
newfs << "]" << "}";
262
return true;
263
}
264
265
}
266
267
bool CascadeClassifier::convert(const String& oldcascade, const String& newcascade)
268
{
269
bool ok = haar_cvt::convert(oldcascade, newcascade);
270
if( !ok && newcascade.size() > 0 )
271
remove(newcascade.c_str());
272
return ok;
273
}
274
275
}
276
277