
Hi, I've been playing around with the binary_hit_or_miss function in the nd_image and it seems to work well in general. I understand that binary thinning can be generated by using hit_or_miss, however I can't seem to get it to work right. Anyone have a code snippet that does the job? I follow the procedure at: http://homepages.inf.ed.ac.uk/rbf/HIPR2/thin.htm My implementation is as follows: ## from HIPR2 web site ## [0,0,0] ## [x,1,x] ## [1,1,1] struct1 = numarray.array( [[0, 0, 0], [0, 1, 0], [1, 1, 1]]) struct2 = numarray.array( [[1, 1, 1], [0, 0, 0], [0, 0, 0]]) ## [x,0,0] ## [1,1,0] ## [x,1,x] struct3 = numarray.array( [[0, 0, 0], [1, 1, 0], [0, 1, 0]]) struct4 = numarray.array( [[0, 1, 1], [0, 0, 1], [0, 0, 0]]) b = [] for i in range(4): temp = ND.binary_hit_or_miss(a, struct1, struct2) b.append(temp) temp = ND.binary_hit_or_miss(a, struct3, struct4) b.append(temp) struct1 = ND.rotate(struct1, 90) struct2 = ND.rotate(struct2, 90) struct3 = ND.rotate(struct3, 90) struct4 = ND.rotate(struct4, 90) result = b[0] for i in range(7): result = numarray.logical_or(result, b[i+1]) result = a - result Bob

Hi Bob, I noticed two problems: 1) you construct rotations of your structures with the nd_image.rotate function. That will not work properly because this function uses spline interpolation, which not necessarily produces exact results. In this case you need to use another, exact rotation method, see my implementation below. 2) I think (correct me if I am wrong) that the application of the 8 structures is sequential, not parallel as you do it. Below I give my implementation, which does not produce the exact same result as shown on the webpage you refer to, although the result seems to be a proper skeleton. This may be because the order in which the structures are applied matters (I think). Could you maybe test that by permutating the order in which the structures are applied? I would be interested if this is true and if one can get the same result as on the webpage by finding the right sequence... Cheers, Peter import numarray from numarray import nd_image image = numarray.array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0], [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0], [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0], [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0], [0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0], [0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]) hit1 = numarray.array([[0, 0, 0], [0, 1, 0], [1, 1, 1]]) miss1 = numarray.array([[1, 1, 1], [0, 0, 0], [0, 0, 0]]) hit2 = numarray.array([[0, 0, 0], [1, 1, 0], [0, 1, 0]]) miss2 = numarray.array([[0, 1, 1], [0, 0, 1], [0, 0, 0]]) hit_list = [hit1, hit2] miss_list = [miss1, miss2] for ii in range(6): hit_list.append(numarray.transpose(hit_list[-2])[::-1, ...]) miss_list.append(numarray.transpose(miss_list[-2])[::-1, ...]) while 1: last = image for hit, miss in zip(hit_list, miss_list): hm = nd_image.binary_hit_or_miss(image, hit, miss) image = numarray.logical_and(image, numarray.logical_not(hm)) if numarray.abs(last - image).max() == 0: break print image On 8 Dec 2004, at 00:20, Bob Klimek wrote:
Hi,
I've been playing around with the binary_hit_or_miss function in the nd_image and it seems to work well in general. I understand that binary thinning can be generated by using hit_or_miss, however I can't seem to get it to work right. Anyone have a code snippet that does the job?
I follow the procedure at:
http://homepages.inf.ed.ac.uk/rbf/HIPR2/thin.htm
My implementation is as follows:
## from HIPR2 web site ## [0,0,0] ## [x,1,x] ## [1,1,1] struct1 = numarray.array( [[0, 0, 0], [0, 1, 0], [1, 1, 1]]) struct2 = numarray.array( [[1, 1, 1], [0, 0, 0], [0, 0, 0]])
## [x,0,0] ## [1,1,0] ## [x,1,x] struct3 = numarray.array( [[0, 0, 0], [1, 1, 0], [0, 1, 0]]) struct4 = numarray.array( [[0, 1, 1], [0, 0, 1], [0, 0, 0]])
b = [] for i in range(4): temp = ND.binary_hit_or_miss(a, struct1, struct2) b.append(temp) temp = ND.binary_hit_or_miss(a, struct3, struct4) b.append(temp)
struct1 = ND.rotate(struct1, 90) struct2 = ND.rotate(struct2, 90) struct3 = ND.rotate(struct3, 90) struct4 = ND.rotate(struct4, 90)
result = b[0] for i in range(7): result = numarray.logical_or(result, b[i+1])
result = a - result
Bob
------------------------------------------------------- SF email is sponsored by - The IT Product Guide Read honest & candid reviews on hundreds of IT Products from real users. Discover which products truly live up to the hype. Start reading now. http://productguide.itmanagersjournal.com/ _______________________________________________ Numpy-discussion mailing list Numpy-discussion@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/numpy-discussion

