Reputation: 1095
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
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
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
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
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