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 );
47CvSeq* icvCutContourRaster( CvSeq* current, CvMemStorage* storage, IplImage* image );
48
49
50//create lists of segments of all contours from image
51CvSeq* 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
121CvSeq* 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