Project

General

Profile

Statistics
| Branch: | Revision:

root / vision / cvblobs8.3 / BlobResult.cpp @ 53f28116

History | View | Annotate | Download (28.4 KB)

1 8711dd52 Nick Stanley
/************************************************************************
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
}