LabelT LabelingGrana()

in tools/cv/source/imgproc/structural.cpp [767:2059]


LabelT LabelingGrana(VARP img, VARP& imgLabels, int connectivity, CCStatsOp& sop) {
    int h, w, c;
    getVARPSize(img, &h, &w, &c);
    std::vector<int> label(h * w, 0);
    imgLabels = _Const(label.data(), {1, h, w, 1}, NHWC, halide_type_of<int>());
    int img_step = w * c, label_step = w;
    //A quick and dirty upper bound for the maximum number of labels.
    //Following formula comes from the fact that a 2x2 block in 8-connectivity case
    //can never have more than 1 new label and 1 label for background.
    //Worst case image example pattern:
    //1 0 1 0 1...
    //0 0 0 0 0...
    //1 0 1 0 1...
    //............
    const size_t Plength = size_t(((h + 1) / 2) * size_t((w + 1) / 2)) + 1;
    std::vector<LabelT> P_(Plength, 0);
    LabelT *P = P_.data();
    LabelT lunique = 1;
    // First scan
    for (int r = 0; r < h; r += 2) {
        // Get rows pointer
        const PixelT * const img_row = img->readMap<PixelT>() + r * img_step;
        const PixelT * const img_row_prev = img_row - img_step;
        const PixelT * const img_row_prev_prev = img_row_prev - img_step;
        const PixelT * const img_row_fol = img_row + img_step;
        LabelT * const imgLabels_row = imgLabels->writeMap<LabelT>() + r * label_step;
        LabelT * const imgLabels_row_prev_prev = imgLabels_row - label_step - label_step;
        for (int c = 0; c < w; c += 2) {
            #define condition_b c-1>=0 && r-2>=0 && img_row_prev_prev[c-1]>0
            #define condition_c r-2>=0 && img_row_prev_prev[c]>0
            #define condition_d c+1<w&& r-2>=0 && img_row_prev_prev[c+1]>0
            #define condition_e c+2<w  && r-1>=0 && img_row_prev[c-1]>0

            #define condition_g c-2>=0 && r-1>=0 && img_row_prev[c-2]>0
            #define condition_h c-1>=0 && r-1>=0 && img_row_prev[c-1]>0
            #define condition_i r-1>=0 && img_row_prev[c]>0
            #define condition_j c+1<w && r-1>=0 && img_row_prev[c+1]>0
            #define condition_k c+2<w && r-1>=0 && img_row_prev[c+2]>0

            #define condition_m c-2>=0 && img_row[c-2]>0
            #define condition_n c-1>=0 && img_row[c-1]>0
            #define condition_o img_row[c]>0
            #define condition_p c+1<w && img_row[c+1]>0

            #define condition_r c-1>=0 && r+1<h && img_row_fol[c-1]>0
            #define condition_s r+1<h && img_row_fol[c]>0
            #define condition_t c+1<w && r+1<h && img_row_fol[c+1]>0
            if (condition_o) {
                if (condition_n) {
                    if (condition_j) {
                        if (condition_i) {
                            //Action_6: Assign label of block S
                            imgLabels_row[c] = imgLabels_row[c - 2];
                            continue;
                        }
                        else {
                            if (condition_c) {
                                if (condition_h) {
                                    //Action_6: Assign label of block S
                                    imgLabels_row[c] = imgLabels_row[c - 2];
                                    continue;
                                }
                                else {
                                    if (condition_g) {
                                        if (condition_b) {
                                            //Action_6: Assign label of block S
                                            imgLabels_row[c] = imgLabels_row[c - 2];
                                            continue;
                                        }
                                        else {
                                            //Action_11: Merge labels of block Q and S
                                            imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]);
                                            continue;
                                        }
                                    }
                                    else {
                                        //Action_11: Merge labels of block Q and S
                                        imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]);
                                        continue;
                                    }
                                }
                            }
                            else {
                                //Action_11: Merge labels of block Q and S
                                imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]);
                                continue;
                            }
                        }
                    }
                    else {
                        if (condition_p) {
                            if (condition_k) {
                                if (condition_d) {
                                    if (condition_i) {
                                        //Action_6: Assign label of block S
                                        imgLabels_row[c] = imgLabels_row[c - 2];
                                        continue;
                                    }
                                    else {
                                        if (condition_c) {
                                            if (condition_h) {
                                                //Action_6: Assign label of block S
                                                imgLabels_row[c] = imgLabels_row[c - 2];
                                                continue;
                                            }
                                            else {
                                                if (condition_g) {
                                                    if (condition_b) {
                                                        //Action_6: Assign label of block S
                                                        imgLabels_row[c] = imgLabels_row[c - 2];
                                                        continue;
                                                    }
                                                    else {
                                                        //Action_12: Merge labels of block R and S
                                                        imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]);
                                                        continue;
                                                    }
                                                }
                                                else {
                                                    //Action_12: Merge labels of block R and S
                                                    imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]);
                                                    continue;
                                                }
                                            }
                                        }
                                        else {
                                            //Action_12: Merge labels of block R and S
                                            imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]);
                                            continue;
                                        }
                                    }
                                }
                                else {
                                    //Action_12: Merge labels of block R and S
                                    imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]);
                                    continue;
                                }
                            }
                            else {
                                //Action_6: Assign label of block S
                                imgLabels_row[c] = imgLabels_row[c - 2];
                                continue;
                            }
                        }
                        else {
                            //Action_6: Assign label of block S
                            imgLabels_row[c] = imgLabels_row[c - 2];
                            continue;
                        }
                    }
                }
                else {
                    if (condition_r) {
                        if (condition_j) {
                            if (condition_m) {
                                if (condition_h) {
                                    if (condition_i) {
                                        //Action_6: Assign label of block S
                                        imgLabels_row[c] = imgLabels_row[c - 2];
                                        continue;
                                    }
                                    else {
                                        if (condition_c) {
                                            //Action_6: Assign label of block S
                                            imgLabels_row[c] = imgLabels_row[c - 2];
                                            continue;
                                        }
                                        else {
                                            //Action_11: Merge labels of block Q and S
                                            imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]);
                                            continue;
                                        }
                                    }
                                }
                                else {
                                    if (condition_g) {
                                        if (condition_b) {
                                            if (condition_i) {
                                                //Action_6: Assign label of block S
                                                imgLabels_row[c] = imgLabels_row[c - 2];
                                                continue;
                                            }
                                            else {
                                                if (condition_c) {
                                                    //Action_6: Assign label of block S
                                                    imgLabels_row[c] = imgLabels_row[c - 2];
                                                    continue;
                                                }
                                                else {
                                                    //Action_11: Merge labels of block Q and S
                                                    imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]);
                                                    continue;
                                                }
                                            }
                                        }
                                        else {
                                            //Action_11: Merge labels of block Q and S
                                            imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]);
                                            continue;
                                        }
                                    }
                                    else {
                                        //Action_11: Merge labels of block Q and S
                                        imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]);
                                        continue;
                                    }
                                }
                            }
                            else {
                                if (condition_i) {
                                    //Action_11: Merge labels of block Q and S
                                    imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]);
                                    continue;
                                }
                                else {
                                    if (condition_h) {
                                        if (condition_c) {
                                            //Action_11: Merge labels of block Q and S
                                            imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]);
                                            continue;
                                        }
                                        else {
                                            //Action_14: Merge labels of block P, Q and S
                                            imgLabels_row[c] = set_union(P, set_union(P, imgLabels_row_prev_prev[c - 2], imgLabels_row_prev_prev[c]), imgLabels_row[c - 2]);
                                            continue;
                                        }
                                    }
                                    else {
                                        //Action_11: Merge labels of block Q and S
                                        imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]);
                                        continue;
                                    }
                                }
                            }
                        }
                        else {
                            if (condition_p) {
                                if (condition_k) {
                                    if (condition_m) {
                                        if (condition_h) {
                                            if (condition_d) {
                                                if (condition_i) {
                                                    //Action_6: Assign label of block S
                                                    imgLabels_row[c] = imgLabels_row[c - 2];
                                                    continue;
                                                }
                                                else {
                                                    if (condition_c) {
                                                        //Action_6: Assign label of block S
                                                        imgLabels_row[c] = imgLabels_row[c - 2];
                                                        continue;
                                                    }
                                                    else {
                                                        //Action_12: Merge labels of block R and S
                                                        imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]);
                                                        continue;
                                                    }
                                                }
                                            }
                                            else {
                                                //Action_12: Merge labels of block R and S
                                                imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]);
                                                continue;
                                            }
                                        }
                                        else {
                                            if (condition_d) {
                                                if (condition_g) {
                                                    if (condition_b) {
                                                        if (condition_i) {
                                                            //Action_6: Assign label of block S
                                                            imgLabels_row[c] = imgLabels_row[c - 2];
                                                            continue;
                                                        }
                                                        else {
                                                            if (condition_c) {
                                                                //Action_6: Assign label of block S
                                                                imgLabels_row[c] = imgLabels_row[c - 2];
                                                                continue;
                                                            }
                                                            else {
                                                                //Action_12: Merge labels of block R and S
                                                                imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]);
                                                                continue;
                                                            }
                                                        }
                                                    }
                                                    else {
                                                        //Action_12: Merge labels of block R and S
                                                        imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]);
                                                        continue;
                                                    }
                                                }
                                                else {
                                                    //Action_12: Merge labels of block R and S
                                                    imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]);
                                                    continue;
                                                }
                                            }
                                            else {
                                                if (condition_i) {
                                                    if (condition_g) {
                                                        if (condition_b) {
                                                            //Action_12: Merge labels of block R and S
                                                            imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]);
                                                            continue;
                                                        }
                                                        else {
                                                            //Action_16: labels of block Q, R and S
                                                            imgLabels_row[c] = set_union(P, set_union(P, imgLabels_row_prev_prev[c], imgLabels_row_prev_prev[c + 2]), imgLabels_row[c - 2]);
                                                            continue;
                                                        }
                                                    }
                                                    else {
                                                        //Action_16: labels of block Q, R and S
                                                        imgLabels_row[c] = set_union(P, set_union(P, imgLabels_row_prev_prev[c], imgLabels_row_prev_prev[c + 2]), imgLabels_row[c - 2]);
                                                        continue;
                                                    }
                                                }
                                                else {
                                                    //Action_12: Merge labels of block R and S
                                                    imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]);
                                                    continue;
                                                }
                                            }
                                        }
                                    }
                                    else {
                                        if (condition_i) {
                                            if (condition_d) {
                                                //Action_12: Merge labels of block R and S
                                                imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]);
                                                continue;
                                            }
                                            else {
                                                //Action_16: labels of block Q, R and S
                                                imgLabels_row[c] = set_union(P, set_union(P, imgLabels_row_prev_prev[c], imgLabels_row_prev_prev[c + 2]), imgLabels_row[c - 2]);
                                                continue;
                                            }
                                        }
                                        else {
                                            if (condition_h) {
                                                if (condition_d) {
                                                    if (condition_c) {
                                                        //Action_12: Merge labels of block R and S
                                                        imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]);
                                                        continue;
                                                    }
                                                    else {
                                                        //Action_15: Merge labels of block P, R and S
                                                        imgLabels_row[c] = set_union(P, set_union(P, imgLabels_row_prev_prev[c - 2], imgLabels_row_prev_prev[c + 2]), imgLabels_row[c - 2]);
                                                        continue;
                                                    }
                                                }
                                                else {
                                                    //Action_15: Merge labels of block P, R and S
                                                    imgLabels_row[c] = set_union(P, set_union(P, imgLabels_row_prev_prev[c - 2], imgLabels_row_prev_prev[c + 2]), imgLabels_row[c - 2]);
                                                    continue;
                                                }
                                            }
                                            else {
                                                //Action_12: Merge labels of block R and S
                                                imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]);
                                                continue;
                                            }
                                        }
                                    }
                                }
                                else {
                                    if (condition_h) {
                                        if (condition_m) {
                                            //Action_6: Assign label of block S
                                            imgLabels_row[c] = imgLabels_row[c - 2];
                                            continue;
                                        }
                                        else {
                                            // ACTION_9 Merge labels of block P and S
                                            imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c - 2], imgLabels_row[c - 2]);
                                            continue;
                                        }
                                    }
                                    else {
                                        if (condition_i) {
                                            if (condition_m) {
                                                if (condition_g) {
                                                    if (condition_b) {
                                                        //Action_6: Assign label of block S
                                                        imgLabels_row[c] = imgLabels_row[c - 2];
                                                        continue;
                                                    }
                                                    else {
                                                        //Action_11: Merge labels of block Q and S
                                                        imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]);
                                                        continue;
                                                    }
                                                }
                                                else {
                                                    //Action_11: Merge labels of block Q and S
                                                    imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]);
                                                    continue;
                                                }
                                            }
                                            else {
                                                //Action_11: Merge labels of block Q and S
                                                imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]);
                                                continue;
                                            }
                                        }
                                        else {
                                            //Action_6: Assign label of block S
                                            imgLabels_row[c] = imgLabels_row[c - 2];
                                            continue;
                                        }
                                    }
                                }
                            }
                            else {
                                if (condition_h) {
                                    if (condition_m) {
                                        //Action_6: Assign label of block S
                                        imgLabels_row[c] = imgLabels_row[c - 2];
                                        continue;
                                    }
                                    else {
                                        // ACTION_9 Merge labels of block P and S
                                        imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c - 2], imgLabels_row[c - 2]);
                                        continue;
                                    }
                                }
                                else {
                                    if (condition_i) {
                                        if (condition_m) {
                                            if (condition_g) {
                                                if (condition_b) {
                                                    //Action_6: Assign label of block S
                                                    imgLabels_row[c] = imgLabels_row[c - 2];
                                                    continue;
                                                }
                                                else {
                                                    //Action_11: Merge labels of block Q and S
                                                    imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]);
                                                    continue;
                                                }
                                            }
                                            else {
                                                //Action_11: Merge labels of block Q and S
                                                imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]);
                                                continue;
                                            }
                                        }
                                        else {
                                            //Action_11: Merge labels of block Q and S
                                            imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]);
                                            continue;
                                        }
                                    }
                                    else {
                                        //Action_6: Assign label of block S
                                        imgLabels_row[c] = imgLabels_row[c - 2];
                                        continue;
                                    }
                                }
                            }
                        }
                    }
                    else {
                        if (condition_j) {
                            if (condition_i) {
                                //Action_4: Assign label of block Q
                                imgLabels_row[c] = imgLabels_row_prev_prev[c];
                                continue;
                            }
                            else {
                                if (condition_h) {
                                    if (condition_c) {
                                        //Action_4: Assign label of block Q
                                        imgLabels_row[c] = imgLabels_row_prev_prev[c];
                                        continue;
                                    }
                                    else {
                                        //Action_7: Merge labels of block P and Q
                                        imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c - 2], imgLabels_row_prev_prev[c]);
                                        continue;
                                    }
                                }
                                else {
                                    //Action_4: Assign label of block Q
                                    imgLabels_row[c] = imgLabels_row_prev_prev[c];
                                    continue;
                                }
                            }
                        }
                        else {
                            if (condition_p) {
                                if (condition_k) {
                                    if (condition_i) {
                                        if (condition_d) {
                                            //Action_5: Assign label of block R
                                            imgLabels_row[c] = imgLabels_row_prev_prev[c + 2];
                                            continue;
                                        }
                                        else {
                                            // ACTION_10 Merge labels of block Q and R
                                            imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row_prev_prev[c + 2]);
                                            continue;
                                        }
                                    }
                                    else {
                                        if (condition_h) {
                                            if (condition_d) {
                                                if (condition_c) {
                                                    //Action_5: Assign label of block R
                                                    imgLabels_row[c] = imgLabels_row_prev_prev[c + 2];
                                                    continue;
                                                }
                                                else {
                                                    //Action_8: Merge labels of block P and R
                                                    imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c - 2], imgLabels_row_prev_prev[c + 2]);
                                                    continue;
                                                }
                                            }
                                            else {
                                                //Action_8: Merge labels of block P and R
                                                imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c - 2], imgLabels_row_prev_prev[c + 2]);
                                                continue;
                                            }
                                        }
                                        else {
                                            //Action_5: Assign label of block R
                                            imgLabels_row[c] = imgLabels_row_prev_prev[c + 2];
                                            continue;
                                        }
                                    }
                                }
                                else {
                                    if (condition_i) {
                                        //Action_4: Assign label of block Q
                                        imgLabels_row[c] = imgLabels_row_prev_prev[c];
                                        continue;
                                    }
                                    else {
                                        if (condition_h) {
                                            //Action_3: Assign label of block P
                                            imgLabels_row[c] = imgLabels_row_prev_prev[c - 2];
                                            continue;
                                        }
                                        else {
                                            //Action_2: New label (the block has foreground pixels and is not connected to anything else)
                                            imgLabels_row[c] = lunique;
                                            P[lunique] = lunique;
                                            lunique = lunique + 1;
                                            continue;
                                        }
                                    }
                                }
                            }
                            else {
                                if (condition_i) {
                                    //Action_4: Assign label of block Q
                                    imgLabels_row[c] = imgLabels_row_prev_prev[c];
                                    continue;
                                }
                                else {
                                    if (condition_h) {
                                        //Action_3: Assign label of block P
                                        imgLabels_row[c] = imgLabels_row_prev_prev[c - 2];
                                        continue;
                                    }
                                    else {
                                        //Action_2: New label (the block has foreground pixels and is not connected to anything else)
                                        imgLabels_row[c] = lunique;
                                        P[lunique] = lunique;
                                        lunique = lunique + 1;
                                        continue;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            else {
                if (condition_s) {
                    if (condition_p) {
                        if (condition_n) {
                            if (condition_j) {
                                if (condition_i) {
                                    //Action_6: Assign label of block S
                                    imgLabels_row[c] = imgLabels_row[c - 2];
                                    continue;
                                }
                                else {
                                    if (condition_c) {
                                        if (condition_h) {
                                            //Action_6: Assign label of block S
                                            imgLabels_row[c] = imgLabels_row[c - 2];
                                            continue;
                                        }
                                        else {
                                            if (condition_g) {
                                                if (condition_b) {
                                                    //Action_6: Assign label of block S
                                                    imgLabels_row[c] = imgLabels_row[c - 2];
                                                    continue;
                                                }
                                                else {
                                                    //Action_11: Merge labels of block Q and S
                                                    imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]);
                                                    continue;
                                                }
                                            }
                                            else {
                                                //Action_11: Merge labels of block Q and S
                                                imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]);
                                                continue;
                                            }
                                        }
                                    }
                                    else {
                                        //Action_11: Merge labels of block Q and S
                                        imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]);
                                        continue;
                                    }
                                }
                            }
                            else {
                                if (condition_k) {
                                    if (condition_d) {
                                        if (condition_i) {
                                            //Action_6: Assign label of block S
                                            imgLabels_row[c] = imgLabels_row[c - 2];
                                            continue;
                                        }
                                        else {
                                            if (condition_c) {
                                                if (condition_h) {
                                                    //Action_6: Assign label of block S
                                                    imgLabels_row[c] = imgLabels_row[c - 2];
                                                    continue;
                                                }
                                                else {
                                                    if (condition_g) {
                                                        if (condition_b) {
                                                            //Action_6: Assign label of block S
                                                            imgLabels_row[c] = imgLabels_row[c - 2];
                                                            continue;
                                                        }
                                                        else {
                                                            //Action_12: Merge labels of block R and S
                                                            imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]);
                                                            continue;
                                                        }
                                                    }
                                                    else {
                                                        //Action_12: Merge labels of block R and S
                                                        imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]);
                                                        continue;
                                                    }
                                                }
                                            }
                                            else {
                                                //Action_12: Merge labels of block R and S
                                                imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]);
                                                continue;
                                            }
                                        }
                                    }
                                    else {
                                        //Action_12: Merge labels of block R and S
                                        imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]);
                                        continue;
                                    }
                                }
                                else {
                                    //Action_6: Assign label of block S
                                    imgLabels_row[c] = imgLabels_row[c - 2];
                                    continue;
                                }
                            }
                        }
                        else {
                            if (condition_r) {
                                if (condition_j) {
                                    if (condition_m) {
                                        if (condition_h) {
                                            if (condition_i) {
                                                //Action_6: Assign label of block S
                                                imgLabels_row[c] = imgLabels_row[c - 2];
                                                continue;
                                            }
                                            else {
                                                if (condition_c) {
                                                    //Action_6: Assign label of block S
                                                    imgLabels_row[c] = imgLabels_row[c - 2];
                                                    continue;
                                                }
                                                else {
                                                    //Action_11: Merge labels of block Q and S
                                                    imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]);
                                                    continue;
                                                }
                                            }
                                        }
                                        else {
                                            if (condition_g) {
                                                if (condition_b) {
                                                    if (condition_i) {
                                                        //Action_6: Assign label of block S
                                                        imgLabels_row[c] = imgLabels_row[c - 2];
                                                        continue;
                                                    }
                                                    else {
                                                        if (condition_c) {
                                                            //Action_6: Assign label of block S
                                                            imgLabels_row[c] = imgLabels_row[c - 2];
                                                            continue;
                                                        }
                                                        else {
                                                            //Action_11: Merge labels of block Q and S
                                                            imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]);
                                                            continue;
                                                        }
                                                    }
                                                }
                                                else {
                                                    //Action_11: Merge labels of block Q and S
                                                    imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]);
                                                    continue;
                                                }
                                            }
                                            else {
                                                //Action_11: Merge labels of block Q and S
                                                imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]);
                                                continue;
                                            }
                                        }
                                    }
                                    else {
                                        //Action_11: Merge labels of block Q and S
                                        imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]);
                                        continue;
                                    }
                                }
                                else {
                                    if (condition_k) {
                                        if (condition_d) {
                                            if (condition_m) {
                                                if (condition_h) {
                                                    if (condition_i) {
                                                        //Action_6: Assign label of block S
                                                        imgLabels_row[c] = imgLabels_row[c - 2];
                                                        continue;
                                                    }
                                                    else {
                                                        if (condition_c) {
                                                            //Action_6: Assign label of block S
                                                            imgLabels_row[c] = imgLabels_row[c - 2];
                                                            continue;
                                                        }
                                                        else {
                                                            //Action_12: Merge labels of block R and S
                                                            imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]);
                                                            continue;
                                                        }
                                                    }
                                                }
                                                else {
                                                    if (condition_g) {
                                                        if (condition_b) {
                                                            if (condition_i) {
                                                                //Action_6: Assign label of block S
                                                                imgLabels_row[c] = imgLabels_row[c - 2];
                                                                continue;
                                                            }
                                                            else {
                                                                if (condition_c) {
                                                                    //Action_6: Assign label of block S
                                                                    imgLabels_row[c] = imgLabels_row[c - 2];
                                                                    continue;
                                                                }
                                                                else {
                                                                    //Action_12: Merge labels of block R and S
                                                                    imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]);
                                                                    continue;
                                                                }
                                                            }
                                                        }
                                                        else {
                                                            //Action_12: Merge labels of block R and S
                                                            imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]);
                                                            continue;
                                                        }
                                                    }
                                                    else {
                                                        //Action_12: Merge labels of block R and S
                                                        imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]);
                                                        continue;
                                                    }
                                                }
                                            }
                                            else {
                                                //Action_12: Merge labels of block R and S
                                                imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]);
                                                continue;
                                            }
                                        }
                                        else {
                                            if (condition_i) {
                                                if (condition_m) {
                                                    if (condition_h) {
                                                        //Action_12: Merge labels of block R and S
                                                        imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]);
                                                        continue;
                                                    }
                                                    else {
                                                        if (condition_g) {
                                                            if (condition_b) {
                                                                //Action_12: Merge labels of block R and S
                                                                imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]);
                                                                continue;
                                                            }
                                                            else {
                                                                //Action_16: labels of block Q, R and S
                                                                imgLabels_row[c] = set_union(P, set_union(P, imgLabels_row_prev_prev[c], imgLabels_row_prev_prev[c + 2]), imgLabels_row[c - 2]);
                                                                continue;
                                                            }
                                                        }
                                                        else {
                                                            //Action_16: labels of block Q, R and S
                                                            imgLabels_row[c] = set_union(P, set_union(P, imgLabels_row_prev_prev[c], imgLabels_row_prev_prev[c + 2]), imgLabels_row[c - 2]);
                                                            continue;
                                                        }
                                                    }
                                                }
                                                else {
                                                    //Action_16: labels of block Q, R and S
                                                    imgLabels_row[c] = set_union(P, set_union(P, imgLabels_row_prev_prev[c], imgLabels_row_prev_prev[c + 2]), imgLabels_row[c - 2]);
                                                    continue;
                                                }
                                            }
                                            else {
                                                //Action_12: Merge labels of block R and S
                                                imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c + 2], imgLabels_row[c - 2]);
                                                continue;
                                            }
                                        }
                                    }
                                    else {
                                        if (condition_i) {
                                            if (condition_m) {
                                                if (condition_h) {
                                                    //Action_6: Assign label of block S
                                                    imgLabels_row[c] = imgLabels_row[c - 2];
                                                    continue;
                                                }
                                                else {
                                                    if (condition_g) {
                                                        if (condition_b) {
                                                            //Action_6: Assign label of block S
                                                            imgLabels_row[c] = imgLabels_row[c - 2];
                                                            continue;
                                                        }
                                                        else {
                                                            //Action_11: Merge labels of block Q and S
                                                            imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]);
                                                            continue;
                                                        }
                                                    }
                                                    else {
                                                        //Action_11: Merge labels of block Q and S
                                                        imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]);
                                                        continue;
                                                    }
                                                }
                                            }
                                            else {
                                                //Action_11: Merge labels of block Q and S
                                                imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row[c - 2]);
                                                continue;
                                            }
                                        }
                                        else {
                                            //Action_6: Assign label of block S
                                            imgLabels_row[c] = imgLabels_row[c - 2];
                                            continue;
                                        }
                                    }
                                }
                            }
                            else {
                                if (condition_j) {
                                    //Action_4: Assign label of block Q
                                    imgLabels_row[c] = imgLabels_row_prev_prev[c];
                                    continue;
                                }
                                else {
                                    if (condition_k) {
                                        if (condition_i) {
                                            if (condition_d) {
                                                //Action_5: Assign label of block R
                                                imgLabels_row[c] = imgLabels_row_prev_prev[c + 2];
                                                continue;
                                            }
                                            else {
                                                // ACTION_10 Merge labels of block Q and R
                                                imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row_prev_prev[c + 2]);
                                                continue;
                                            }
                                        }
                                        else {
                                            //Action_5: Assign label of block R
                                            imgLabels_row[c] = imgLabels_row_prev_prev[c + 2];
                                            continue;
                                        }
                                    }
                                    else {
                                        if (condition_i) {
                                            //Action_4: Assign label of block Q
                                            imgLabels_row[c] = imgLabels_row_prev_prev[c];
                                            continue;
                                        }
                                        else {
                                            //Action_2: New label (the block has foreground pixels and is not connected to anything else)
                                            imgLabels_row[c] = lunique;
                                            P[lunique] = lunique;
                                            lunique = lunique + 1;
                                            continue;
                                        }
                                    }
                                }
                            }
                        }
                    }
                    else {
                        if (condition_r) {
                            //Action_6: Assign label of block S
                            imgLabels_row[c] = imgLabels_row[c - 2];
                            continue;
                        }
                        else {
                            if (condition_n) {
                                //Action_6: Assign label of block S
                                imgLabels_row[c] = imgLabels_row[c - 2];
                                continue;
                            }
                            else {
                                //Action_2: New label (the block has foreground pixels and is not connected to anything else)
                                imgLabels_row[c] = lunique;
                                P[lunique] = lunique;
                                lunique = lunique + 1;
                                continue;
                            }
                        }
                    }
                }
                else {
                    if (condition_p) {
                        if (condition_j) {
                            //Action_4: Assign label of block Q
                            imgLabels_row[c] = imgLabels_row_prev_prev[c];
                            continue;
                        }
                        else {
                            if (condition_k) {
                                if (condition_i) {
                                    if (condition_d) {
                                        //Action_5: Assign label of block R
                                        imgLabels_row[c] = imgLabels_row_prev_prev[c + 2];
                                        continue;
                                    }
                                    else {
                                        // ACTION_10 Merge labels of block Q and R
                                        imgLabels_row[c] = set_union(P, imgLabels_row_prev_prev[c], imgLabels_row_prev_prev[c + 2]);
                                        continue;
                                    }
                                }
                                else {
                                    //Action_5: Assign label of block R
                                    imgLabels_row[c] = imgLabels_row_prev_prev[c + 2];
                                    continue;
                                }
                            }
                            else {
                                if (condition_i) {
                                    //Action_4: Assign label of block Q
                                    imgLabels_row[c] = imgLabels_row_prev_prev[c];
                                    continue;
                                }
                                else {
                                    //Action_2: New label (the block has foreground pixels and is not connected to anything else)
                                    imgLabels_row[c] = lunique;
                                    P[lunique] = lunique;
                                    lunique = lunique + 1;
                                    continue;
                                }
                            }
                        }
                    }
                    else {
                        if (condition_t) {
                            //Action_2: New label (the block has foreground pixels and is not connected to anything else)
                            imgLabels_row[c] = lunique;
                            P[lunique] = lunique;
                            lunique = lunique + 1;
                            continue;
                        }
                        else {
                            // Action_1: No action (the block has no foreground pixels)
                            imgLabels_row[c] = 0;
                            continue;
                        }
                    }
                }
            }
        }
    }

    // Second scan + analysis
    LabelT nLabels = flattenL(P, lunique);
    sop.init(nLabels);
    if (h & 1){
        if (w & 1){
            // Case 1: both rows and cols odd
            for (int r = 0; r < h; r += 2) {
                // Get rows pointer
                const PixelT * const img_row = img->readMap<PixelT>() + r * img_step;
                const PixelT * const img_row_fol = img_row + img_step;
                LabelT * const imgLabels_row = imgLabels->writeMap<LabelT>() + r * label_step;
                LabelT * const imgLabels_row_fol = imgLabels_row + label_step;

                for (int c = 0; c < w; c += 2) {
                    LabelT iLabel = imgLabels_row[c];
                    if (iLabel > 0) {
                        iLabel = P[iLabel];
                        if (img_row[c] > 0){
                            imgLabels_row[c] = iLabel;
                            sop(r, c, iLabel);
                        }
                        else{
                            imgLabels_row[c] = 0;
                            sop(r, c, 0);
                        }
                        if (c + 1 < w) {
                            if (img_row[c + 1] > 0){
                                imgLabels_row[c + 1] = iLabel;
                                sop(r, c + 1, iLabel);
                            }
                            else{
                                imgLabels_row[c + 1] = 0;
                                sop(r, c + 1, 0);
                            }
                            if (r + 1 < h) {
                                if (img_row_fol[c] > 0){
                                    imgLabels_row_fol[c] = iLabel;
                                    sop(r + 1, c, iLabel);
                                }
                                else{
                                    imgLabels_row_fol[c] = 0;
                                    sop(r + 1, c, 0);
                                }
                                if (img_row_fol[c + 1] > 0){
                                    imgLabels_row_fol[c + 1] = iLabel;
                                    sop(r + 1, c + 1, iLabel);
                                }
                                else{
                                    imgLabels_row_fol[c + 1] = 0;
                                    sop(r + 1, c + 1, 0);
                                }
                            }
                        }
                        else if (r + 1 < h) {
                            if (img_row_fol[c] > 0){
                                imgLabels_row_fol[c] = iLabel;
                                sop(r + 1, c, iLabel);
                            }
                            else{
                                imgLabels_row_fol[c] = 0;
                                sop(r + 1, c, 0);
                            }
                        }
                    }
                    else {
                        imgLabels_row[c] = 0;
                        sop(r, c, 0);
                        if (c + 1 < w) {
                            imgLabels_row[c + 1] = 0;
                            sop(r, c + 1, 0);
                            if (r + 1 < h) {
                                imgLabels_row_fol[c] = 0;
                                imgLabels_row_fol[c + 1] = 0;
                                sop(r + 1, c, 0);
                                sop(r + 1, c + 1, 0);
                            }
                        }
                        else if (r + 1 < h) {
                            imgLabels_row_fol[c] = 0;
                            sop(r + 1, c, 0);
                        }
                    }
                }
            }
        }//END Case 1
        else{
            //Case 2: only rows odd
            for (int r = 0; r < h; r += 2) {
                // Get rows pointer
                const PixelT * const img_row = img->readMap<PixelT>() + r * img_step;
                const PixelT * const img_row_fol = img_row + img_step;
                LabelT * const imgLabels_row = imgLabels->writeMap<LabelT>() + r * label_step;
                LabelT * const imgLabels_row_fol = imgLabels_row + label_step;

                for (int c = 0; c < w; c += 2) {
                    LabelT iLabel = imgLabels_row[c];
                    if (iLabel > 0) {
                        iLabel = P[iLabel];
                        if (img_row[c] > 0){
                            imgLabels_row[c] = iLabel;
                            sop(r, c, iLabel);
                        }
                        else{
                            imgLabels_row[c] = 0;
                            sop(r, c, 0);
                        }
                        if (img_row[c + 1] > 0){
                            imgLabels_row[c + 1] = iLabel;
                            sop(r, c + 1, iLabel);
                        }
                        else{
                            imgLabels_row[c + 1] = 0;
                            sop(r, c + 1, 0);
                        }
                        if (r + 1 < h) {
                            if (img_row_fol[c] > 0){
                                imgLabels_row_fol[c] = iLabel;
                                sop(r + 1, c, iLabel);
                            }
                            else{
                                imgLabels_row_fol[c] = 0;
                                sop(r + 1, c, 0);
                            }
                            if (img_row_fol[c + 1] > 0){
                                imgLabels_row_fol[c + 1] = iLabel;
                                sop(r + 1, c + 1, iLabel);
                            }
                            else{
                                imgLabels_row_fol[c + 1] = 0;
                                sop(r + 1, c + 1, 0);
                            }
                        }
                    }
                    else {
                        imgLabels_row[c] = 0;
                        imgLabels_row[c + 1] = 0;
                        sop(r, c, 0);
                        sop(r, c + 1, 0);
                        if (r + 1 < h) {
                            imgLabels_row_fol[c] = 0;
                            imgLabels_row_fol[c + 1] = 0;
                            sop(r + 1, c, 0);
                            sop(r + 1, c + 1, 0);
                        }
                    }
                }
            }
        }// END Case 2
    }
    else{
        if (w & 1){
            //Case 3: only cols odd
            for (int r = 0; r < h; r += 2) {
                // Get rows pointer
                const PixelT * const img_row = img->readMap<PixelT>() + r * img_step;
                const PixelT * const img_row_fol = img_row + img_step;
                LabelT * const imgLabels_row = imgLabels->writeMap<LabelT>() + r * label_step;
                LabelT * const imgLabels_row_fol = imgLabels_row + label_step;

                for (int c = 0; c < w; c += 2) {
                    LabelT iLabel = imgLabels_row[c];
                    if (iLabel > 0) {
                        iLabel = P[iLabel];
                        if (img_row[c] > 0){
                            imgLabels_row[c] = iLabel;
                            sop(r, c, iLabel);
                        }
                        else{
                            imgLabels_row[c] = 0;
                            sop(r, c, 0);
                        }
                        if (img_row_fol[c] > 0){
                            imgLabels_row_fol[c] = iLabel;
                            sop(r + 1, c, iLabel);
                        }
                        else{
                            imgLabels_row_fol[c] = 0;
                            sop(r + 1, c, 0);
                        }
                        if (c + 1 < w) {
                            if (img_row[c + 1] > 0){
                                imgLabels_row[c + 1] = iLabel;
                                sop(r, c + 1, iLabel);
                            }
                            else{
                                imgLabels_row[c + 1] = 0;
                                sop(r, c + 1, 0);
                            }
                            if (img_row_fol[c + 1] > 0){
                                imgLabels_row_fol[c + 1] = iLabel;
                                sop(r + 1, c + 1, iLabel);
                            }
                            else{
                                imgLabels_row_fol[c + 1] = 0;
                                sop(r + 1, c + 1, 0);
                            }
                        }
                    }
                    else{
                        imgLabels_row[c] = 0;
                        imgLabels_row_fol[c] = 0;
                        sop(r, c, 0);
                        sop(r + 1, c, 0);
                        if (c + 1 < w) {
                            imgLabels_row[c + 1] = 0;
                            imgLabels_row_fol[c + 1] = 0;
                            sop(r, c + 1, 0);
                            sop(r + 1, c + 1, 0);
                        }
                    }
                }
            }
        }// END case 3
        else{
            //Case 4: nothing odd
            for (int r = 0; r < h; r += 2) {
                // Get rows pointer
                const PixelT * const img_row = img->readMap<PixelT>() + r * img_step;
                const PixelT * const img_row_fol = img_row + img_step;
                LabelT * const imgLabels_row = imgLabels->writeMap<LabelT>() + r * label_step;
                LabelT * const imgLabels_row_fol = imgLabels_row + label_step;

                for (int c = 0; c < w; c += 2) {
                    LabelT iLabel = imgLabels_row[c];
                    if (iLabel > 0) {
                        iLabel = P[iLabel];
                        if (img_row[c] > 0){
                            imgLabels_row[c] = iLabel;
                            sop(r, c, iLabel);
                        }
                        else{
                            imgLabels_row[c] = 0;
                            sop(r, c, 0);
                        }
                        if (img_row[c + 1] > 0){
                            imgLabels_row[c + 1] = iLabel;
                            sop(r, c + 1, iLabel);
                        }
                        else{
                            imgLabels_row[c + 1] = 0;
                            sop(r, c + 1, 0);
                        }
                        if (img_row_fol[c] > 0){
                            imgLabels_row_fol[c] = iLabel;
                            sop(r + 1, c, iLabel);
                        }
                        else{
                            imgLabels_row_fol[c] = 0;
                            sop(r + 1, c, 0);
                        }
                        if (img_row_fol[c + 1] > 0){
                            imgLabels_row_fol[c + 1] = iLabel;
                            sop(r + 1, c + 1, iLabel);
                        }
                        else{
                            imgLabels_row_fol[c + 1] = 0;
                            sop(r + 1, c + 1, 0);
                        }
                    }
                    else {
                        imgLabels_row[c] = 0;
                        imgLabels_row[c + 1] = 0;
                        imgLabels_row_fol[c] = 0;
                        imgLabels_row_fol[c + 1] = 0;
                        sop(r, c, 0);
                        sop(r, c + 1, 0);
                        sop(r + 1, c, 0);
                        sop(r + 1, c + 1, 0);
                    }
                }
            }
        }//END case 4
    }
    sop.finish();
    return nLabels;
}