Project

General

Profile

Statistics
| Branch: | Revision:

root / vision / cvblobs8.3 / BlobContour.cpp @ b11b2b30

History | View | Annotate | Download (5.47 KB)

1
#include "BlobContour.h"
2
#include "cxcore.h"
3

    
4
CBlobContour::CBlobContour()
5
{
6
        m_startPoint.x = 0;
7
        m_startPoint.y = 0;
8
        m_area = -1;
9
        m_perimeter = -1;
10
        m_contourPoints = NULL;
11
        m_moments.m00 = -1;
12
        m_contour = NULL;
13
        m_parentStorage = NULL;
14
}
15
CBlobContour::CBlobContour(CvPoint startPoint, CvMemStorage *storage )
16
{
17
        m_startPoint.x = startPoint.x;
18
        m_startPoint.y = startPoint.y;
19
        m_area = -1;
20
        m_perimeter = -1;
21
        m_moments.m00 = -1;
22

    
23
        m_parentStorage = storage;
24

    
25
        m_contourPoints = NULL;
26

    
27
        // contour sequence: must be compatible with opencv functions
28
        m_contour = cvCreateSeq( CV_SEQ_ELTYPE_CODE | CV_SEQ_KIND_CURVE | CV_SEQ_FLAG_CLOSED,
29
                                              sizeof(CvContour),
30
                                              sizeof(t_chainCode),m_parentStorage);
31

    
32
}
33

    
34

    
35
//! Copy constructor
36
CBlobContour::CBlobContour( CBlobContour *source )
37
{
38
        if (source != NULL )
39
        {
40
                *this = *source;
41
        }
42
}
43

    
44
CBlobContour::~CBlobContour()
45
{
46
        // let parent blob deallocate all contour and contour point memory
47
        m_contour = NULL;
48
        m_contourPoints = NULL;
49
}
50

    
51

    
52
//! Copy operator
53
CBlobContour& CBlobContour::operator=( const CBlobContour &source )
54
{
55
        if( this != &source )
56
        {                
57
                m_startPoint = source.m_startPoint;
58

    
59
                m_parentStorage = source.m_parentStorage;
60
                
61
                if (m_contour)
62
                {
63
                        cvClearSeq( m_contour );
64
                }
65

    
66
                if (source.m_contour)
67
                {
68
                        m_contour =        cvCloneSeq( source.m_contour, m_parentStorage);
69
                }
70
                
71
                if( source.m_contourPoints )
72
                {
73
                        if( m_contourPoints )
74
                                cvClearSeq( m_contourPoints );
75
                        m_contourPoints = cvCloneSeq( source.m_contourPoints, m_parentStorage);
76
                }
77

    
78
                m_area = source.m_area;
79
                m_perimeter = source.m_area;
80
                m_moments = source.m_moments;
81
        }
82
        return *this;
83
}
84

    
85

    
86
/**
87
- FUNCI?: AddChainCode
88
- FUNCIONALITAT: Add chain code to contour
89
- PAR?METRES:
90
        - 
91
- RESULTAT:
92
        - 
93
- RESTRICCIONS:
94
        - 
95
- AUTOR: rborras
96
- DATA DE CREACI?: 2008/05/06
97
- MODIFICACI?: Data. Autor. Descripci?.
98
*/
99
void CBlobContour::AddChainCode(t_chainCode chaincode)
100
{
101
        cvSeqPush(m_contour, &chaincode);
102
}
103

    
104
//! Clears chain code contour and points
105
void CBlobContour::ResetChainCode()
106
{
107
        if( m_contour )
108
        {
109
                cvClearSeq( m_contour );
110
                m_contour = NULL;
111
        }
112
        if( m_contourPoints )
113
        {
114
                cvClearSeq( m_contourPoints );
115
                m_contourPoints = NULL;
116
        }
117
}
118

    
119
/**
120
- FUNCI?: GetPerimeter
121
- FUNCIONALITAT: Get perimeter from chain code. Diagonals sum sqrt(2) and horizontal and vertical codes 1
122
- PAR?METRES:
123
        - 
124
- RESULTAT:
125
        - 
126
- RESTRICCIONS:
127
        - 
128
- AUTOR: rborras
129
- DATA DE CREACI?: 2008/04/30
130
- MODIFICACI?: Data. Autor. Descripci?.
131
- NOTA: Algorithm derived from "Methods to estimate area and perimeters of blob-like objects: A comparison", L.Yang
132
*/
133
double CBlobContour::GetPerimeter()
134
{
135
        // is calculated?
136
        if (m_perimeter != -1)
137
        {
138
                return m_perimeter;
139
        }
140

    
141
        if( IsEmpty() )
142
                return 0;
143

    
144
        m_perimeter = cvContourPerimeter( GetContourPoints() );
145

    
146
        return m_perimeter;
147
}
148

    
149
/**
150
- FUNCI?: GetArea
151
- FUNCIONALITAT: Computes area from chain code
152
- PAR?METRES:
153
        - 
154
- RESULTAT:
155
        - May give negative areas for clock wise contours
156
- RESTRICCIONS:
157
        - 
158
- AUTOR: rborras
159
- DATA DE CREACI?: 2008/04/30
160
- MODIFICACI?: Data. Autor. Descripci?.
161
- NOTA: Algorithm derived from "Properties of contour codes", G.R. Wilson
162
*/
163
double CBlobContour::GetArea()
164
{
165
        // is calculated?
166
        if (m_area != -1)
167
        {
168
                return m_area;
169
        }
170

    
171
        if( IsEmpty() )
172
                return 0;
173

    
174
        m_area = fabs( cvContourArea( GetContourPoints() ));
175
        
176
        return m_area;
177
}
178

    
179
//! Get contour moment (p,q up to MAX_CALCULATED_MOMENTS)
180
double CBlobContour::GetMoment(int p, int q)
181
{
182
        // is a valid moment?
183
        if ( p < 0 || q < 0 || p > MAX_MOMENTS_ORDER || q > MAX_MOMENTS_ORDER )
184
        {
185
                return -1;
186
        }
187

    
188
        if( IsEmpty() )
189
                return 0;
190

    
191
        // it is calculated?
192
        if( m_moments.m00 == -1)
193
        {
194
                cvMoments( GetContourPoints(), &m_moments );
195
        }
196
                
197
        return cvGetSpatialMoment( &m_moments, p, q );
198

    
199
        
200
}
201

    
202
//! Calculate contour points from crack codes
203
t_PointList CBlobContour::GetContourPoints()
204
{
205
        // it is calculated?
206
        if( m_contourPoints != NULL )
207
                return m_contourPoints;
208

    
209
        if ( m_contour == NULL || m_contour->total <= 0 )
210
        {
211
                return NULL;
212
        }
213

    
214
        CvSeq *tmpPoints;
215
        CvSeqReader reader;
216
        CvSeqWriter writer;
217
        CvPoint actualPoint;
218
        CvRect boundingBox;
219

    
220
        // if aproximation is different than simple extern perimeter will not work
221
        tmpPoints = cvApproxChains( m_contour, m_parentStorage, CV_CHAIN_APPROX_NONE);
222

    
223

    
224
        // apply an offset to contour points to recover real coordinates
225
        
226
        cvStartReadSeq( tmpPoints, &reader);
227

    
228
        m_contourPoints = cvCreateSeq( tmpPoints->flags, tmpPoints->header_size, tmpPoints->elem_size, m_parentStorage );
229
        cvStartAppendToSeq(m_contourPoints, &writer );
230

    
231
        // also calculate bounding box of the contour to allow cvPointPolygonTest
232
        // work correctly on the generated polygon
233
        boundingBox.x = boundingBox.y = 10000;
234
        boundingBox.width = boundingBox.height = 0;
235
        
236
        for( int i=0; i< tmpPoints->total; i++)
237
        {
238
                CV_READ_SEQ_ELEM( actualPoint, reader);
239

    
240
                actualPoint.x += m_startPoint.x;
241
                actualPoint.y += m_startPoint.y;
242

    
243
                boundingBox.x = MIN( boundingBox.x, actualPoint.x );
244
                boundingBox.y = MIN( boundingBox.y, actualPoint.y );
245
                boundingBox.width = MAX( boundingBox.width, actualPoint.x );
246
                boundingBox.height = MAX( boundingBox.height, actualPoint.y );
247
                
248
                CV_WRITE_SEQ_ELEM( actualPoint, writer );
249
        }
250
        cvEndWriteSeq( &writer );
251
        cvClearSeq( tmpPoints );
252

    
253
        // assign calculated bounding box
254
        ((CvContour*)m_contourPoints)->rect = boundingBox;
255

    
256

    
257
        return m_contourPoints;
258
}