NewProggie
NewProggie

Reputation: 1095

Thinning contour lines in a binary image

I have a binary image with contour lines and need to purify each contour line of all unnecessary pixels, leaving behind a minimally connected line.

Can somebody give me a source, code example or further information for this kind of problem and where to search for help, please?

Upvotes: 1

Views: 7784

Answers (4)

Joe Kington
Joe Kington

Reputation: 284750

If you're looking for python implementations, have a look at scikit-image.

One of their examples is essentially your use case.

Alternately, if you wanted to stick to "straight" scipy, you can do this by using successive erosions and dilations using scipy.ndimage. (As @AxezDNyde mentions.)

Edit: Links fixed.

Upvotes: 2

adrianN
adrianN

Reputation: 417

There is a package available on PyPi called thinning that you can just pip install. It implements the thinning algorithm by Guo and Hall for bumpy arrays / opencv grayscale images.

Upvotes: 0

Abtin Rasoulian
Abtin Rasoulian

Reputation: 919

There is a actually an algorithm for that called Zhang-Suen thinning algorithm. You can find its code here: http://rosettacode.org/wiki/Zhang-Suen_thinning_algorithm

Also I wrote a vectorized version of that in Python which is around 10 times faster than that code. Here is the code:

def neighbours_vec(image):
    return image[2:,1:-1], image[2:,2:], image[1:-1,2:], image[:-2,2:], image[:-2,1:-1],     image[:-2,:-2], image[1:-1,:-2], image[2:,:-2]

def transitions_vec(P2, P3, P4, P5, P6, P7, P8, P9):
    return ((P3-P2) > 0).astype(int) + ((P4-P3) > 0).astype(int) + \
    ((P5-P4) > 0).astype(int) + ((P6-P5) > 0).astype(int) + \
    ((P7-P6) > 0).astype(int) + ((P8-P7) > 0).astype(int) + \
    ((P9-P8) > 0).astype(int) + ((P2-P9) > 0).astype(int)

def zhangSuen_vec(image, iterations):
    for iter in range (1, iterations):
        print iter
        # step 1    
        P2,P3,P4,P5,P6,P7,P8,P9 = neighbours_vec(image)
        condition0 = image[1:-1,1:-1]
        condition4 = P4*P6*P8
        condition3 = P2*P4*P6
        condition2 = transitions_vec(P2, P3, P4, P5, P6, P7, P8, P9) == 1
        condition1 = (2 <= P2+P3+P4+P5+P6+P7+P8+P9) * (P2+P3+P4+P5+P6+P7+P8+P9 <= 6)
        cond = (condition0 == 1) * (condition4 == 0) * (condition3 == 0) * (condition2 == 1) * (condition1 == 1)
        changing1 = numpy.where(cond == 1)
        image[changing1[0]+1,changing1[1]+1] = 0
        # step 2
        P2,P3,P4,P5,P6,P7,P8,P9 = neighbours_vec(image)
        condition0 = image[1:-1,1:-1]
        condition4 = P2*P6*P8
        condition3 = P2*P4*P8
        condition2 = transitions_vec(P2, P3, P4, P5, P6, P7, P8, P9) == 1
        condition1 = (2 <= P2+P3+P4+P5+P6+P7+P8+P9) * (P2+P3+P4+P5+P6+P7+P8+P9 <= 6)
        cond = (condition0 == 1) * (condition4 == 0) * (condition3 == 0) * (condition2 == 1) * (condition1 == 1)
        changing2 = numpy.where(cond == 1)
        image[changing2[0]+1,changing2[1]+1] = 0
    return image

Upvotes: 4

Axez D. Nyde
Axez D. Nyde

Reputation: 11

A combination of erosion and dilation (and vice versa) on a binary image can help to get rid of salt n pepper like noise leaving small lines intact. Keywords are 'rank order filters' and 'morphological filters'.

Upvotes: 1

Related Questions