Discussion:
Medial Axis Transform?
Stephen DiVerdi
2006-04-23 20:07:51 UTC
Permalink
Moving on, I'm now working on thinning / skeletonizing a binary image.
I'm surprised to find that OpenCV doesn't already have support for this
type of operation, and the comments on the mailing list archive seem to
say nothing more than "use erode" which isn't really a satisfactory answer
- cvErode definitely does not have the same behavior as thinning.

Here are the two pages I've been looking at for information on how to
impelement this technique:

http://www.cee.hw.ac.uk/hipr/html/thin.html
http://www.cee.hw.ac.uk/hipr/html/skeleton.html

As the first page shows, to do thinning using a morphology style operator,
you need hit-and-miss morphology support, which OpenCV doesn't have. I'd
also prefer not to use an iterative algorithm, so I decided to go with the
second option, the Medial Axis Transform. cvDistTransform does the first
step of the work for me, but once I have a distance image, I need to
reliably extract the ridges from that image, and that's where I'm having
trouble.

My thought was that since I'm looking for ridges, the negative values of a
laplacian filter would do the trick, which is not altogether incorrect,
but does lend itself to noise / fragmented edges. I haven't been able to
get satisfactory results with it. Does anyone have any suggestions on
what might be a better way to proceed here? Either with extracting ridges
from the distance transform, or another approach that OpenCV does actually
support that I missed?

Thanks!

-stephen diverdi
-***@cs.ucsb.edu


Change settings: http://www.yahoogroups.com/mygroups, select
Get Emails (get all posts)
Daily Digest (one summary email per day)
Read on the web (read posts on the web only)Or Unsubscribe by mailing OpenCV-***@yahoogroups.com
Ricardo
2006-04-23 21:41:34 UTC
Permalink
Yours seem a good idea.

1)
Perhaps just a silly suggestion, but have you tried looking "under the
hood" of one of Matlab's similar functions?

2)
See if it helps to look at the HTML help of
cvPreCornerDetect
cvCornerHarris
cvGoodFeaturesToTrack

as thet approach the subject of local maxima or maxima supression.
Also, see if the code of those functions rings a bell.

3)
Look for a prebuilt skeletonizing function in c/c++. I know there's at
least one out there, just don't recall where...

Cheers!
Post by Stephen DiVerdi
Moving on, I'm now working on thinning / skeletonizing a binary image.
I'm surprised to find that OpenCV doesn't already have support for this
type of operation, and the comments on the mailing list archive seem to
say nothing more than "use erode" which isn't really a satisfactory answer
- cvErode definitely does not have the same behavior as thinning.
Here are the two pages I've been looking at for information on how to
http://www.cee.hw.ac.uk/hipr/html/thin.html
http://www.cee.hw.ac.uk/hipr/html/skeleton.html
As the first page shows, to do thinning using a morphology style operator,
you need hit-and-miss morphology support, which OpenCV doesn't have.
I'd
Post by Stephen DiVerdi
also prefer not to use an iterative algorithm, so I decided to go with the
second option, the Medial Axis Transform. cvDistTransform does the first
step of the work for me, but once I have a distance image, I need to
reliably extract the ridges from that image, and that's where I'm having
trouble.
My thought was that since I'm looking for ridges, the negative
values of a
Post by Stephen DiVerdi
laplacian filter would do the trick, which is not altogether incorrect,
but does lend itself to noise / fragmented edges. I haven't been able to
get satisfactory results with it. Does anyone have any suggestions on
what might be a better way to proceed here? Either with extracting ridges
from the distance transform, or another approach that OpenCV does actually
support that I missed?
Thanks!
-stephen diverdi
Change settings: http://www.yahoogroups.com/mygroups, select
Get Emails (get all posts)
Daily Digest (one summary email per day)
Read on the web (read posts on the web only)Or Unsubscribe by mailing OpenCV-***@yahoogroups.com
Stephen DiVerdi
2006-04-23 22:29:34 UTC
Permalink
Thanks for the quick reply.
Post by Ricardo
1)
Perhaps just a silly suggestion, but have you tried looking "under the
hood" of one of Matlab's similar functions?
No - I don't have Matlab, nor do I know how to use Matlab. =/ In general
my area is computer graphics, but lately I've been doing a bit more vision
work. I guess it's coming on time to learn how to use Matlab, eh?
Post by Ricardo
2)
See if it helps to look at the HTML help of
cvPreCornerDetect
cvCornerHarris
cvGoodFeaturesToTrack
as thet approach the subject of local maxima or maxima supression.
Yeah, I've been using these functions over the past week or so. I even
already tried the documentation's recommendation for local maxima
retrieval, but the problem is the ridges of a distance transform are _not_
local maxima. If you think about it, any pixel on a ridge in a distance
transform will have one other pixel in its neighborhood that's greater
than it. That's what confounds the problem a bit. =)
Post by Ricardo
Also, see if the code of those functions rings a bell.
I'm not sure what you mean here...
Post by Ricardo
3)
Look for a prebuilt skeletonizing function in c/c++. I know there's at
least one out there, just don't recall where...
I've found some other libraries that do contain skeletonizing, but I'm
reluctant to use them for a couple reasons:

