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 |
} |