Peter Verveer wrote:
Hi Bob,
I noticed two problems:
1) you construct rotations of your structures with the nd_image.rotate function. That will not work properly because this function uses spline interpolation, which not necessarily produces exact results. In this case you need to use another, exact rotation method, see my implementation below.
2) I think (correct me if I am wrong) that the application of the 8 structures is sequential, not parallel as you do it.
Below I give my implementation, which does not produce the exact same result as shown on the webpage you refer to, although the result seems to be a proper skeleton. This may be because the order in which the structures are applied matters (I think). Could you maybe test that by permutating the order in which the structures are applied? I would be interested if this is true and if one can get the same result as on the webpage by finding the right sequence...
Peter, Thanks much for getting back to me on this. Your sample code was very helpful! :-) I rewrote my function based on yours and I'm getting the same answer. So far I haven't been able to figure out why is it different from the web site and so far I haven't tried changing the order of the structuring elements. I'll try tomorrow. I'll let you know if I come up with anything new. Regards, Bob

Peter Verveer wrote:
Hi Bob,
Below I give my implementation, which does not produce the exact same result as shown on the webpage you refer to, although the result seems to be a proper skeleton. This may be because the order in which the structures are applied matters (I think). Could you maybe test that by permutating the order in which the structures are applied? I would be interested if this is true and if one can get the same result as on the webpage by finding the right sequence...
Peter, I'm finally able to get back with some answers; unfortunately, for a number of reasons my time spent on this is quite fragmented. First, to answer your question about changing the order in which structures are applied. It turns out it does matter. I tried rotating the structures clockwise and counter-clockwise, pre-rotating the structure before doing the four rotations, and I permutating the order, and in some of those cases the results are different, although usually only slightly different - a couple pixels here, a few there. Second, no matter what I tried, I could not duplicate the picture in the webpage. Third, besides the test image (off the webpage) I also tested a skeleton function on few other images using several packages available to me, including an old Matrox MIL, ImageJ, and Matlab. Each one of them produced different results. I'm not sure that one is more correct than another, they're probably all correct. In general the nd_image skeleton produces results similar to Matlab. Peter, would you be interested in adding a few binary morphology functions to nd_image? So far I have working versions of borderkill, borderkeep, reconstruct, thinning, thickening, skeleton, skiz, and convex hull. Even though they were all produced with just what's there right now (erosion, dilation, and hit-or-miss) and a few numarray functions, it took a long time to figure out and could be helpful to the next guy. I'd be happy to send you what I got and/or post it. Regards, Bob

Hi Bob, Thanks for using the nd_image code. It is helpful to get some user feedback. I think I did not tell you in my last email, but your last questions actually allowed me to find a few minor bugs and fix them...
First, to answer your question about changing the order in which structures are applied. It turns out it does matter. I tried rotating the structures clockwise and counter-clockwise, pre-rotating the structure before doing the four rotations, and I permutating the order, and in some of those cases the results are different, although usually only slightly different - a couple pixels here, a few there.
This seems reasonable to me, I would expect that the order matters.
Second, no matter what I tried, I could not duplicate the picture in the webpage.
Third, besides the test image (off the webpage) I also tested a skeleton function on few other images using several packages available to me, including an old Matrox MIL, ImageJ, and Matlab. Each one of them produced different results. I'm not sure that one is more correct than another, they're probably all correct. In general the nd_image skeleton produces results similar to Matlab.
It seems then that there is no accepted single solution for the skeleton, so I guess the code from nd_image is okay then.
Peter, would you be interested in adding a few binary morphology functions to nd_image? So far I have working versions of borderkill, borderkeep, reconstruct, thinning, thickening, skeleton, skiz, and convex hull. Even though they were all produced with just what's there right now (erosion, dilation, and hit-or-miss) and a few numarray functions, it took a long time to figure out and could be helpful to the next guy. I'd be happy to send you what I got and/or post it.
One issue is that nd_image functions are supposed to be generic and work in any dimension. So I kept the binary morphology low-level on purpose, so far. But on the other hand, I don't see why we could not add some stuff even if it only works in 2D (which I assume is the case with your code.) Why don't you send me what you have and I have a look in the next weeks? Cheers, Peter
participants (2)
-
Bob Klimek
-
Peter Verveer