1) I'd rather not have to go through the process of taking an IplImage,
converting it to the other library's image type, running their code and
then converting back. That's a lot of wasted cycles, and I'm looking for
realtime performance here.

2) I'm still a little in disbelief that OpenCV doesn't have support for
this functionality, so I figured there must be some trick that the
standard functions allow (like the local maxima retrieval discussed for
cvPreCornerDetect) that I'm not seeing. I mean, this is a pretty basic
function for an image processing library, isn't it? I'm similarly
surprised at the morphological function support in OpenCV, since erode and
dilate don't seem to implement the standard form of those operations
(finding max or min in the kernel, rather than just doing kernel
matching), and there's no hit-and-miss kernel support.

3) I could even program my own function to do this, as I understand the
algorithms involved and have written lots of code like this before. With
this project though I decided it was finally time to stop reinventing the
wheel and learn OpenCV in earnest. In general, I'd say it's good
philosophy to defer to a carefully written expert library that will have a
lot of performance considerations that I wouldn't have implemented myself
(like the 4-byte aligned images and inplace morphological operations).
So, if there's anyway to support this sort of operation in OpenCV, I'd
really rather use that. Of course, if no support exists, I don't have an
option...


Also, here you can see the results I'm currently getting:

Loading Image...
Loading Image...
Loading Image...

The skeleton comes from this code:

cvDistTransform( threshold, distance, CV_DIST_L2, CV_DIST_MASK_5, NULL, NULL );
cvLaplace( distance, laplace, 3 );
cvCmpS( laplace, -3, skeleton, CV_CMP_LE );

However, the problems are obvious - the threshold is a single component,
but the skeleton is not connected, and there's a lot of noisey pixels
around the boundary.


Thanks again,

-stephen diverdi
-***@cs.ucsb.edu


Change settings: http://www.yahoogroups.com/mygroups, select
Get Emails (get all posts)
Daily Digest (one summary email per day)
Read on the web (read posts on the web only)Or Unsubscribe by mailing OpenCV-***@yahoogroups.com
Stephen DiVerdi
2006-04-23 23:18:15 UTC
Permalink
The idea is: instead of working with 3 channels (R, G and B) you would
only work with one (H). OpenCV offers some functions to convert
between color spaces (something like cv convert color). In this case
you would use a flag like BGR2HSV (I think, since opencv reverses the
order of the channels). You would then use a function to separate the
HSV channels into H (something like cv split). Then you would use your
freshly modified function, and pass the H image instead of the RGB.
Hmm, this 'solution' doesn't really solve the problem. I recently did
some work with hue images and had similar difficulty.

For one thing, the floodfill function can operate on a single channel
image, so all you'd need to do to try this is to

IplImage *rgb, hsv, hue;

// convert to hsv
cvCvtColor( rgb, hsv, CV_RGB2HSV );

// extract hue channel
cvSetImageCOI( hsv, 1 );
cvSetImageROI( hsv, cvRect( 0, 0, hsv->width, hsv->height ) );
cvCopy( hsv, hue );

// flood fill on the hue image
cvFloodfFill( hue, ... );

