0001-connectedComponents-warning-free-version.patch

Jason Newton, 2012-08-27 03:15 pm

Download (17.4 kB)

 
b/modules/imgproc/include/opencv2/imgproc/imgproc.hpp
1055 1055
CV_EXPORTS_W void matchTemplate( InputArray image, InputArray templ,
1056 1056
                                 OutputArray result, int method );
1057 1057

  
1058
//! computes the connected components labeled image of boolean image I with 4 or 8 way connectivity - returns N, the total
1059
//number of labels [0, N-1] where 0 represents the background label.
1060
CV_EXPORTS_W uint64_t connectedComponents(Mat &L, const Mat &I, int connectivity = 8);
1061

  
1062

  
1058 1063
//! mode of the contour retrieval algorithm
1059 1064
enum
1060 1065
{
b/modules/imgproc/src/connectedcomponents.cpp
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
// 2011 Jason Newton <[email protected]>
41
//M*/
42
//
43
#include "precomp.hpp"
44

  
45
namespace cv{
46
    namespace connectedcomponents{
47
    using std::vector;
48

  
49
    //Find the root of the tree of node i
50
    template<typename LabelT>
51
    inline static
52
    LabelT findRoot(const vector<LabelT> &P, LabelT i){
53
        LabelT root = i;
54
        while(P[root] < root){
55
            root = P[root];
56
        }
57
        return root;
58
    }
59

  
60
    //Make all nodes in the path of node i point to root
61
    template<typename LabelT>
62
    inline static
63
    void setRoot(vector<LabelT> &P, LabelT i, LabelT root){
64
        while(P[i] < i){
65
            LabelT j = P[i];
66
            P[i] = root;
67
            i = j;
68
        }
69
        P[i] = root;
70
    }
71

  
72
    //Find the root of the tree of the node i and compress the path in the process
73
    template<typename LabelT>
74
    inline static
75
    LabelT find(vector<LabelT> &P, LabelT i){
76
        LabelT root = findRoot(P, i);
77
        setRoot(P, i, root);
78
        return root;
79
    }
80

  
81
    //unite the two trees containing nodes i and j and return the new root
82
    template<typename LabelT>
83
    inline static
84
    LabelT set_union(vector<LabelT> &P, LabelT i, LabelT j){
85
        LabelT root = findRoot(P, i);
86
        if(i != j){
87
            LabelT rootj = findRoot(P, j);
88
            if(root > rootj){
89
                root = rootj;
90
            }
91
            setRoot(P, j, root);
92
        }
93
        setRoot(P, i, root);
94
        return root;
95
    }
96

  
97
    //Flatten the Union Find tree and relabel the components
98
    template<typename LabelT>
99
    inline static
100
    LabelT flattenL(vector<LabelT> &P){
101
        LabelT k = 1;
102
        for(size_t i = 1; i < P.size(); ++i){
103
            if(P[i] < i){
104
                P[i] = P[P[i]];
105
            }else{
106
                P[i] = k; k = k + 1;
107
            }
108
        }
109
        return k;
110
    }
111

  
112
    ////Flatten the Union Find tree - inconsistent labels
113
    //void flatten(int P[], int size){
114
    //    for(int i = 1; i < size; ++i){
115
    //        P[i] = P[P[i]];
116
    //    }
117
    //}
118
    const int G4[2][2] = {{-1, 0}, {0, -1}};//b, d neighborhoods
119
    const int G8[4][2] = {{-1, -1}, {-1, 0}, {-1, 1}, {0, -1}};//a, b, c, d neighborhoods
120
    //Based on "Two Strategies to Speed up Connected Components Algorithms", the SAUF (Scan array union find) variant
121
    //using decision trees
122
    //Kesheng Wu, et al
123
    template<typename LabelT, typename PixelT, int connectivity = 8>
124
    struct LabelingImpl{
125
    LabelT operator()(Mat &L, const Mat &I){
126
        const int rows = L.rows;
127
        const int cols = L.cols;
128
        size_t nPixels = size_t(rows) * cols;
129
        vector<LabelT> P; P.push_back(0);
130
        LabelT l = 1;
131
        //scanning phase
132
        for(int r_i = 0; r_i < rows; ++r_i){
133
            for(int c_i = 0; c_i < cols; ++c_i){
134
                if(!I.at<PixelT>(r_i, c_i)){
135
                    L.at<LabelT>(r_i, c_i) = 0;
136
                    continue;
137
                }
138
                if(connectivity == 8){
139
                    const int a = 0;
140
                    const int b = 1;
141
                    const int c = 2;
142
                    const int d = 3;
143

  
144
                    bool T[4];
145

  
146
                    for(size_t i = 0; i < 4; ++i){
147
                        int gr = r_i + G8[i][0];
148
                        int gc = c_i + G8[i][1];
149
                        T[i] = false;
150
                        if(gr >= 0 && gr < rows && gc >= 0 && gc < cols){
151
                            if(I.at<PixelT>(gr, gc)){
152
                                T[i] = true;
153
                            }
154
                        }
155
                    }
156

  
157
                    //decision tree
158
                    if(T[b]){
159
                        //copy(b)
160
                        L.at<LabelT>(r_i, c_i) = L.at<LabelT>(r_i + G8[b][0], c_i + G8[b][1]);
161
                    }else{//not b
162
                        if(T[c]){
163
                            if(T[a]){
164
                                //copy(c, a)
165
                                L.at<LabelT>(r_i, c_i) = set_union(P, L.at<LabelT>(r_i + G8[c][0], c_i + G8[c][1]), L.at<LabelT>(r_i + G8[a][0], c_i + G8[a][1]));
166
                            }else{
167
                                if(T[d]){
168
                                    //copy(c, d)
169
                                    L.at<LabelT>(r_i, c_i) = set_union(P, L.at<LabelT>(r_i + G8[c][0], c_i + G8[c][1]), L.at<LabelT>(r_i + G8[d][0], c_i + G8[d][1]));
170
                                }else{
171
                                    //copy(c)
172
                                    L.at<LabelT>(r_i, c_i) = L.at<LabelT>(r_i + G8[c][0], c_i + G8[c][1]);
173
                                }
174
                            }
175
                        }else{//not c
176
                            if(T[a]){
177
                                //copy(a)
178
                                L.at<LabelT>(r_i, c_i) = L.at<LabelT>(r_i + G8[a][0], c_i + G8[a][1]);
179
                            }else{
180
                                if(T[d]){
181
                                    //copy(d)
182
                                    L.at<LabelT>(r_i, c_i) = L.at<LabelT>(r_i + G8[d][0], c_i + G8[d][1]);
183
                                }else{
184
                                    //new label
185
                                    L.at<LabelT>(r_i, c_i) = l;
186
                                    P.push_back(l);//P[l] = l;
187
                                    l = l + 1;
188
                                }
189
                            }
190
                        }
191
                    }
192
                }else{
193
                    //B & D only
194
                    const int b = 0;
195
                    const int d = 1;
196
                    assert(connectivity == 4);
197
                    bool T[2];
198
                    for(size_t i = 0; i < 2; ++i){
199
                        int gr = r_i + G4[i][0];
200
                        int gc = c_i + G4[i][1];
201
                        T[i] = false;
202
                        if(gr >= 0 && gr < rows && gc >= 0 && gc < cols){
203
                            if(I.at<PixelT>(gr, gc)){
204
                                T[i] = true;
205
                            }
206
                        }
207
                    }
208

  
209
                    if(T[b]){
210
                        if(T[d]){
211
                            //copy(d, b)
212
                            L.at<LabelT>(r_i, c_i) = set_union(P, L.at<LabelT>(r_i + G4[d][0], c_i + G4[d][1]), L.at<LabelT>(r_i + G4[b][0], c_i + G4[b][1]));
213
                        }else{
214
                            //copy(b)
215
                            L.at<LabelT>(r_i, c_i) = L.at<LabelT>(r_i + G4[b][0], c_i + G4[b][1]);
216
                        }
217
                    }else{
218
                        if(T[d]){
219
                            //copy(d)
220
                            L.at<LabelT>(r_i, c_i) = L.at<LabelT>(r_i + G4[d][0], c_i + G4[d][1]);
221
                        }else{
222
                            //new label
223
                            L.at<LabelT>(r_i, c_i) = l;
224
                            P.push_back(l);//P[l] = l;
225
                            l = l + 1;
226
                        }
227
                    }
228

  
229
                }
230
            }
231
        }
232

  
233
        //analysis
234
        LabelT nLabels = flattenL(P);
235

  
236
        //assign final labels
237
        for(size_t r = 0; r < rows; ++r){
238
            for(size_t c = 0; c < cols; ++c){
239
                L.at<LabelT>(r, c) = P[L.at<LabelT>(r, c)];
240
            }
241
        }
242

  
243
        return nLabels;
244
    }//End function LabelingImpl operator()
245

  
246
    };//End struct LabelingImpl
247
}//end namespace connectedcomponents
248

  
249
//L's type must have an appropriate depth for the number of pixels in I
250
uint64_t connectedComponents(Mat &L, const Mat &I, int connectivity){
251
    CV_Assert(L.rows == I.rows);
252
    CV_Assert(L.cols == I.cols);
253
    CV_Assert(L.channels() == 1 && I.channels() == 1);
254
    CV_Assert(connectivity == 8 || connectivity == 4);
255

  
256
    int lDepth = L.depth();
257
    int iDepth = I.depth();
258
    using connectedcomponents::LabelingImpl;
259
    //warn if L's depth is not sufficient?
260

  
261
    if(lDepth == CV_8U){
262
        if(iDepth == CV_8U || iDepth == CV_8S){
263
            if(connectivity == 4){
264
                return (uint64_t) LabelingImpl<uint8_t, uint8_t, 4>()(L, I);
265
            }else{
266
                return (uint64_t) LabelingImpl<uint8_t, uint8_t, 8>()(L, I);
267
            }
268
        }else if(iDepth == CV_16U || iDepth == CV_16S){
269
            if(connectivity == 4){
270
                return (uint64_t) LabelingImpl<uint8_t, uint16_t, 4>()(L, I);
271
            }else{
272
                return (uint64_t) LabelingImpl<uint8_t, uint16_t, 8>()(L, I);
273
            }
274
        }else if(iDepth == CV_32S){
275
            if(connectivity == 4){
276
                return (uint64_t) LabelingImpl<uint8_t, int32_t, 4>()(L, I);
277
            }else{
278
                return (uint64_t) LabelingImpl<uint8_t, int32_t, 8>()(L, I);
279
            }
280
        }else if(iDepth == CV_32F){
281
            if(connectivity == 4){
282
                return (uint64_t) LabelingImpl<uint8_t, float, 4>()(L, I);
283
            }else{
284
                return (uint64_t) LabelingImpl<uint8_t, float, 8>()(L, I);
285
            }
286
        }else if(iDepth == CV_64F){
287
            if(connectivity == 4){
288
                return (uint64_t) LabelingImpl<uint8_t, double, 4>()(L, I);
289
            }else{
290
                return (uint64_t) LabelingImpl<uint8_t, double, 8>()(L, I);
291
            }
292
        }
293
    }else if(lDepth == CV_16U){
294
        if(iDepth == CV_8U || iDepth == CV_8S){
295
            if(connectivity == 4){
296
                return (uint64_t) LabelingImpl<uint16_t, uint8_t, 4>()(L, I);
297
            }else{
298
                return (uint64_t) LabelingImpl<uint16_t, uint8_t, 8>()(L, I);
299
            }
300
        }else if(iDepth == CV_16U || iDepth == CV_16S){
301
            if(connectivity == 4){
302
                return (uint64_t) LabelingImpl<uint16_t, uint16_t, 4>()(L, I);
303
            }else{
304
                return (uint64_t) LabelingImpl<uint16_t, uint16_t, 8>()(L, I);
305
            }
306
        }else if(iDepth == CV_32S){
307
            if(connectivity == 4){
308
                return (uint64_t) LabelingImpl<uint16_t, int32_t, 4>()(L, I);
309
            }else{
310
                return (uint64_t) LabelingImpl<uint16_t, int32_t, 8>()(L, I);
311
            }
312
        }else if(iDepth == CV_32F){
313
            if(connectivity == 4){
314
                return (uint64_t) LabelingImpl<uint16_t, float, 4>()(L, I);
315
            }else{
316
                return (uint64_t) LabelingImpl<uint16_t, float, 8>()(L, I);
317
            }
318
        }else if(iDepth == CV_64F){
319
            if(connectivity == 4){
320
                return (uint64_t) LabelingImpl<uint16_t, double, 4>()(L, I);
321
            }else{
322
                return (uint64_t) LabelingImpl<uint16_t, double, 8>()(L, I);
323
            }
324
        }
325
    }else if(lDepth == CV_32S){
326
        if(iDepth == CV_8U || iDepth == CV_8S){
327
            if(connectivity == 4){
328
                return (uint64_t) LabelingImpl<int32_t, uint8_t, 4>()(L, I);
329
            }else{
330
                return (uint64_t) LabelingImpl<int32_t, uint8_t, 8>()(L, I);
331
            }
332
        }else if(iDepth == CV_16U || iDepth == CV_16S){
333
            if(connectivity == 4){
334
                return (uint64_t) LabelingImpl<int32_t, uint16_t, 4>()(L, I);
335
            }else{
336
                return (uint64_t) LabelingImpl<int32_t, uint16_t, 8>()(L, I);
337
            }
338
        }else if(iDepth == CV_32S){
339
            if(connectivity == 4){
340
                return (uint64_t) LabelingImpl<int32_t, int32_t, 4>()(L, I);
341
            }else{
342
                return (uint64_t) LabelingImpl<int32_t, int32_t, 8>()(L, I);
343
            }
344
        }else if(iDepth == CV_32F){
345
            if(connectivity == 4){
346
                return (uint64_t) LabelingImpl<int32_t, float, 4>()(L, I);
347
            }else{
348
                return (uint64_t) LabelingImpl<int32_t, float, 8>()(L, I);
349
            }
350
        }else if(iDepth == CV_64F){
351
            if(connectivity == 4){
352
                return (uint64_t) LabelingImpl<int32_t, double, 4>()(L, I);
353
            }else{
354
                return (uint64_t) LabelingImpl<int32_t, double, 8>()(L, I);
355
            }
356
        }
357
    }
358

  
359
    CV_Error(CV_StsUnsupportedFormat, "unsupported label/image type");
360
    return -1;
361
}
362

  
363

  
364
}
365

  
b/samples/cpp/connected_components.cpp
11 11
static void on_trackbar(int, void*)
12 12
{
13 13
    Mat bw = threshval < 128 ? (img < threshval) : (img > threshval);
14

  
15
    vector<vector<Point> > contours;
16
    vector<Vec4i> hierarchy;
17

  
18
    findContours( bw, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );
19

  
20
    Mat dst = Mat::zeros(img.size(), CV_8UC3);
21

  
22
    if( !contours.empty() && !hierarchy.empty() )
23
    {
24
        // iterate through all the top-level contours,
25
        // draw each connected component with its own random color
26
        int idx = 0;
27
        for( ; idx >= 0; idx = hierarchy[idx][0] )
28
        {
29
            Scalar color( (rand()&255), (rand()&255), (rand()&255) );
30
            drawContours( dst, contours, idx, color, CV_FILLED, 8, hierarchy );
31
        }
14
    Mat labelImage(img.size(), CV_32S);
15
    int nLabels = connectedComponents(labelImage, bw, 8);
16
    Vec3b colors[nLabels];
17
    colors[0] = Vec3b(0, 0, 0);//background
18
    for(int label = 1; label < nLabels; ++label){
19
        colors[label] = Vec3b( (rand()&255), (rand()&255), (rand()&255) );
32 20
    }
21
    Mat dst(img.size(), CV_8UC3);
22
    for(int r = 0; r < dst.rows; ++r){
23
        for(int c = 0; c < dst.cols; ++c){
24
            int label = labelImage.at<int>(r, c);
25
            Vec3b &pixel = dst.at<Vec3b>(r, c);
26
            pixel = colors[label];
27
         }
28
     }
33 29

  
34 30
    imshow( "Connected Components", dst );
35 31
}
36
-