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 // Intel License Agreement
11 // For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000, Intel Corporation, 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 #include "_cvaux.h"
43
44 #ifdef WIN32 /* make sure it builds under Linux whenever it is included into Makefile.am or not. */
45
46 //void icvCutContour( CvSeq* current, IplImage* image );
47 CvSeq* icvCutContourRaster( CvSeq* current, CvMemStorage* storage, IplImage* image );
48
49
50 //create lists of segments of all contours from image
cvExtractSingleEdges(IplImage * image,CvMemStorage * storage)51 CvSeq* cvExtractSingleEdges( IplImage* image, //bw image - it's content will be destroyed by cvFindContours
52 CvMemStorage* storage )
53 {
54 CvMemStorage* tmp_storage = cvCreateChildMemStorage( storage );
55 CvSeq* contours = 0;
56 cvFindContours( image, tmp_storage, &contours, sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_NONE );
57 cvZero( image );
58
59 //iterate through contours
60 //iterate through tree
61 CvSeq* current = contours;
62 int number = 0;
63 int level = 1;
64
65 CvSeq* output = 0;
66 CvSeq* tail_seq = 0;
67
68 //actually this loop can iterates through tree,
69 //but still we use CV_RETR_LIST it is not useful
70 while( current )
71 {
72 number++;
73
74 //get vertical list of segments for one contour
75 CvSeq* new_seq = icvCutContourRaster( current, storage, image );
76
77 //add this vertical list to horisontal list
78 if( new_seq )
79 {
80 if( tail_seq )
81 {
82 tail_seq->h_next = new_seq;
83 new_seq->h_prev = tail_seq;
84 tail_seq = new_seq;
85 }
86 else
87 {
88 output = tail_seq = new_seq;
89 }
90 }
91
92 //iteration through tree
93 if( current->v_next )
94 {
95 //goto child
96 current = current->v_next;
97 level++;
98 }
99 else
100 {
101 //go parent
102 while( !current->h_next )
103 {
104 current = current->v_prev;
105 level--;
106 if( !level ) break;
107 }
108
109 if( current ) //go brother
110 current = current->h_next;
111 }
112 }
113
114 //free temporary memstorage with initial contours
115 cvReleaseMemStorage( &tmp_storage );
116
117 return output;
118 }
119
120 //makes vertical list of segments for 1 contour
icvCutContourRaster(CvSeq * current,CvMemStorage * storage,IplImage * image)121 CvSeq* icvCutContourRaster( CvSeq* current, CvMemStorage* storage, IplImage* image /*tmp image*/)
122 {
123 //iplSet(image, 0 ); // this can cause double edges if two contours have common edge
124 // for example if object is circle with 1 pixel width
125 // to remove such problem - remove this iplSet
126
127 //approx contour by single edges
128 CvSeqReader reader;
129 CvSeqWriter writer;
130
131 int writing = 0;
132 cvStartReadSeq( current, &reader, 0 );
133 //below line just to avoid warning
134 cvStartWriteSeq( current->flags, sizeof(CvContour), sizeof(CvPoint), storage, &writer );
135
136 CvSeq* output = 0;
137 CvSeq* tail = 0;
138
139 //first pass through contour - compute number of branches at every point
140 int i;
141 for( i = 0; i < current->total; i++ )
142 {
143 CvPoint cur;
144
145 CV_READ_SEQ_ELEM( cur, reader );
146
147 //mark point
148 ((uchar*)image->imageData)[image->widthStep * cur.y + cur.x]++;
149 assert( ((uchar*)image->imageData)[image->widthStep * cur.y + cur.x] != 255 );
150
151 }
152
153 //second pass - create separate edges
154 for( i = 0; i < current->total; i++ )
155 {
156 CvPoint cur;
157
158 CV_READ_SEQ_ELEM( cur, reader );
159
160 //get pixel at this point
161 uchar flag = image->imageData[image->widthStep * cur.y + cur.x];
162 if( flag != 255 && flag < 3) //
163 {
164 if(!writing)
165 {
166 cvStartWriteSeq( current->flags, sizeof(CvContour), sizeof(CvPoint), storage, &writer );
167 writing = 1 ;
168 }
169
170 //mark point
171 if( flag < 3 ) ((uchar*)image->imageData)[image->widthStep * cur.y + cur.x] = 255;
172 //add it to another seq
173 CV_WRITE_SEQ_ELEM( cur, writer );
174
175 }
176 else
177 {
178 //exclude this point from contour
179 if( writing )
180 {
181 CvSeq* newseq = cvEndWriteSeq( &writer );
182 writing = 0;
183
184 if( tail )
185 {
186 tail->v_next = newseq;
187 newseq->v_prev = tail;
188 tail = newseq;
189 }
190 else
191 {
192 output = tail = newseq;
193 }
194 }
195 }
196 }
197
198
199 if( writing ) //if were not self intersections
200 {
201 CvSeq* newseq = cvEndWriteSeq( &writer );
202 writing = 0;
203
204 if( tail )
205 {
206 tail->v_next = newseq;
207 newseq->v_prev = tail;
208 tail = newseq;
209 }
210 else
211 {
212 output = tail = newseq;
213 }
214 }
215
216
217 return output;
218
219 }
220
221
222 /*void icvCutContour( CvSeq* current, IplImage* image )
223 {
224 //approx contour by single edges
225 CvSeqReader reader;
226 CvSeqReader rev_reader;
227
228 cvStartReadSeq( current, &reader, 0 );
229
230 int64* cur_pt = (int64*)reader.ptr;
231 int64* prev_pt = (int64*)reader.prev_elem;
232
233 //search for point a in aba position
234 for( int i = 0; i < current->total; i++ )
235 {
236 CV_NEXT_SEQ_ELEM( sizeof(int64), reader );
237
238 //compare current reader pos element with old previous
239 if( prev_pt[0] == ((int64*)reader.ptr)[0] )
240 {
241 //return to prev pos
242 CV_PREV_SEQ_ELEM( sizeof(int64), reader );
243
244
245 //this point is end of edge
246 //start going both directions and collect edge
247 cvStartReadSeq( current, &rev_reader, 1 );
248
249 int pos = cvGetSeqReaderPos( &reader );
250 cvSetSeqReaderPos( &rev_reader, pos );
251
252 //walk in both directions
253 while(1);
254
255
256 }
257 int64* cur_pt = (int64*)reader.ptr;
258 int64* prev_pt = (int64*)reader.prev_elem;
259
260 }
261 }
262
263 */
264 #endif /* WIN32 */
265
266
267
268
269