There's one big problem with this approach though, and that is the
periodic nature of the hue value - pixels that have very close hues can
have very different hue values in the red region, as red pixels will have
a hue near 0 and magenta pixels will have a hue near 1. Direct use of the
hue channel as an intensity channel introduces a tremendous number of new
apparent edges from this effeect, and also from the fact that gray
and near-gray pixels have almost random hue values. Edge detection,
floodfilling, etc. are mostly useless on straight hue->gray images.

In my experimentation on this area, I thought about what I wanted to do,
and the fundamental issue came down to the fact that operations that work
on a single channel use intensity images which do not reflect changes in
chrominance (like you'd expect a hue image to do), so when you look at an
edge detecter output for an RGB image, you can easily be disappointed that
hue-changes that make obvious _perceptual_ edges are not detected.

I had a few ideas how to address this. One approach was to use the
results of a paper from SIGGRAPH 2005, "Color2Gray: Salience-Preserving
Color Removal" by Gooch et al.,
http://www.cs.northwestern.edu/~ago820/color2gray/ The purpose of their
technique is to construct a gray image that contains intensity edges that
reflect both intensity _and_ chrominance edges in the original RGB image.
I made a function in OpenCV style that I could insert into my filter
testing program, but the problem with color2gray is that it's a global,
pairwise pixel operation, so it scales very poorly. I experimented a bit
with a local version of the algorithm, but had a hard time getting
improved results.

That led me to another idea though, which is to allow one-channel
functions to operate on n-channel images by allowing the user to specify
an appropriate distance function that would take two pixels and compute a
similarity measure (the trivial example taking two single channel pixels
and returning the difference). Then a function like cvFloodFill (or
cvCanny or something else) could operate on RGB images, and the user could
provide a perceptual distance function instead (for example, one that
computes euclidian distance in the CIElab colorspace). That might work
for simple algorithms like cvFloodFill, but a lot of algorithms in OpenCV
don't explicitly make use of a distance function, as they formulate the
algorithms with matrices for example. How to amend these functions to use
a different distance metric becomes more an issue of constructing a group
that has the same operator properties as the real numbers (if that's even
really possible), but my abstract algebra is awfully rusty and I wasn't up
to the task.

Anyway, if anyone would like to talk more about the possibilities here,
I'm game.

-stephen diverdi
-***@cs.ucsb.edu


Change settings: http://www.yahoogroups.com/mygroups, select
Get Emails (get all posts)
Daily Digest (one summary email per day)
Read on the web (read posts on the web only)Or Unsubscribe by mailing OpenCV-***@yahoogroups.com
Ricardo
2006-04-23 23:39:56 UTC
Permalink
Great answer!!
I really forgot that issue with the reds in the hue channel... My bad! :P
And once again, luminance is sometimes more used than crominance, thus
not yielding results that are perceptually coherent, as you said.

I guess it's a question of after having a coarse prototype, for a
flood fill function, you just start adding stuff to it. That, or
defining beforehand how complex you want your function to be.

I will have a look on that paper you mentioned.

Also! Just recalled. Has anyone looked to the L*a*b* colorspace? I
understand, from people who used it, that it is more robust than HSV.
And another thing that just occured! Has anyone considered using a
region grow algorithm after an initial coarse flood fill?

cheers!
Post by Stephen DiVerdi
The idea is: instead of working with 3 channels (R, G and B) you would
only work with one (H). OpenCV offers some functions to convert
between color spaces (something like cv convert color). In this case
you would use a flag like BGR2HSV (I think, since opencv reverses the
order of the channels). You would then use a function to separate the
HSV channels into H (something like cv split). Then you would use your
freshly modified function, and pass the H image instead of the RGB.
Hmm, this 'solution' doesn't really solve the problem. I recently did
some work with hue images and had similar difficulty.
For one thing, the floodfill function can operate on a single channel
image, so all you'd need to do to try this is to
IplImage *rgb, hsv, hue;
// convert to hsv
cvCvtColor( rgb, hsv, CV_RGB2HSV );
// extract hue channel
cvSetImageCOI( hsv, 1 );
cvSetImageROI( hsv, cvRect( 0, 0, hsv->width, hsv->height ) );
cvCopy( hsv, hue );
// flood fill on the hue image
cvFloodfFill( hue, ... );
There's one big problem with this approach though, and that is the
periodic nature of the hue value - pixels that have very close hues can
have very different hue values in the red region, as red pixels will have
a hue near 0 and magenta pixels will have a hue near 1. Direct use of the
hue channel as an intensity channel introduces a tremendous number of new
apparent edges from this effeect, and also from the fact that gray
and near-gray pixels have almost random hue values. Edge detection,
floodfilling, etc. are mostly useless on straight hue->gray images.
In my experimentation on this area, I thought about what I wanted to do,
and the fundamental issue came down to the fact that operations that work
on a single channel use intensity images which do not reflect
changes in
Post by Stephen DiVerdi
chrominance (like you'd expect a hue image to do), so when you look at an
edge detecter output for an RGB image, you can easily be
disappointed that
Post by Stephen DiVerdi
hue-changes that make obvious _perceptual_ edges are not detected.
I had a few ideas how to address this. One approach was to use the
results of a paper from SIGGRAPH 2005, "Color2Gray: Salience-Preserving
Color Removal" by Gooch et al.,
http://www.cs.northwestern.edu/~ago820/color2gray/ The purpose of their
technique is to construct a gray image that contains intensity edges that
reflect both intensity _and_ chrominance edges in the original RGB image.
I made a function in OpenCV style that I could insert into my filter
testing program, but the problem with color2gray is that it's a global,
pairwise pixel operation, so it scales very poorly. I experimented a bit
with a local version of the algorithm, but had a hard time getting
improved results.
That led me to another idea though, which is to allow one-channel
functions to operate on n-channel images by allowing the user to specify
an appropriate distance function that would take two pixels and compute a
similarity measure (the trivial example taking two single channel pixels
and returning the difference). Then a function like cvFloodFill (or
cvCanny or something else) could operate on RGB images, and the user could
provide a perceptual distance function instead (for example, one that
computes euclidian distance in the CIElab colorspace). That might work
for simple algorithms like cvFloodFill, but a lot of algorithms in OpenCV
don't explicitly make use of a distance function, as they formulate the
algorithms with matrices for example. How to amend these functions to use
a different distance metric becomes more an issue of constructing a group
that has the same operator properties as the real numbers (if that's even
really possible), but my abstract algebra is awfully rusty and I wasn't up
to the task.
Anyway, if anyone would like to talk more about the possibilities here,
I'm game.
-stephen diverdi
Change settings: http://www.yahoogroups.com/mygroups, select
Get Emails (get all posts)
Daily Digest (one summary email per day)
Read on the web (read posts on the web only)Or Unsubscribe by mailing OpenCV-***@yahoogroups.com
Stephen DiVerdi
2006-04-24 02:51:22 UTC
Permalink
I guess it's a question of after having a coarse prototype, for a flood
fill function, you just start adding stuff to it. That, or defining
beforehand how complex you want your function to be.
With the right API, such a function can be very general-purpose. Take a
look at STL container classes for example. I have my own floodfill
function that takes a similar approach, but unfortunately I'm not at
liberty to share the source. The prototype looks like this though:

typedef bool ( *check_func )( unsigned char *, int, int, void * );
typedef void ( *process_func )( unsigned char *, int, int, void * );
void flood ( unsigned char *img, int seedx, int seedy, void *data,
check_func check, process_func process );

With this function, the user can specify how a pixel is checked (default
is to see if it's within a threshold from the seed pixel) and how it's
processed if it passes the check (default is to set the pixel to the
target color). Because of how the function is written, it's trivial to
modify it to check for difference in hue vs. difference in intensity, or
to do any number of other things.

The tradeoff is usually performance, as it's harder for a compiler to
optimize a function like this. Some libraries get around this with
templates and generic programming, like Blitz++ Numerical Library, but
it's pretty complicated stuff.
Also! Just recalled. Has anyone looked to the L*a*b* colorspace? I
understand, from people who used it, that it is more robust than HSV.
Yeah, I mentioned CIELab in my last message. It doesn't solve the problem
though, as you need a function that can then operate on the non-RGB
values. Naeem, seems like your only options in this case are to modify
cvFloodFill, write your own, or find another library. =/


-stephen diverdi
-***@cs.ucsb.edu


Change settings: http://www.yahoogroups.com/mygroups, select
Get Emails (get all posts)
Daily Digest (one summary email per day)
Read on the web (read posts on the web only)Or Unsubscribe by mailing OpenCV-***@yahoogroups.com
Ricardo
2006-04-24 07:44:16 UTC
Permalink
Post by Stephen DiVerdi
I guess it's a question of after having a coarse prototype, for a flood
fill function, you just start adding stuff to it. That, or defining
beforehand how complex you want your function to be.
With the right API, such a function can be very general-purpose.
Take a
Post by Stephen DiVerdi
look at STL container classes for example. I have my own floodfill
function that takes a similar approach, but unfortunately I'm not at
typedef bool ( *check_func )( unsigned char *, int, int, void * );
typedef void ( *process_func )( unsigned char *, int, int, void * );
void flood ( unsigned char *img, int seedx, int seedy, void *data,
check_func check, process_func process );
With this function, the user can specify how a pixel is checked (default
is to see if it's within a threshold from the seed pixel) and how it's
processed if it passes the check (default is to set the pixel to the
target color). Because of how the function is written, it's trivial to
modify it to check for difference in hue vs. difference in
intensity, or
Post by Stephen DiVerdi
to do any number of other things.
The tradeoff is usually performance, as it's harder for a compiler to
optimize a function like this. Some libraries get around this with
templates and generic programming, like Blitz++ Numerical Library, but
it's pretty complicated stuff.
-- Ok... now you're ahead of me on this one... I will take your word
for it. :P
Post by Stephen DiVerdi
Also! Just recalled. Has anyone looked to the L*a*b* colorspace? I
understand, from people who used it, that it is more robust than HSV.
Yeah, I mentioned CIELab in my last message. It doesn't solve the problem
though, as you need a function that can then operate on the non-RGB
values. Naeem, seems like your only options in this case are to modify
cvFloodFill, write your own, or find another library. =/
--Again, when I read diagonally, I miss details. Guess I didn't see
your refence to cielab...
About your tip to Naeem: I told you so! ;) :P

cheers!






Change settings: http://www.yahoogroups.com/mygroups, select
Get Emails (get all posts)
Daily Digest (one summary email per day)
Read on the web (read posts on the web only)Or Unsubscribe by mailing OpenCV-***@yahoogroups.com
Ricardo
2006-04-23 23:28:41 UTC
Permalink
Post by Stephen DiVerdi
No - I don't have Matlab, nor do I know how to use Matlab. =/ In general
my area is computer graphics, but lately I've been doing a bit more vision
work. I guess it's coming on time to learn how to use Matlab, eh?
-- Perhaps, in your spare time... I mean, the language is pretty much
the same, appart from the mathematic operators.
Post by Stephen DiVerdi
Yeah, I've been using these functions over the past week or so. I even
already tried the documentation's recommendation for local maxima
retrieval, but the problem is the ridges of a distance transform are _not_
local maxima. If you think about it, any pixel on a ridge in a distance
transform will have one other pixel in its neighborhood that's greater
than it. That's what confounds the problem a bit. =)
-- Ooopsss! Guess you're correct. I was thinking perpendicular to the
ridge, not along it... so I guess you won't have many maxima that way. :P
Post by Stephen DiVerdi
Post by Ricardo
Also, see if the code of those functions rings a bell.
I'm not sure what you mean here...
-- I meant: go see the opencv functions I mentioned and see if there's
any line of code that might be helpful.
Post by Stephen DiVerdi
1) I'd rather not have to go through the process of taking an IplImage,
converting it to the other library's image type, running their code and
then converting back. That's a lot of wasted cycles, and I'm
looking for
Post by Stephen DiVerdi
realtime performance here.
-- So, just copy the code and adapt to work with opencv. :)
Post by Stephen DiVerdi
2) I'm still a little in disbelief that OpenCV doesn't have support for
this functionality, so I figured there must be some trick that the
standard functions allow (like the local maxima retrieval discussed for
cvPreCornerDetect) that I'm not seeing. I mean, this is a pretty basic
function for an image processing library, isn't it? I'm similarly
surprised at the morphological function support in OpenCV, since erode and
dilate don't seem to implement the standard form of those operations
(finding max or min in the kernel, rather than just doing kernel
matching), and there's no hit-and-miss kernel support.
-- Disbelieve away!! I was shocked not to find a connected components
and labelling function! I had to use one someone had already built for
opencv compatibility.
Post by Stephen DiVerdi
3) I could even program my own function to do this, as I understand the
algorithms involved and have written lots of code like this before.
With
Post by Stephen DiVerdi
this project though I decided it was finally time to stop
reinventing the
Post by Stephen DiVerdi
wheel and learn OpenCV in earnest. In general, I'd say it's good
philosophy to defer to a carefully written expert library that will have a
lot of performance considerations that I wouldn't have implemented myself
(like the 4-byte aligned images and inplace morphological operations).
So, if there's anyway to support this sort of operation in OpenCV, I'd
really rather use that. Of course, if no support exists, I don't have an
option...
-- You're not reinventing much of a wheel if you look to code already
made and adapt to your case. This spares you more time than a personal
endeavour looking for that piece of opencv code that should exist. :)
Post by Stephen DiVerdi
http://www.cs.ucsb.edu/~sdiverdi/pics/phone.png
http://www.cs.ucsb.edu/~sdiverdi/pics/threshold.png
http://www.cs.ucsb.edu/~sdiverdi/pics/skeleton.png
-- These results seem pretty ok to me. I would perhaps suggest that
you test it with the same images as the tutorial pages you provided in
previous posts (I apologize if you're already doing this).
Post by Stephen DiVerdi
cvDistTransform( threshold, distance, CV_DIST_L2, CV_DIST_MASK_5, NULL, NULL );
cvLaplace( distance, laplace, 3 );
cvCmpS( laplace, -3, skeleton, CV_CMP_LE );
However, the problems are obvious - the threshold is a single
component,
Post by Stephen DiVerdi
but the skeleton is not connected, and there's a lot of noisey pixels
around the boundary.
-- Now you've lost me... I'm not that proficient with skeletons, dist.
transform and lablace.






Change settings: http://www.yahoogroups.com/mygroups, select
Get Emails (get all posts)
Daily Digest (one summary email per day)
Read on the web (read posts on the web only)Or Unsubscribe by mailing OpenCV-***@yahoogroups.com
Ricardo
2006-06-28 11:16:12 UTC
Permalink
Sometime ago I made this comment, which now I realise is not accurate.
OpenCV does have a connected components and labelling function. It's
called cvFloodFill, I've used it, it works. May be a bit hard to start
with, but the demo in the samples directory helps. It also helped me
to do some binary images with the letters I M B W hand drawn in it,
just to realise it does connect those pixels and groups them into the
same region without any problem (some simpler algorithms have problems).

I was not as lucky working with 3 and 4 level b/w images, so I stick
to the binary labelling problem.
Post by Ricardo
I was shocked not to find a connected components
and labelling function! I had to use one someone had already built for
opencv compatibility.
------------------------ Yahoo! Groups Sponsor --------------------~-->
Great things are happening at Yahoo! Groups. See the new email design.
http://us.click.yahoo.com/TISQkA/hOaOAA/yQLSAA/W4wwlB/TM
--------------------------------------------------------------------~->

Change settings: http://www.yahoogroups.com/mygroups, select
Get Emails (get all posts)
Daily Digest (one summary email per day)
Read on the web (read posts on the web only)Or Unsubscribe by mailing OpenCV-***@yahoogroups.com
Stephen DiVerdi
2006-04-24 02:25:53 UTC
Permalink
Post by Ricardo
-- So, just copy the code and adapt to work with opencv. :)
-- You're not reinventing much of a wheel if you look to code already
made and adapt to your case. This spares you more time than a personal
endeavour looking for that piece of opencv code that should exist. :)
I think we're experiencing a conflict of philosophies here. Time spent
looking for the established best way to do something is not time wasted,
and in the overwhelming majority of cases, saves tremendous amounts of
effort. It certainly should not be the first or even second step to
reimplement an established algorithm.

