Quantcast

Morphological thinning operation from Z. Guo and R. W. Hall, "Parallel Thinn....

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Morphological thinning operation from Z. Guo and R. W. Hall, "Parallel Thinn....

fatihtsp
Hello,

Morphological thinning with openCV. code gets from:
Z. Guo and R. W. Hall, "Parallel Thinning with Two-Subiteration Algorithm", Communications of the ACM, vol. 32, no. 3, March 1989.
This code takes two CvMat variable but can be easily converted to use with IplImage.

hope it helps skeletonization of the binary image.



/*------------------------ BEGIN ---------------------------*/

void MorphologicalThinning(CvMat *pSrc, CvMat *pDst) {
        bool bDone = false;
        int rows = pSrc->rows;
        int cols = pSrc->cols;
        /// pad source
        CvMat *p_enlarged_src = cvCreateMat(rows + 2, cols + 2, CV_32FC1);
        for(int i = 0; i < (rows+2); i++) {
                CV_MAT_ELEM(*p_enlarged_src, float, i, 0) = 0.0f;
                CV_MAT_ELEM(*p_enlarged_src, float, i, cols+1) = 0.0f;
        }
        for(int j = 0; j < (cols+2); j++) {
                CV_MAT_ELEM(*p_enlarged_src, float, 0, j) = 0.0f;
                CV_MAT_ELEM(*p_enlarged_src, float, rows+1, j) = 0.0f;
        }
        for(int i = 0; i < rows; i++) {
                for(int j = 0; j < cols; j++) {
                        if (CV_MAT_ELEM(*pSrc, float, i, j) >= 0.5f) {
                                CV_MAT_ELEM(*p_enlarged_src, float, i+1, j+1) = 1.0f;
                        }
                        else
                                CV_MAT_ELEM(*p_enlarged_src, float, i+1, j+1) = 0.0f;
                }
        }
        /// start to thin
        CvMat *p_thinMat1 = cvCreateMat(rows + 2, cols + 2, CV_32FC1);
        CvMat *p_thinMat2 = cvCreateMat(rows + 2, cols + 2, CV_32FC1);
        CvMat *p_cmp = cvCreateMat(rows + 2, cols + 2, CV_8UC1);
        while (bDone != true) {
                /// sub-iteration 1
                ThinSubiteration1(p_enlarged_src, p_thinMat1);
                /// sub-iteration 2
                ThinSubiteration2(p_thinMat1, p_thinMat2);
                /// compare
                cvCmp(p_enlarged_src, p_thinMat2, p_cmp, CV_CMP_EQ);
                /// check
                int num_non_zero = cvCountNonZero(p_cmp);
                if(num_non_zero == (rows + 2) * (cols + 2)) {
                        bDone = true;
                }
                /// copy
                cvCopy(p_thinMat2, p_enlarged_src);
        }
        /// copy result
        for(int i = 0; i < rows; i++) {
                for(int j = 0; j < cols; j++) {
                        CV_MAT_ELEM(*pDst, float, i, j) = CV_MAT_ELEM(*p_enlarged_src, float, i+1, j+1);
                }
        }
        /// clean memory
        cvReleaseMat(&p_enlarged_src);
        cvReleaseMat(&p_thinMat1);
        cvReleaseMat(&p_thinMat2);
        cvReleaseMat(&p_cmp);
}
void ThinSubiteration1(CvMat *pSrc, CvMat *pDst) {
        int rows = pSrc->rows;
        int cols = pSrc->cols;
        cvCopy(pSrc, pDst);
        for(int i = 0; i < rows; i++) {
                for(int j = 0; j < cols; j++) {
                        if(CV_MAT_ELEM(*pSrc, float, i, j) == 1.0f) {
                                /// get 8 neighbors
                                /// calculate C(p)
                                int neighbor0 = (int) CV_MAT_ELEM(*pSrc, float, i-1, j-1);
                                int neighbor1 = (int) CV_MAT_ELEM(*pSrc, float, i-1, j);
                                int neighbor2 = (int) CV_MAT_ELEM(*pSrc, float, i-1, j+1);
                                int neighbor3 = (int) CV_MAT_ELEM(*pSrc, float, i, j+1);
                                int neighbor4 = (int) CV_MAT_ELEM(*pSrc, float, i+1, j+1);
                                int neighbor5 = (int) CV_MAT_ELEM(*pSrc, float, i+1, j);
                                int neighbor6 = (int) CV_MAT_ELEM(*pSrc, float, i+1, j-1);
                                int neighbor7 = (int) CV_MAT_ELEM(*pSrc, float, i, j-1);
                                int C = int(~neighbor1 & ( neighbor2 | neighbor3)) +
                                                 int(~neighbor3 & ( neighbor4 | neighbor5)) +
                                                 int(~neighbor5 & ( neighbor6 | neighbor7)) +
                                                 int(~neighbor7 & ( neighbor0 | neighbor1));
                                if(C == 1) {
                                        /// calculate N
                                        int N1 = int(neighbor0 | neighbor1) +
                                                         int(neighbor2 | neighbor3) +
                                                         int(neighbor4 | neighbor5) +
                                                         int(neighbor6 | neighbor7);
                                        int N2 = int(neighbor1 | neighbor2) +
                                                         int(neighbor3 | neighbor4) +
                                                         int(neighbor5 | neighbor6) +
                                                         int(neighbor7 | neighbor0);
                                        int N = min(N1,N2);
                                        if ((N == 2) || (N == 3)) {
                                                /// calculate criteria 3
                                                int c3 = ( neighbor1 | neighbor2 | ~neighbor4) & neighbor3;
                                                if(c3 == 0) {
                                                        CV_MAT_ELEM(*pDst, float, i, j) = 0.0f;
                                                }
                                        }
                                }
                        }
                }
        }
}


