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