head	1.3;
access;
symbols;
locks; strict;
comment	@// @;


1.3
date	94.10.14.06.16.22;	author rjj;	state Exp;
branches;
next	1.2;

1.2
date	94.08.27.18.04.08;	author rjj;	state Exp;
branches;
next	1.1;

1.1
date	94.08.09.03.07.12;	author rjj;	state Exp;
branches;
next	;


desc
@Initial implementation of the Medial Axis Transform.
Note the the inverse is not yet implemented.
@


1.3
log
@Added algorithm name to header.  Made spelling and style changes.
Added support for the inverse_medial_axis() function.
@
text
@// mat.c                Section: 4.4  Medial Axis Transform (MAT)
//      Copyright 1994, Center for Computer Vision and Visualization,
//      University of Florida.  All rights reserved.
// Medial Axis Transform

#include "Nbh.h"
#include "mat.h"


IA_Image<IA_Point<int>,int>
medial_axis( const IA_Image<IA_Point<int>,IA_Bit> & aImage,
	     const IA_Set<IA_Point<int> > & ball,
	     unsigned int & count ) {

    IA_Neighborhood<IA_Point<int>,IA_Point<int> >
	m_nbhd( aImage.domain().dim(), ball );

    IA_Image<IA_Point<int>,int>  m( aImage.domain(), 0 );

    IA_Image<IA_Point<int>,IA_Bit>
	a = aImage,
	b( aImage.domain(), IA_Bit(0) );

    count = 0;
    while ( a != IA_Bit( 0 ) ) {
	a = min( a, m_nbhd );

	// Remember a is binary valued image, ~x == chi(0,x)
	b = a & ~( max( min( a, m_nbhd ),
			m_nbhd ) );
	++count;
	m += count * IA_Image<IA_Point<int>,int>( b );
    }

    return m;
}


IA_Image<IA_Point<int>,IA_Bit>
inverse_medial_axis( const IA_Image<IA_Point<int>,int> & m,
		     const IA_Set<IA_Point<int> > & ball )  {

    // Each non-zero value in m corresponds to where a ball of
    //   the appropriate radius value should be placed.
    // However, the ball\'s radius is actually one less than
    //   the image value, since a value of one (1)
    //   corresponds to a single point.
    // Thus, radus value > 0 => k = radius value -1

    IA_Set<IA_Point<int> >
	ball_ps   = extend_to_point( 0, m.domain().dim() ),
	result_ps = IA_empty_ipset( m.domain().dim() );

    int  maxK = max( m );

    for( int k=1; k<=maxK; k++ ) {
	result_ps |= m.restrict( IA_Set<int>( k ) ).domain()
	    + ball_ps;

	// Grow the ball for the next loop through
	ball_ps += ball;  // Minkowski sum of point sets
    }

    // The result is an image over the same domain but with the
    //    corresponding inverse medial axis masked in with 1\'s.
    IA_Image<IA_Point<int>,IA_Bit>
	result_image( m.domain(), IA_Bit(0) ),
	ball_image( result_ps, IA_Bit(1) );

    return
	result_image.restrict_assign( ball_image );
}

@


1.2
log
@Modified includes to be iac++ 2.0 compliant.
@
text
@d1 1
a1 1
// mat.c                Section: 4.4
d11 2
a12 2
medial_axis( const IA_Image<IA_Point<int>,IA_Bit> & a,
	     const IA_Set<IA_Point<int> > & ps,
d16 1
a16 1
	m_nbhd( a.domain().dim(), ps );
d18 1
a18 1
    IA_Image<IA_Point<int>,int>  idi_a( a ), m( a );
d20 4
d25 6
a30 6
    while ( idi_a != 0 ) {
	idi_a = min( idi_a, m_nbhd );
	IA_Image<IA_Point<int>,int>
	    b( chi_eq( 0, max( min( idi_a, m_nbhd ),
			       m_nbhd ) ) );
	b *= idi_a;
d32 1
a32 1
	m = m + count*b;
d38 1
a38 1
/* NOT YET IMPLEMENTED
d40 19
a58 3
inverse_media_axis( const IA_Image<IA_Point<int>,u_char> & m,
		    const IA_Set<IA_Point<int> > & ps,
		    const unsigned int count ) {
d60 10
a69 1
    cerr << __FILE__ << "::inverse_media_axis() stub called" << endl;
d71 1
a71 1
	to_bit( m );
d73 1
a73 1
*/
@


1.1
log
@Initial revision
@
text
@d6 1
a6 1
#include "Neighborhood.h"
@