I guess since OpenCV doesn't support the operations I need, I _will_ go
ahead and look into my own implementation / integrating another library's
implementation, but I think it's safe to say that this is a less than
ideal solution - the amount of effort necessary is much greater.
Post by Ricardo
-- Disbelieve away!! I was shocked not to find a connected components
and labelling function! I had to use one someone had already built for
opencv compatibility.
Well, this seems to suggest that there's some significant functionality
missing from OpenCV. I'm new to this community, but I've read what I can
find in the archives and on the web. I haven't seen much though about the
overriding philosophy or goals of the OpenCV project, or how it's managed
/ who it's developed by / how to contribute. However, it seems like there
are common questions on this list about code for functionality that people
expect in a general purpose computer vision / image processing library,
which makes me think that maybe some of these functions should be added.

I know how development of an open source project goes, and so I'm
certainly not trying to say "hey devs, get in gear!" I recognize the
tremendous amount of work that's gone in here - OpenCV is a great library,
and I've been really surprised by the depth in its capabilities. But it
does also surprise me with what's missing and how things are implemented.

I'm more than happy to pony up and help with development myself too. Now
that I see that thinning / skeletonizing is missing from OpenCV, I will
offer up my solution to the mailing list. I'm also happy to share any of
the other code I've worked on (as I recently mailed about the hough
transform difficulties, or the color2gray code I mentioned in another
thread).
Post by Ricardo
Post by Stephen DiVerdi
http://www.cs.ucsb.edu/~sdiverdi/pics/phone.png
http://www.cs.ucsb.edu/~sdiverdi/pics/threshold.png
http://www.cs.ucsb.edu/~sdiverdi/pics/skeleton.png
-- These results seem pretty ok to me. I would perhaps suggest that
you test it with the same images as the tutorial pages you provided in
previous posts (I apologize if you're already doing this).
Yeah, the phone input image comes from the tutorial I posted, and you can
see their skeleton results here

Loading Image...

(for a poorly thresholded image, but the cleanness of the results is what
i'm interested in) Notice that since the threshold is connected and so is
the skeleton, which is really the important property for my purposes.


Thanks,

-stephen diverdi
-***@cs.ucsb.edu


Change settings: http://www.yahoogroups.com/mygroups, select
Get Emails (get all posts)
Daily Digest (one summary email per day)
Read on the web (read posts on the web only)Or Unsubscribe by mailing OpenCV-***@yahoogroups.com
Ricardo
2006-04-24 07:38:01 UTC
Permalink
Post by Stephen DiVerdi
I think we're experiencing a conflict of philosophies here. Time spent
looking for the established best way to do something is not time wasted,
and in the overwhelming majority of cases, saves tremendous amounts of
effort. It certainly should not be the first or even second step to
reimplement an established algorithm.
I guess since OpenCV doesn't support the operations I need, I _will_ go
ahead and look into my own implementation / integrating another library's
implementation, but I think it's safe to say that this is a less than
ideal solution - the amount of effort necessary is much greater.
-- "conflict of philosophies": Yes and no. It's always better to have
opencv already dealing with aspect A or B. If it's not done in opencv,
I don't jump right away to doing my own code. I'm sorry but I think
that's suicide! Not because I wouldn't like it or think it would be
better, but just because in a project I can't dedicate 1 or 2 weeks to
develop something from scratch if it's already implemented somewhere
else and I didn't search for it. On the other hand, I can't search ad
eternum, and most times the ready-to-use code is not opencv compatible
and must be adapted. In my case, I had to do an rgb2lab conversion
because I wasn't pleased with the one opencv made. I already had the
programme made in matlab language, so it was pretty much "just
translating". Wrong! I ended up loosing 3 weeks instead of 1 I had for
this task, ended up doing 3 variations of the function (based on CIE
and ICC standards, which no-one seemed to implement ever twice the
same way) and quit after 3 weeks, looking under matlab's hood and
wikipedia and official standards printouts. Point being: there was a
better way. :) For that paticular task, I could sacrifice some aspects
and use a not so robust function, and then compensate for that later,
with some others. So, perhaps I just added confusion, but I guess the
"conflict of philosophies" is more of a case of evaluating how much
time you're willing to spend on a task, and I'm just not willing on
spending more than necessary.
Post by Stephen DiVerdi
Well, this seems to suggest that there's some significant functionality
missing from OpenCV. I'm new to this community, but I've read what I can
find in the archives and on the web. I haven't seen much though about the
overriding philosophy or goals of the OpenCV project, or how it's managed
/ who it's developed by / how to contribute. However, it seems like there
are common questions on this list about code for functionality that people
expect in a general purpose computer vision / image processing library,
which makes me think that maybe some of these functions should be added.
--I agree totally. Perhaps in release 1.0.0-NON-BETA! :P
Or perhaps in the cvs version (read about it, but never used it).
Or maybe the cvaux thing (ditto).
It must be hard to manage a project like this, and there must be many
people contributing with similar functions, but all different in a
way, and most not complying with the standards of opencv dev. team.
And then there's probably too much people posting a cvAddOneAndOne
function. :P
Anyway, I think there's a way for anyone to jump in as a developer. At
least in the linux version they tell you to download a whole bunch of
extra stuff if you want to jump in as a dev.
Post by Stephen DiVerdi
I know how development of an open source project goes, and so I'm
certainly not trying to say "hey devs, get in gear!" I recognize the
tremendous amount of work that's gone in here - OpenCV is a great library,
and I've been really surprised by the depth in its capabilities.
But it
Post by Stephen DiVerdi
does also surprise me with what's missing and how things are
implemented.
--There are somethings you won't find implemented anywhere else...
Perhaps a question of opencv dev's own needs and priorities?
Post by Stephen DiVerdi
I'm more than happy to pony up and help with development myself too.
Now
Post by Stephen DiVerdi
that I see that thinning / skeletonizing is missing from OpenCV, I will
offer up my solution to the mailing list. I'm also happy to share any of
the other code I've worked on (as I recently mailed about the hough
transform difficulties, or the color2gray code I mentioned in another
thread).
--I think you would be interested in checking that "jump in as an
opencv developer" thing. :)
Post by Stephen DiVerdi
Yeah, the phone input image comes from the tutorial I posted, and you can
see their skeleton results here
http://www.cee.hw.ac.uk/hipr/images/phn1ske1.gif
(for a poorly thresholded image, but the cleanness of the results is what
i'm interested in) Notice that since the threshold is connected and so is
the skeleton, which is really the important property for my purposes.
--Ok, that's what happen when I answer in a hurry: I didn't bother
looking for "their" results. I have to say, appart from some noise
dots you have in your skeleton, it looks far better to me than
"theirs". I guess we'll be seeing your code soon hum? ;)

cheers!





Change settings: http://www.yahoogroups.com/mygroups, select
Get Emails (get all posts)
Daily Digest (one summary email per day)
Read on the web (read posts on the web only)Or Unsubscribe by mailing OpenCV-***@yahoogroups.com
David Johansen
2008-01-07 23:24:06 UTC
Permalink
Post by Stephen DiVerdi
Moving on, I'm now working on thinning / skeletonizing a binary image.
I'm surprised to find that OpenCV doesn't already have support for this
type of operation, and the comments on the mailing list archive seem to
say nothing more than "use erode" which isn't really a satisfactory answer
- cvErode definitely does not have the same behavior as thinning.
Here are the two pages I've been looking at for information on how to
http://www.cee.hw.ac.uk/hipr/html/thin.html
http://www.cee.hw.ac.uk/hipr/html/skeleton.html
As the first page shows, to do thinning using a morphology style operator,
you need hit-and-miss morphology support, which OpenCV doesn't have.
I'd
Post by Stephen DiVerdi
also prefer not to use an iterative algorithm, so I decided to go with the
second option, the Medial Axis Transform. cvDistTransform does the first
step of the work for me, but once I have a distance image, I need to
reliably extract the ridges from that image, and that's where I'm having
trouble.
My thought was that since I'm looking for ridges, the negative
values of a
Post by Stephen DiVerdi
laplacian filter would do the trick, which is not altogether incorrect,
but does lend itself to noise / fragmented edges. I haven't been able to
get satisfactory results with it. Does anyone have any suggestions on
what might be a better way to proceed here? Either with extracting ridges
from the distance transform, or another approach that OpenCV does actually
support that I missed?
Thanks!
-stephen diverdi
Did you ever get an implementation of this working?
Dave



Change settings: http://www.yahoogroups.com/mygroups, select
Get Emails (get all posts)
Daily Digest (one summary email per day)
Read on the web (read posts on the web only)Or Unsubscribe by mailing OpenCV-***@yahoogroups.com
Continue reading on narkive:
Search results for 'Medial Axis Transform?' (Questions and Answers)
6
replies
Name the movements permitted by the elbow joint?
started 2006-03-13 12:34:40 UTC
biology
Loading...