void ThinSubiteration2(CvMat *pSrc, CvMat *pDst) {
        int rows = pSrc->rows;
        int cols = pSrc->cols;
        cvCopy(pSrc, pDst);
        for(int i = 0; i < rows; i++) {
                for(int j = 0; j < cols; j++) {
                        if ( CV_MAT_ELEM(*pSrc, float, i, j) == 1.0f) {
                                /// get 8 neighbors
                                /// calculate C(p)
                                int neighbor0 = (int) CV_MAT_ELEM(*pSrc, float, i-1, j-1);
                                int neighbor1 = (int) CV_MAT_ELEM(*pSrc, float, i-1, j);
                                int neighbor2 = (int) CV_MAT_ELEM(*pSrc, float, i-1, j+1);
                                int neighbor3 = (int) CV_MAT_ELEM(*pSrc, float, i, j+1);
                                int neighbor4 = (int) CV_MAT_ELEM(*pSrc, float, i+1, j+1);
                                int neighbor5 = (int) CV_MAT_ELEM(*pSrc, float, i+1, j);
                                int neighbor6 = (int) CV_MAT_ELEM(*pSrc, float, i+1, j-1);
                                int neighbor7 = (int) CV_MAT_ELEM(*pSrc, float, i, j-1);
                                int C = int(~neighbor1 & ( neighbor2 | neighbor3)) +
                                        int(~neighbor3 & ( neighbor4 | neighbor5)) +
                                        int(~neighbor5 & ( neighbor6 | neighbor7)) +
                                        int(~neighbor7 & ( neighbor0 | neighbor1));
                                if(C == 1) {
                                        /// calculate N
                                        int N1 = int(neighbor0 | neighbor1) +
                                                int(neighbor2 | neighbor3) +
                                                int(neighbor4 | neighbor5) +
                                                int(neighbor6 | neighbor7);
                                        int N2 = int(neighbor1 | neighbor2) +
                                                int(neighbor3 | neighbor4) +
                                                int(neighbor5 | neighbor6) +
                                                int(neighbor7 | neighbor0);
                                        int N = min(N1,N2);
                                        if((N == 2) || (N == 3)) {
                                                int E = (neighbor5 | neighbor6 | ~neighbor0) & neighbor7;
                                                if(E == 0) {
                                                        CV_MAT_ELEM(*pDst, float, i, j) = 0.0f;
                                                }
                                        }
                                }
                        }
                }
        }
}



Loading...