root / vision / cvblobs8.3 / BlobResult.cpp @ 53f28116
History | View | Annotate | Download (28.4 KB)
1 |
/************************************************************************
|
---|---|
2 |
BlobResult.cpp
|
3 |
|
4 |
FUNCIONALITAT: Implementaci? de la classe CBlobResult
|
5 |
AUTOR: Inspecta S.L.
|
6 |
MODIFICACIONS (Modificaci?, Autor, Data):
|
7 |
|
8 |
**************************************************************************/
|
9 |
|
10 |
#include <limits.h> |
11 |
#include <stdio.h> |
12 |
#include <functional> |
13 |
#include <algorithm> |
14 |
#include "BlobResult.h" |
15 |
|
16 |
//! Show errors functions: only works for windows releases
|
17 |
#ifdef _SHOW_ERRORS
|
18 |
#include <afx.h> //suport per a CStrings |
19 |
#include <afxwin.h> //suport per a AfxMessageBox |
20 |
#endif
|
21 |
|
22 |
/**************************************************************************
|
23 |
Constructors / Destructors
|
24 |
**************************************************************************/
|
25 |
|
26 |
|
27 |
/**
|
28 |
- FUNCI?: CBlobResult
|
29 |
- FUNCIONALITAT: Constructor estandard.
|
30 |
- PAR?METRES:
|
31 |
- RESULTAT:
|
32 |
- Crea un CBlobResult sense cap blob
|
33 |
- RESTRICCIONS:
|
34 |
- AUTOR: Ricard Borr?s
|
35 |
- DATA DE CREACI?: 20-07-2004.
|
36 |
- MODIFICACI?: Data. Autor. Descripci?.
|
37 |
*/
|
38 |
/**
|
39 |
- FUNCTION: CBlobResult
|
40 |
- FUNCTIONALITY: Standard constructor
|
41 |
- PARAMETERS:
|
42 |
- RESULT:
|
43 |
- creates an empty set of blobs
|
44 |
- RESTRICTIONS:
|
45 |
- AUTHOR: Ricard Borr?s
|
46 |
- CREATION DATE: 25-05-2005.
|
47 |
- MODIFICATION: Date. Author. Description.
|
48 |
*/
|
49 |
CBlobResult::CBlobResult() |
50 |
{ |
51 |
m_blobs = Blob_vector(); |
52 |
} |
53 |
|
54 |
/**
|
55 |
- FUNCI?: CBlobResult
|
56 |
- FUNCIONALITAT: Constructor a partir d'una imatge. Inicialitza la seq??ncia de blobs
|
57 |
amb els blobs resultants de l'an?lisi de blobs de la imatge.
|
58 |
- PAR?METRES:
|
59 |
- source: imatge d'on s'extreuran els blobs
|
60 |
- mask: m?scara a aplicar. Nom?s es calcularan els blobs on la m?scara sigui
|
61 |
diferent de 0. Els blobs que toquin a un pixel 0 de la m?scara seran
|
62 |
considerats exteriors.
|
63 |
- threshold: llindar que s'aplicar? a la imatge source abans de calcular els blobs
|
64 |
- findmoments: indica si s'han de calcular els moments de cada blob
|
65 |
- blackBlobs: true per buscar blobs negres a la binaritzazi? (it will join all extern white blobs).
|
66 |
false per buscar blobs negres a la binaritzazi? (it will join all extern black blobs).
|
67 |
|
68 |
- RESULTAT:
|
69 |
- objecte CBlobResult amb els blobs de la imatge source
|
70 |
- RESTRICCIONS:
|
71 |
- AUTOR: Ricard Borr?s
|
72 |
- DATA DE CREACI?: 25-05-2005.
|
73 |
- MODIFICACI?: Data. Autor. Descripci?.
|
74 |
*/
|
75 |
/**
|
76 |
- FUNCTION: CBlob
|
77 |
- FUNCTIONALITY: Constructor from an image. Fills an object with all the blobs in
|
78 |
the image
|
79 |
- PARAMETERS:
|
80 |
- source: image to extract the blobs from
|
81 |
- mask: optional mask to apply. The blobs will be extracted where the mask is
|
82 |
not 0. All the neighbouring blobs where the mask is 0 will be extern blobs
|
83 |
- threshold: threshold level to apply to the image before computing blobs
|
84 |
- findmoments: true to calculate the blob moments (slower) (needed to calculate elipses!)
|
85 |
- blackBlobs: true to search for black blobs in the binarization (it will join all extern white blobs).
|
86 |
false to search for white blobs in the binarization (it will join all extern black blobs).
|
87 |
- RESULT:
|
88 |
- object with all the blobs in the image. It throws an EXCEPCIO_CALCUL_BLOBS
|
89 |
if some error appears in the BlobAnalysis function
|
90 |
- RESTRICTIONS:
|
91 |
- AUTHOR: Ricard Borr?s
|
92 |
- CREATION DATE: 25-05-2005.
|
93 |
- MODIFICATION: Date. Author. Description.
|
94 |
*/
|
95 |
CBlobResult::CBlobResult(IplImage *source, IplImage *mask, uchar backgroundColor ) |
96 |
{ |
97 |
bool success;
|
98 |
|
99 |
try
|
100 |
{ |
101 |
success = ComponentLabeling( source, mask, backgroundColor, m_blobs ); |
102 |
} |
103 |
catch(...)
|
104 |
{ |
105 |
success = false;
|
106 |
} |
107 |
|
108 |
if( !success ) throw EXCEPCIO_CALCUL_BLOBS; |
109 |
} |
110 |
|
111 |
/**
|
112 |
- FUNCI?: CBlobResult
|
113 |
- FUNCIONALITAT: Constructor de c?pia. Inicialitza la seq??ncia de blobs
|
114 |
amb els blobs del par?metre.
|
115 |
- PAR?METRES:
|
116 |
- source: objecte que es copiar?
|
117 |
- RESULTAT:
|
118 |
- objecte CBlobResult amb els blobs de l'objecte source
|
119 |
- RESTRICCIONS:
|
120 |
- AUTOR: Ricard Borr?s
|
121 |
- DATA DE CREACI?: 25-05-2005.
|
122 |
- MODIFICACI?: Data. Autor. Descripci?.
|
123 |
*/
|
124 |
/**
|
125 |
- FUNCTION: CBlobResult
|
126 |
- FUNCTIONALITY: Copy constructor
|
127 |
- PARAMETERS:
|
128 |
- source: object to copy
|
129 |
- RESULT:
|
130 |
- RESTRICTIONS:
|
131 |
- AUTHOR: Ricard Borr?s
|
132 |
- CREATION DATE: 25-05-2005.
|
133 |
- MODIFICATION: Date. Author. Description.
|
134 |
*/
|
135 |
CBlobResult::CBlobResult( const CBlobResult &source )
|
136 |
{ |
137 |
m_blobs = Blob_vector( source.GetNumBlobs() ); |
138 |
|
139 |
// creem el nou a partir del passat com a par?metre
|
140 |
m_blobs = Blob_vector( source.GetNumBlobs() ); |
141 |
// copiem els blobs de l'origen a l'actual
|
142 |
Blob_vector::const_iterator pBlobsSrc = source.m_blobs.begin(); |
143 |
Blob_vector::iterator pBlobsDst = m_blobs.begin(); |
144 |
|
145 |
while( pBlobsSrc != source.m_blobs.end() )
|
146 |
{ |
147 |
// no podem cridar a l'operador = ja que Blob_vector ?s un
|
148 |
// vector de CBlob*. Per tant, creem un blob nou a partir del
|
149 |
// blob original
|
150 |
*pBlobsDst = new CBlob(**pBlobsSrc);
|
151 |
pBlobsSrc++; |
152 |
pBlobsDst++; |
153 |
} |
154 |
} |
155 |
|
156 |
|
157 |
|
158 |
/**
|
159 |
- FUNCI?: ~CBlobResult
|
160 |
- FUNCIONALITAT: Destructor estandard.
|
161 |
- PAR?METRES:
|
162 |
- RESULTAT:
|
163 |
- Allibera la mem?ria reservada de cadascun dels blobs de la classe
|
164 |
- RESTRICCIONS:
|
165 |
- AUTOR: Ricard Borr?s
|
166 |
- DATA DE CREACI?: 25-05-2005.
|
167 |
- MODIFICACI?: Data. Autor. Descripci?.
|
168 |
*/
|
169 |
/**
|
170 |
- FUNCTION: ~CBlobResult
|
171 |
- FUNCTIONALITY: Destructor
|
172 |
- PARAMETERS:
|
173 |
- RESULT:
|
174 |
- RESTRICTIONS:
|
175 |
- AUTHOR: Ricard Borr?s
|
176 |
- CREATION DATE: 25-05-2005.
|
177 |
- MODIFICATION: Date. Author. Description.
|
178 |
*/
|
179 |
CBlobResult::~CBlobResult() |
180 |
{ |
181 |
ClearBlobs(); |
182 |
} |
183 |
|
184 |
/**************************************************************************
|
185 |
Operadors / Operators
|
186 |
**************************************************************************/
|
187 |
|
188 |
|
189 |
/**
|
190 |
- FUNCI?: operador =
|
191 |
- FUNCIONALITAT: Assigna un objecte source a l'actual
|
192 |
- PAR?METRES:
|
193 |
- source: objecte a assignar
|
194 |
- RESULTAT:
|
195 |
- Substitueix els blobs actuals per els de l'objecte source
|
196 |
- RESTRICCIONS:
|
197 |
- AUTOR: Ricard Borr?s
|
198 |
- DATA DE CREACI?: 25-05-2005.
|
199 |
- MODIFICACI?: Data. Autor. Descripci?.
|
200 |
*/
|
201 |
/**
|
202 |
- FUNCTION: Assigment operator
|
203 |
- FUNCTIONALITY:
|
204 |
- PARAMETERS:
|
205 |
- RESULT:
|
206 |
- RESTRICTIONS:
|
207 |
- AUTHOR: Ricard Borr?s
|
208 |
- CREATION DATE: 25-05-2005.
|
209 |
- MODIFICATION: Date. Author. Description.
|
210 |
*/
|
211 |
CBlobResult& CBlobResult::operator=(const CBlobResult& source) |
212 |
{ |
213 |
// si ja s?n el mateix, no cal fer res
|
214 |
if (this != &source) |
215 |
{ |
216 |
// alliberem el conjunt de blobs antic
|
217 |
for( int i = 0; i < GetNumBlobs(); i++ ) |
218 |
{ |
219 |
delete m_blobs[i];
|
220 |
} |
221 |
m_blobs.clear(); |
222 |
// creem el nou a partir del passat com a par?metre
|
223 |
m_blobs = Blob_vector( source.GetNumBlobs() ); |
224 |
// copiem els blobs de l'origen a l'actual
|
225 |
Blob_vector::const_iterator pBlobsSrc = source.m_blobs.begin(); |
226 |
Blob_vector::iterator pBlobsDst = m_blobs.begin(); |
227 |
|
228 |
while( pBlobsSrc != source.m_blobs.end() )
|
229 |
{ |
230 |
// no podem cridar a l'operador = ja que Blob_vector ?s un
|
231 |
// vector de CBlob*. Per tant, creem un blob nou a partir del
|
232 |
// blob original
|
233 |
*pBlobsDst = new CBlob(**pBlobsSrc);
|
234 |
pBlobsSrc++; |
235 |
pBlobsDst++; |
236 |
} |
237 |
} |
238 |
return *this; |
239 |
} |
240 |
|
241 |
|
242 |
/**
|
243 |
- FUNCI?: operador +
|
244 |
- FUNCIONALITAT: Concatena els blobs de dos CBlobResult
|
245 |
- PAR?METRES:
|
246 |
- source: d'on s'agafaran els blobs afegits a l'actual
|
247 |
- RESULTAT:
|
248 |
- retorna un nou CBlobResult amb els dos CBlobResult concatenats
|
249 |
- RESTRICCIONS:
|
250 |
- AUTOR: Ricard Borr?s
|
251 |
- DATA DE CREACI?: 25-05-2005.
|
252 |
- NOTA: per la implementaci?, els blobs del par?metre es posen en ordre invers
|
253 |
- MODIFICACI?: Data. Autor. Descripci?.
|
254 |
*/
|
255 |
/**
|
256 |
- FUNCTION: + operator
|
257 |
- FUNCTIONALITY: Joins the blobs in source with the current ones
|
258 |
- PARAMETERS:
|
259 |
- source: object to copy the blobs
|
260 |
- RESULT:
|
261 |
- object with the actual blobs and the source blobs
|
262 |
- RESTRICTIONS:
|
263 |
- AUTHOR: Ricard Borr?s
|
264 |
- CREATION DATE: 25-05-2005.
|
265 |
- MODIFICATION: Date. Author. Description.
|
266 |
*/
|
267 |
CBlobResult CBlobResult::operator+( const CBlobResult& source ) const |
268 |
{ |
269 |
//creem el resultat a partir dels blobs actuals
|
270 |
CBlobResult resultat( *this );
|
271 |
|
272 |
// reservem mem?ria per als nous blobs
|
273 |
resultat.m_blobs.resize( resultat.GetNumBlobs() + source.GetNumBlobs() ); |
274 |
|
275 |
// declarem els iterador per rec?rrer els blobs d'origen i desti
|
276 |
Blob_vector::const_iterator pBlobsSrc = source.m_blobs.begin(); |
277 |
Blob_vector::iterator pBlobsDst = resultat.m_blobs.end(); |
278 |
|
279 |
// insertem els blobs de l'origen a l'actual
|
280 |
while( pBlobsSrc != source.m_blobs.end() )
|
281 |
{ |
282 |
pBlobsDst--; |
283 |
*pBlobsDst = new CBlob(**pBlobsSrc);
|
284 |
pBlobsSrc++; |
285 |
} |
286 |
|
287 |
return resultat;
|
288 |
} |
289 |
|
290 |
/**************************************************************************
|
291 |
Operacions / Operations
|
292 |
**************************************************************************/
|
293 |
|
294 |
/**
|
295 |
- FUNCI?: AddBlob
|
296 |
- FUNCIONALITAT: Afegeix un blob al conjunt
|
297 |
- PAR?METRES:
|
298 |
- blob: blob a afegir
|
299 |
- RESULTAT:
|
300 |
- modifica el conjunt de blobs actual
|
301 |
- RESTRICCIONS:
|
302 |
- AUTOR: Ricard Borr?s
|
303 |
- DATA DE CREACI?: 2006/03/01
|
304 |
- MODIFICACI?: Data. Autor. Descripci?.
|
305 |
*/
|
306 |
void CBlobResult::AddBlob( CBlob *blob )
|
307 |
{ |
308 |
if( blob != NULL ) |
309 |
m_blobs.push_back( new CBlob( blob ) );
|
310 |
} |
311 |
|
312 |
|
313 |
#ifdef MATRIXCV_ACTIU
|
314 |
|
315 |
/**
|
316 |
- FUNCI?: GetResult
|
317 |
- FUNCIONALITAT: Calcula el resultat especificat sobre tots els blobs de la classe
|
318 |
- PAR?METRES:
|
319 |
- evaluador: Qualsevol objecte derivat de COperadorBlob
|
320 |
- RESULTAT:
|
321 |
- Retorna un array de double's amb el resultat per cada blob
|
322 |
- RESTRICCIONS:
|
323 |
- AUTOR: Ricard Borr?s
|
324 |
- DATA DE CREACI?: 25-05-2005.
|
325 |
- MODIFICACI?: Data. Autor. Descripci?.
|
326 |
*/
|
327 |
/**
|
328 |
- FUNCTION: GetResult
|
329 |
- FUNCTIONALITY: Computes the function evaluador on all the blobs of the class
|
330 |
and returns a vector with the result
|
331 |
- PARAMETERS:
|
332 |
- evaluador: function to apply to each blob (any object derived from the
|
333 |
COperadorBlob class )
|
334 |
- RESULT:
|
335 |
- vector with all the results in the same order as the blobs
|
336 |
- RESTRICTIONS:
|
337 |
- AUTHOR: Ricard Borr?s
|
338 |
- CREATION DATE: 25-05-2005.
|
339 |
- MODIFICATION: Date. Author. Description.
|
340 |
*/
|
341 |
double_vector CBlobResult::GetResult( funcio_calculBlob *evaluador ) const
|
342 |
{ |
343 |
if( GetNumBlobs() <= 0 ) |
344 |
{ |
345 |
return double_vector();
|
346 |
} |
347 |
|
348 |
// definim el resultat
|
349 |
double_vector result = double_vector( GetNumBlobs() ); |
350 |
// i iteradors sobre els blobs i el resultat
|
351 |
double_vector::iterator itResult = result.GetIterator(); |
352 |
Blob_vector::const_iterator itBlobs = m_blobs.begin(); |
353 |
|
354 |
// avaluem la funci? en tots els blobs
|
355 |
while( itBlobs != m_blobs.end() )
|
356 |
{ |
357 |
*itResult = (*evaluador)(**itBlobs); |
358 |
itBlobs++; |
359 |
itResult++; |
360 |
} |
361 |
return result;
|
362 |
} |
363 |
#endif
|
364 |
|
365 |
/**
|
366 |
- FUNCI?: GetSTLResult
|
367 |
- FUNCIONALITAT: Calcula el resultat especificat sobre tots els blobs de la classe
|
368 |
- PAR?METRES:
|
369 |
- evaluador: Qualsevol objecte derivat de COperadorBlob
|
370 |
- RESULTAT:
|
371 |
- Retorna un array de double's STL amb el resultat per cada blob
|
372 |
- RESTRICCIONS:
|
373 |
- AUTOR: Ricard Borr?s
|
374 |
- DATA DE CREACI?: 25-05-2005.
|
375 |
- MODIFICACI?: Data. Autor. Descripci?.
|
376 |
*/
|
377 |
/**
|
378 |
- FUNCTION: GetResult
|
379 |
- FUNCTIONALITY: Computes the function evaluador on all the blobs of the class
|
380 |
and returns a vector with the result
|
381 |
- PARAMETERS:
|
382 |
- evaluador: function to apply to each blob (any object derived from the
|
383 |
COperadorBlob class )
|
384 |
- RESULT:
|
385 |
- vector with all the results in the same order as the blobs
|
386 |
- RESTRICTIONS:
|
387 |
- AUTHOR: Ricard Borr?s
|
388 |
- CREATION DATE: 25-05-2005.
|
389 |
- MODIFICATION: Date. Author. Description.
|
390 |
*/
|
391 |
double_stl_vector CBlobResult::GetSTLResult( funcio_calculBlob *evaluador ) const
|
392 |
{ |
393 |
if( GetNumBlobs() <= 0 ) |
394 |
{ |
395 |
return double_stl_vector();
|
396 |
} |
397 |
|
398 |
// definim el resultat
|
399 |
double_stl_vector result = double_stl_vector( GetNumBlobs() ); |
400 |
// i iteradors sobre els blobs i el resultat
|
401 |
double_stl_vector::iterator itResult = result.begin(); |
402 |
Blob_vector::const_iterator itBlobs = m_blobs.begin(); |
403 |
|
404 |
// avaluem la funci? en tots els blobs
|
405 |
while( itBlobs != m_blobs.end() )
|
406 |
{ |
407 |
*itResult = (*evaluador)(**itBlobs); |
408 |
itBlobs++; |
409 |
itResult++; |
410 |
} |
411 |
return result;
|
412 |
} |
413 |
|
414 |
/**
|
415 |
- FUNCI?: GetNumber
|
416 |
- FUNCIONALITAT: Calcula el resultat especificat sobre un ?nic blob de la classe
|
417 |
- PAR?METRES:
|
418 |
- evaluador: Qualsevol objecte derivat de COperadorBlob
|
419 |
- indexblob: n?mero de blob del que volem calcular el resultat.
|
420 |
- RESULTAT:
|
421 |
- Retorna un double amb el resultat
|
422 |
- RESTRICCIONS:
|
423 |
- AUTOR: Ricard Borr?s
|
424 |
- DATA DE CREACI?: 25-05-2005.
|
425 |
- MODIFICACI?: Data. Autor. Descripci?.
|
426 |
*/
|
427 |
/**
|
428 |
- FUNCTION: GetNumber
|
429 |
- FUNCTIONALITY: Computes the function evaluador on a blob of the class
|
430 |
- PARAMETERS:
|
431 |
- indexBlob: index of the blob to compute the function
|
432 |
- evaluador: function to apply to each blob (any object derived from the
|
433 |
COperadorBlob class )
|
434 |
- RESULT:
|
435 |
- RESTRICTIONS:
|
436 |
- AUTHOR: Ricard Borr?s
|
437 |
- CREATION DATE: 25-05-2005.
|
438 |
- MODIFICATION: Date. Author. Description.
|
439 |
*/
|
440 |
double CBlobResult::GetNumber( int indexBlob, funcio_calculBlob *evaluador ) const |
441 |
{ |
442 |
if( indexBlob < 0 || indexBlob >= GetNumBlobs() ) |
443 |
RaiseError( EXCEPTION_BLOB_OUT_OF_BOUNDS ); |
444 |
return (*evaluador)( *m_blobs[indexBlob] );
|
445 |
} |
446 |
|
447 |
/////////////////////////// FILTRAT DE BLOBS ////////////////////////////////////
|
448 |
|
449 |
/**
|
450 |
- FUNCI?: Filter
|
451 |
- FUNCIONALITAT: Filtra els blobs de la classe i deixa el resultat amb nom?s
|
452 |
els blobs que han passat el filtre.
|
453 |
El filtrat es basa en especificar condicions sobre un resultat dels blobs
|
454 |
i seleccionar (o excloure) aquells blobs que no compleixen una determinada
|
455 |
condicio
|
456 |
- PAR?METRES:
|
457 |
- dst: variable per deixar els blobs filtrats
|
458 |
- filterAction: acci? de filtrat. Incloure els blobs trobats (B_INCLUDE),
|
459 |
o excloure els blobs trobats (B_EXCLUDE)
|
460 |
- evaluador: Funci? per evaluar els blobs (qualsevol objecte derivat de COperadorBlob
|
461 |
- Condition: tipus de condici? que ha de superar la mesura (FilterType)
|
462 |
sobre cada blob per a ser considerat.
|
463 |
B_EQUAL,B_NOT_EQUAL,B_GREATER,B_LESS,B_GREATER_OR_EQUAL,
|
464 |
B_LESS_OR_EQUAL,B_INSIDE,B_OUTSIDE
|
465 |
- LowLimit: valor num?ric per a la comparaci? (Condition) de la mesura (FilterType)
|
466 |
- HighLimit: valor num?ric per a la comparaci? (Condition) de la mesura (FilterType)
|
467 |
(nom?s t? sentit per a aquelles condicions que tenen dos valors
|
468 |
(B_INSIDE, per exemple).
|
469 |
- RESULTAT:
|
470 |
- Deixa els blobs resultants del filtrat a destination
|
471 |
- RESTRICCIONS:
|
472 |
- AUTOR: Ricard Borr?s
|
473 |
- DATA DE CREACI?: 25-05-2005.
|
474 |
- MODIFICACI?: Data. Autor. Descripci?.
|
475 |
*/
|
476 |
/**
|
477 |
- FUNCTION: Filter
|
478 |
- FUNCTIONALITY: Get some blobs from the class based on conditions on measures
|
479 |
of the blobs.
|
480 |
- PARAMETERS:
|
481 |
- dst: where to store the selected blobs
|
482 |
- filterAction: B_INCLUDE: include the blobs which pass the filter in the result
|
483 |
B_EXCLUDE: exclude the blobs which pass the filter in the result
|
484 |
- evaluador: Object to evaluate the blob
|
485 |
- Condition: How to decide if the result returned by evaluador on each blob
|
486 |
is included or not. It can be:
|
487 |
B_EQUAL,B_NOT_EQUAL,B_GREATER,B_LESS,B_GREATER_OR_EQUAL,
|
488 |
B_LESS_OR_EQUAL,B_INSIDE,B_OUTSIDE
|
489 |
- LowLimit: numerical value to evaluate the Condition on evaluador(blob)
|
490 |
- HighLimit: numerical value to evaluate the Condition on evaluador(blob).
|
491 |
Only useful for B_INSIDE and B_OUTSIDE
|
492 |
- RESULT:
|
493 |
- It returns on dst the blobs that accomplish (B_INCLUDE) or discards (B_EXCLUDE)
|
494 |
the Condition on the result returned by evaluador on each blob
|
495 |
- RESTRICTIONS:
|
496 |
- AUTHOR: Ricard Borr?s
|
497 |
- CREATION DATE: 25-05-2005.
|
498 |
- MODIFICATION: Date. Author. Description.
|
499 |
*/
|
500 |
void CBlobResult::Filter(CBlobResult &dst,
|
501 |
int filterAction,
|
502 |
funcio_calculBlob *evaluador, |
503 |
int condition,
|
504 |
double lowLimit, double highLimit /*=0*/) const |
505 |
|
506 |
{ |
507 |
// do the job
|
508 |
DoFilter(dst, filterAction, evaluador, condition, lowLimit, highLimit ); |
509 |
} |
510 |
|
511 |
/**
|
512 |
- FUNCI?: Filter (const version)
|
513 |
- FUNCIONALITAT: Filtra els blobs de la classe i deixa el resultat amb nom?s
|
514 |
els blobs que han passat el filtre.
|
515 |
El filtrat es basa en especificar condicions sobre un resultat dels blobs
|
516 |
i seleccionar (o excloure) aquells blobs que no compleixen una determinada
|
517 |
condicio
|
518 |
- PAR?METRES:
|
519 |
- dst: variable per deixar els blobs filtrats
|
520 |
- filterAction: acci? de filtrat. Incloure els blobs trobats (B_INCLUDE),
|
521 |
o excloure els blobs trobats (B_EXCLUDE)
|
522 |
- evaluador: Funci? per evaluar els blobs (qualsevol objecte derivat de COperadorBlob
|
523 |
- Condition: tipus de condici? que ha de superar la mesura (FilterType)
|
524 |
sobre cada blob per a ser considerat.
|
525 |
B_EQUAL,B_NOT_EQUAL,B_GREATER,B_LESS,B_GREATER_OR_EQUAL,
|
526 |
B_LESS_OR_EQUAL,B_INSIDE,B_OUTSIDE
|
527 |
- LowLimit: valor num?ric per a la comparaci? (Condition) de la mesura (FilterType)
|
528 |
- HighLimit: valor num?ric per a la comparaci? (Condition) de la mesura (FilterType)
|
529 |
(nom?s t? sentit per a aquelles condicions que tenen dos valors
|
530 |
(B_INSIDE, per exemple).
|
531 |
- RESULTAT:
|
532 |
- Deixa els blobs resultants del filtrat a destination
|
533 |
- RESTRICCIONS:
|
534 |
- AUTOR: Ricard Borr?s
|
535 |
- DATA DE CREACI?: 25-05-2005.
|
536 |
- MODIFICACI?: Data. Autor. Descripci?.
|
537 |
*/
|
538 |
/**
|
539 |
- FUNCTION: Filter (const version)
|
540 |
- FUNCTIONALITY: Get some blobs from the class based on conditions on measures
|
541 |
of the blobs.
|
542 |
- PARAMETERS:
|
543 |
- dst: where to store the selected blobs
|
544 |
- filterAction: B_INCLUDE: include the blobs which pass the filter in the result
|
545 |
B_EXCLUDE: exclude the blobs which pass the filter in the result
|
546 |
- evaluador: Object to evaluate the blob
|
547 |
- Condition: How to decide if the result returned by evaluador on each blob
|
548 |
is included or not. It can be:
|
549 |
B_EQUAL,B_NOT_EQUAL,B_GREATER,B_LESS,B_GREATER_OR_EQUAL,
|
550 |
B_LESS_OR_EQUAL,B_INSIDE,B_OUTSIDE
|
551 |
- LowLimit: numerical value to evaluate the Condition on evaluador(blob)
|
552 |
- HighLimit: numerical value to evaluate the Condition on evaluador(blob).
|
553 |
Only useful for B_INSIDE and B_OUTSIDE
|
554 |
- RESULT:
|
555 |
- It returns on dst the blobs that accomplish (B_INCLUDE) or discards (B_EXCLUDE)
|
556 |
the Condition on the result returned by evaluador on each blob
|
557 |
- RESTRICTIONS:
|
558 |
- AUTHOR: Ricard Borr?s
|
559 |
- CREATION DATE: 25-05-2005.
|
560 |
- MODIFICATION: Date. Author. Description.
|
561 |
*/
|
562 |
void CBlobResult::Filter(CBlobResult &dst,
|
563 |
int filterAction,
|
564 |
funcio_calculBlob *evaluador, |
565 |
int condition,
|
566 |
double lowLimit, double highLimit /*=0*/) |
567 |
|
568 |
{ |
569 |
int numBlobs = GetNumBlobs();
|
570 |
|
571 |
// do the job
|
572 |
DoFilter(dst, filterAction, evaluador, condition, lowLimit, highLimit ); |
573 |
|
574 |
// inline operation: remove previous blobs
|
575 |
if( &dst == this ) |
576 |
{ |
577 |
// esborrem els primers blobs ( que s?n els originals )
|
578 |
// ja que els tindrem replicats al final si passen el filtre
|
579 |
Blob_vector::iterator itBlobs = m_blobs.begin(); |
580 |
for( int i = 0; i < numBlobs; i++ ) |
581 |
{ |
582 |
delete *itBlobs;
|
583 |
itBlobs++; |
584 |
} |
585 |
m_blobs.erase( m_blobs.begin(), itBlobs ); |
586 |
} |
587 |
} |
588 |
|
589 |
|
590 |
//! Does the Filter method job
|
591 |
void CBlobResult::DoFilter(CBlobResult &dst, int filterAction, funcio_calculBlob *evaluador, |
592 |
int condition, double lowLimit, double highLimit/* = 0*/) const |
593 |
{ |
594 |
int i, numBlobs;
|
595 |
bool resultavaluacio;
|
596 |
double_stl_vector avaluacioBlobs; |
597 |
double_stl_vector::iterator itavaluacioBlobs; |
598 |
|
599 |
if( GetNumBlobs() <= 0 ) return; |
600 |
if( !evaluador ) return; |
601 |
//avaluem els blobs amb la funci? pertinent
|
602 |
avaluacioBlobs = GetSTLResult(evaluador); |
603 |
itavaluacioBlobs = avaluacioBlobs.begin(); |
604 |
numBlobs = GetNumBlobs(); |
605 |
switch(condition)
|
606 |
{ |
607 |
case B_EQUAL:
|
608 |
for(i=0;i<numBlobs;i++, itavaluacioBlobs++) |
609 |
{ |
610 |
resultavaluacio= *itavaluacioBlobs == lowLimit; |
611 |
if( ( resultavaluacio && filterAction == B_INCLUDE ) ||
|
612 |
( !resultavaluacio && filterAction == B_EXCLUDE )) |
613 |
{ |
614 |
dst.m_blobs.push_back( new CBlob( GetBlob( i ) ));
|
615 |
} |
616 |
} |
617 |
break;
|
618 |
case B_NOT_EQUAL:
|
619 |
for(i=0;i<numBlobs;i++, itavaluacioBlobs++) |
620 |
{ |
621 |
resultavaluacio = *itavaluacioBlobs != lowLimit; |
622 |
if( ( resultavaluacio && filterAction == B_INCLUDE ) ||
|
623 |
( !resultavaluacio && filterAction == B_EXCLUDE )) |
624 |
{ |
625 |
dst.m_blobs.push_back( new CBlob( GetBlob( i ) ));
|
626 |
} |
627 |
} |
628 |
break;
|
629 |
case B_GREATER:
|
630 |
for(i=0;i<numBlobs;i++, itavaluacioBlobs++) |
631 |
{ |
632 |
resultavaluacio= *itavaluacioBlobs > lowLimit; |
633 |
if( ( resultavaluacio && filterAction == B_INCLUDE ) ||
|
634 |
( !resultavaluacio && filterAction == B_EXCLUDE )) |
635 |
{ |
636 |
dst.m_blobs.push_back( new CBlob( GetBlob( i ) ));
|
637 |
} |
638 |
} |
639 |
break;
|
640 |
case B_LESS:
|
641 |
for(i=0;i<numBlobs;i++, itavaluacioBlobs++) |
642 |
{ |
643 |
resultavaluacio= *itavaluacioBlobs < lowLimit; |
644 |
if( ( resultavaluacio && filterAction == B_INCLUDE ) ||
|
645 |
( !resultavaluacio && filterAction == B_EXCLUDE )) |
646 |
{ |
647 |
dst.m_blobs.push_back( new CBlob( GetBlob( i ) ));
|
648 |
} |
649 |
} |
650 |
break;
|
651 |
case B_GREATER_OR_EQUAL:
|
652 |
for(i=0;i<numBlobs;i++, itavaluacioBlobs++) |
653 |
{ |
654 |
resultavaluacio= *itavaluacioBlobs>= lowLimit; |
655 |
if( ( resultavaluacio && filterAction == B_INCLUDE ) ||
|
656 |
( !resultavaluacio && filterAction == B_EXCLUDE )) |
657 |
{ |
658 |
dst.m_blobs.push_back( new CBlob( GetBlob( i ) ));
|
659 |
} |
660 |
} |
661 |
break;
|
662 |
case B_LESS_OR_EQUAL:
|
663 |
for(i=0;i<numBlobs;i++, itavaluacioBlobs++) |
664 |
{ |
665 |
resultavaluacio= *itavaluacioBlobs <= lowLimit; |
666 |
if( ( resultavaluacio && filterAction == B_INCLUDE ) ||
|
667 |
( !resultavaluacio && filterAction == B_EXCLUDE )) |
668 |
{ |
669 |
dst.m_blobs.push_back( new CBlob( GetBlob( i ) ));
|
670 |
} |
671 |
} |
672 |
break;
|
673 |
case B_INSIDE:
|
674 |
for(i=0;i<numBlobs;i++, itavaluacioBlobs++) |
675 |
{ |
676 |
resultavaluacio=( *itavaluacioBlobs >= lowLimit) && ( *itavaluacioBlobs <= highLimit); |
677 |
if( ( resultavaluacio && filterAction == B_INCLUDE ) ||
|
678 |
( !resultavaluacio && filterAction == B_EXCLUDE )) |
679 |
{ |
680 |
dst.m_blobs.push_back( new CBlob( GetBlob( i ) ));
|
681 |
} |
682 |
} |
683 |
break;
|
684 |
case B_OUTSIDE:
|
685 |
for(i=0;i<numBlobs;i++, itavaluacioBlobs++) |
686 |
{ |
687 |
resultavaluacio=( *itavaluacioBlobs < lowLimit) || ( *itavaluacioBlobs > highLimit); |
688 |
if( ( resultavaluacio && filterAction == B_INCLUDE ) ||
|
689 |
( !resultavaluacio && filterAction == B_EXCLUDE )) |
690 |
{ |
691 |
dst.m_blobs.push_back( new CBlob( GetBlob( i ) ));
|
692 |
} |
693 |
} |
694 |
break;
|
695 |
} |
696 |
} |
697 |
/**
|
698 |
- FUNCI?: GetBlob
|
699 |
- FUNCIONALITAT: Retorna un blob si aquest existeix (index != -1)
|
700 |
- PAR?METRES:
|
701 |
- indexblob: index del blob a retornar
|
702 |
- RESULTAT:
|
703 |
- RESTRICCIONS:
|
704 |
- AUTOR: Ricard Borr?s
|
705 |
- DATA DE CREACI?: 25-05-2005.
|
706 |
- MODIFICACI?: Data. Autor. Descripci?.
|
707 |
*/
|
708 |
/*
|
709 |
- FUNCTION: GetBlob
|
710 |
- FUNCTIONALITY: Gets the n-th blob (without ordering the blobs)
|
711 |
- PARAMETERS:
|
712 |
- indexblob: index in the blob array
|
713 |
- RESULT:
|
714 |
- RESTRICTIONS:
|
715 |
- AUTHOR: Ricard Borr?s
|
716 |
- CREATION DATE: 25-05-2005.
|
717 |
- MODIFICATION: Date. Author. Description.
|
718 |
*/
|
719 |
CBlob CBlobResult::GetBlob(int indexblob) const |
720 |
{ |
721 |
if( indexblob < 0 || indexblob >= GetNumBlobs() ) |
722 |
RaiseError( EXCEPTION_BLOB_OUT_OF_BOUNDS ); |
723 |
|
724 |
return *m_blobs[indexblob];
|
725 |
} |
726 |
CBlob *CBlobResult::GetBlob(int indexblob)
|
727 |
{ |
728 |
if( indexblob < 0 || indexblob >= GetNumBlobs() ) |
729 |
RaiseError( EXCEPTION_BLOB_OUT_OF_BOUNDS ); |
730 |
|
731 |
return m_blobs[indexblob];
|
732 |
} |
733 |
|
734 |
/**
|
735 |
- FUNCI?: GetNthBlob
|
736 |
- FUNCIONALITAT: Retorna l'en?ssim blob segons un determinat criteri
|
737 |
- PAR?METRES:
|
738 |
- criteri: criteri per ordenar els blobs (objectes derivats de COperadorBlob)
|
739 |
- nBlob: index del blob a retornar
|
740 |
- dst: on es retorna el resultat
|
741 |
- RESULTAT:
|
742 |
- retorna el blob nBlob a dst ordenant els blobs de la classe segons el criteri
|
743 |
en ordre DESCENDENT. Per exemple, per obtenir el blob major:
|
744 |
GetNthBlob( CBlobGetArea(), 0, blobMajor );
|
745 |
GetNthBlob( CBlobGetArea(), 1, blobMajor ); (segon blob m?s gran)
|
746 |
- RESTRICCIONS:
|
747 |
- AUTOR: Ricard Borr?s
|
748 |
- DATA DE CREACI?: 25-05-2005.
|
749 |
- MODIFICACI?: Data. Autor. Descripci?.
|
750 |
*/
|
751 |
/*
|
752 |
- FUNCTION: GetNthBlob
|
753 |
- FUNCTIONALITY: Gets the n-th blob ordering first the blobs with some criteria
|
754 |
- PARAMETERS:
|
755 |
- criteri: criteria to order the blob array
|
756 |
- nBlob: index of the returned blob in the ordered blob array
|
757 |
- dst: where to store the result
|
758 |
- RESULT:
|
759 |
- RESTRICTIONS:
|
760 |
- AUTHOR: Ricard Borr?s
|
761 |
- CREATION DATE: 25-05-2005.
|
762 |
- MODIFICATION: Date. Author. Description.
|
763 |
*/
|
764 |
void CBlobResult::GetNthBlob( funcio_calculBlob *criteri, int nBlob, CBlob &dst ) const |
765 |
{ |
766 |
// verifiquem que no estem accedint fora el vector de blobs
|
767 |
if( nBlob < 0 || nBlob >= GetNumBlobs() ) |
768 |
{ |
769 |
//RaiseError( EXCEPTION_BLOB_OUT_OF_BOUNDS );
|
770 |
dst = CBlob(); |
771 |
return;
|
772 |
} |
773 |
|
774 |
double_stl_vector avaluacioBlobs, avaluacioBlobsOrdenat; |
775 |
double valorEnessim;
|
776 |
|
777 |
//avaluem els blobs amb la funci? pertinent
|
778 |
avaluacioBlobs = GetSTLResult(criteri); |
779 |
|
780 |
avaluacioBlobsOrdenat = double_stl_vector( GetNumBlobs() ); |
781 |
|
782 |
// obtenim els nBlob primers resultats (en ordre descendent)
|
783 |
std::partial_sort_copy( avaluacioBlobs.begin(), |
784 |
avaluacioBlobs.end(), |
785 |
avaluacioBlobsOrdenat.begin(), |
786 |
avaluacioBlobsOrdenat.end(), |
787 |
std::greater<double>() );
|
788 |
|
789 |
valorEnessim = avaluacioBlobsOrdenat[nBlob]; |
790 |
|
791 |
// busquem el primer blob que t? el valor n-ssim
|
792 |
double_stl_vector::const_iterator itAvaluacio = avaluacioBlobs.begin(); |
793 |
|
794 |
bool trobatBlob = false; |
795 |
int indexBlob = 0; |
796 |
while( itAvaluacio != avaluacioBlobs.end() && !trobatBlob )
|
797 |
{ |
798 |
if( *itAvaluacio == valorEnessim )
|
799 |
{ |
800 |
trobatBlob = true;
|
801 |
dst = CBlob( GetBlob(indexBlob)); |
802 |
} |
803 |
itAvaluacio++; |
804 |
indexBlob++; |
805 |
} |
806 |
} |
807 |
|
808 |
/**
|
809 |
- FUNCI?: ClearBlobs
|
810 |
- FUNCIONALITAT: Elimina tots els blobs de l'objecte
|
811 |
- PAR?METRES:
|
812 |
- RESULTAT:
|
813 |
- Allibera tota la mem?ria dels blobs
|
814 |
- RESTRICCIONS:
|
815 |
- AUTOR: Ricard Borr?s Navarra
|
816 |
- DATA DE CREACI?: 25-05-2005.
|
817 |
- MODIFICACI?: Data. Autor. Descripci?.
|
818 |
*/
|
819 |
/*
|
820 |
- FUNCTION: ClearBlobs
|
821 |
- FUNCTIONALITY: Clears all the blobs from the object and releases all its memory
|
822 |
- PARAMETERS:
|
823 |
- RESULT:
|
824 |
- RESTRICTIONS:
|
825 |
- AUTHOR: Ricard Borr?s
|
826 |
- CREATION DATE: 25-05-2005.
|
827 |
- MODIFICATION: Date. Author. Description.
|
828 |
*/
|
829 |
void CBlobResult::ClearBlobs()
|
830 |
{ |
831 |
Blob_vector::iterator itBlobs = m_blobs.begin(); |
832 |
while( itBlobs != m_blobs.end() )
|
833 |
{ |
834 |
delete *itBlobs;
|
835 |
itBlobs++; |
836 |
} |
837 |
|
838 |
m_blobs.clear(); |
839 |
} |
840 |
|
841 |
/**
|
842 |
- FUNCI?: RaiseError
|
843 |
- FUNCIONALITAT: Funci? per a notificar errors al l'usuari (en debug) i llen?a
|
844 |
les excepcions
|
845 |
- PAR?METRES:
|
846 |
- errorCode: codi d'error
|
847 |
- RESULTAT:
|
848 |
- Ensenya un missatge a l'usuari (en debug) i llen?a una excepci?
|
849 |
- RESTRICCIONS:
|
850 |
- AUTOR: Ricard Borr?s Navarra
|
851 |
- DATA DE CREACI?: 25-05-2005.
|
852 |
- MODIFICACI?: Data. Autor. Descripci?.
|
853 |
*/
|
854 |
/*
|
855 |
- FUNCTION: RaiseError
|
856 |
- FUNCTIONALITY: Error handling function
|
857 |
- PARAMETERS:
|
858 |
- errorCode: reason of the error
|
859 |
- RESULT:
|
860 |
- in _SHOW_ERRORS version, shows a message box with the error. In release is silent.
|
861 |
In both cases throws an exception with the error.
|
862 |
- RESTRICTIONS:
|
863 |
- AUTHOR: Ricard Borr?s
|
864 |
- CREATION DATE: 25-05-2005.
|
865 |
- MODIFICATION: Date. Author. Description.
|
866 |
*/
|
867 |
void CBlobResult::RaiseError(const int errorCode) const |
868 |
{ |
869 |
//! Do we need to show errors?
|
870 |
#ifdef _SHOW_ERRORS
|
871 |
CString msg, format = "Error en CBlobResult: %s";
|
872 |
|
873 |
switch (errorCode)
|
874 |
{ |
875 |
case EXCEPTION_BLOB_OUT_OF_BOUNDS:
|
876 |
msg.Format(format, "Intentant accedir a un blob no existent");
|
877 |
break;
|
878 |
default:
|
879 |
msg.Format(format, "Codi d'error desconegut");
|
880 |
break;
|
881 |
} |
882 |
|
883 |
AfxMessageBox(msg); |
884 |
|
885 |
#endif
|
886 |
throw errorCode;
|
887 |
} |
888 |
|
889 |
|
890 |
|
891 |
/**************************************************************************
|
892 |
Auxiliars / Auxiliary functions
|
893 |
**************************************************************************/
|
894 |
|
895 |
|
896 |
/**
|
897 |
- FUNCI?: PrintBlobs
|
898 |
- FUNCIONALITAT: Escriu els par?metres (?rea, per?metre, exterior, mitjana)
|
899 |
de tots els blobs a un fitxer.
|
900 |
- PAR?METRES:
|
901 |
- nom_fitxer: path complet del fitxer amb el resultat
|
902 |
- RESULTAT:
|
903 |
- RESTRICCIONS:
|
904 |
- AUTOR: Ricard Borr?s
|
905 |
- DATA DE CREACI?: 25-05-2005.
|
906 |
- MODIFICACI?: Data. Autor. Descripci?.
|
907 |
*/
|
908 |
/*
|
909 |
- FUNCTION: PrintBlobs
|
910 |
- FUNCTIONALITY: Prints some blob features in an ASCII file
|
911 |
- PARAMETERS:
|
912 |
- nom_fitxer: full path + filename to generate
|
913 |
- RESULT:
|
914 |
- RESTRICTIONS:
|
915 |
- AUTHOR: Ricard Borr?s
|
916 |
- CREATION DATE: 25-05-2005.
|
917 |
- MODIFICATION: Date. Author. Description.
|
918 |
*/
|
919 |
void CBlobResult::PrintBlobs( char *nom_fitxer ) const |
920 |
{ |
921 |
double_stl_vector area, /*perimetre,*/ exterior, compacitat, longitud,
|
922 |
externPerimeter, perimetreConvex, perimetre; |
923 |
int i;
|
924 |
FILE *fitxer_sortida; |
925 |
|
926 |
area = GetSTLResult( CBlobGetArea()); |
927 |
perimetre = GetSTLResult( CBlobGetPerimeter()); |
928 |
exterior = GetSTLResult( CBlobGetExterior()); |
929 |
compacitat = GetSTLResult(CBlobGetCompactness()); |
930 |
longitud = GetSTLResult( CBlobGetLength()); |
931 |
externPerimeter = GetSTLResult( CBlobGetExternPerimeter()); |
932 |
perimetreConvex = GetSTLResult( CBlobGetHullPerimeter()); |
933 |
|
934 |
fitxer_sortida = fopen( nom_fitxer, "w" );
|
935 |
|
936 |
for(i=0; i<GetNumBlobs(); i++) |
937 |
{ |
938 |
fprintf( fitxer_sortida, "blob %d ->\t a=%7.0f\t p=%8.2f (%8.2f extern)\t pconvex=%8.2f\t ext=%.0f\t m=%7.2f\t c=%3.2f\t l=%8.2f\n",
|
939 |
i, area[i], perimetre[i], externPerimeter[i], perimetreConvex[i], exterior[i], compacitat[i], longitud[i] ); |
940 |
} |
941 |
fclose( fitxer_sortida ); |
942 |
|
943 |
} |