www.pudn.com > gsnake.rar > contour.tex
\rhead{class CONTOUR}
\section{CONTOUR : A deformable template object}
{\tt CONTOUR} is a collection of {\tt SNAXEL} objects forming a deformable template. It has the following structure :
\begin{verbatim}
class CONTOUR {
protected :
SNAXEL *head; /* head of snake */
SNAXEL *tail; /* tail of snake */
SNAKEMODE mode; /* opened or closed snake */
short numsnaxel; /* number of snaxel */
double cg_row, cg_col; /* center of gravity */
double avglen; /* ave. power (length) of snake */
double sig_nu_sqr; /* white noise variance on gradient power */
double Z; /* normalizing constant */
short direction; /* [0/-1/+1] preset gradient direction */
};
\end{verbatim}
{\tt CONTOUR} is a linked list of {\tt SNAXELS} originated at image origin or the reference point ({\tt cg\_col}, {\tt cg\_row}). Each contour can have a gradient direction ({\tt direction}) that pointing outward (+1) or inward (-1). {\tt avglen} refers to $l(U)$ in equation (3.9), {\tt sig\_nu\_sqr} refers to $\sigma_{\eta}^{2}$ in equation (3.24), and {\tt Z} refers to $Z_{i}$ in equation (4.35) of \cite{kn:thesis}.
%
\subsection{{\tt CONTOUR} constructor}
\subsubsection*{Synopsis}
\begin{verbatim}
CONTOUR(void)
\end{verbatim}
\subsubsection*{Description}
The constructor initializes the number of snaxels, white noise variance ($\sigma_{\eta}^{2}$) and contour direction to 0, sets normalizing constant to 1. and directs the head and tail to NULL.
%
\subsection{{\tt CONTOUR} destructor}
\subsubsection*{Synopsis}
\begin{verbatim}
~CONTOUR(void)
\end{verbatim}
\subsubsection*{Description}
The destructor frees the memory allocated to snaxels which form a complete chain of contour.
%
\subsection{Resetting a {\tt CONTOUR} }
\subsubsection*{Synopsis}
\begin{verbatim}
void reset()
\end{verbatim}
\subsubsection*{Description}
{\tt reset} allows the reuse of an {\tt CONTOUR} object by freeing up the memory allocated to snaxels and setting the head and tail to NULL.
%
\subsection{Automatic initialization of closed contour}
\subsubsection*{Synopsis}
\begin{verbatim}
int init( short _cg_row, short _cg_col,
double radius, short numpts = 16)
\end{verbatim}
\subsubsection*{Arguments}
\tb
{\tt \_cg\_row, \_cg\_col} & Centre of circle. \\
{\tt radius} & Radius of circle. \\
{\tt numpts} & Number of snaxels.
\te
\subsubsection*{Returns}
\tb
{\tt NOERROR} & Successful operation.\\
{\tt MEMORYERROR} & Memory allocation failure.
\te
\subsubsection*{Description}
{\tt init} creates a circle with {\tt numpts} snaxels and sets its {\tt mode} to \_CLOSED, that is, a contour with its head and tail internally connected.
%
\subsection{Automatic initialization of open contour}
\subsubsection*{Synopsis}
\begin{verbatim}
int init( short sx, short sy, short ex, short ey,
short numpts = 16 )
\end{verbatim}
\subsubsection*{Arguments}
\tb
{\tt sx, sy} & The starting point of a line. \\
{\tt ex, ey} & The ending point of a line. \\
{\tt numpts} & Number of snaxels.
\te
\subsubsection*{Returns}
\tb
{\tt NOERROR} & Successful operation. \\
{\tt MEMORYERROR} & Memory allocation failure.
\te
\subsubsection*{Description}
{\tt init} creates a line with {\tt numpts} snaxels and sets its {\tt mode} to \_OPENED, that is, a contour with unconnected head and tail.
%
\subsection{Manual initialization of a contour }
\subsubsection*{Synopsis}
\begin{verbatim}
int init( IMAGE *ximg, unsigned char blowup = 1,
INITMODE theINIT = _CLICKMOUSE,
SNAKEMODE _mode = _CLOSED,int spacing)
\end{verbatim}
\subsubsection*{Arguments}
\tb
{\tt *ximg} & Reference image. \\
{\tt blowup} & Image magnification factor. \\
{\tt theINIT} & Contour initialization method,
\_DRAGMOUSE or \_CLICKMOUSE \\
{\tt \_mode} & Snake mode of a contour, \_OPENED or \_CLOSED.
\te
\subsubsection*{Returns}
\tb
{\tt NOERROR} & Successful operation. \\
{\tt MEMORYERROR} & Memory allocation error.
\te
\subsubsection*{Description}
{\tt init} creates a contour of either through clicking ({\tt \_CLICKMOUSE}) or dragging ({\tt \_DRAGMOUSE}) by mouse. By displaying the reference image on an X window, the user then specifies the desired snaxels. Since the snaxels are joined sequentially, the selection of the snaxels must be in order.
%
\subsection{File interface methods}
\subsubsection*{Synopsis}
\begin{verbatim}
int read( char *filename )
int write( char *filename )
\end{verbatim}
\subsubsection*{Arguments}
\tb
{\tt *filename} & Contour file.
\te
\subsubsection*{Returns}
\tb
{\tt NOERROR} & Successful read or write operation. \\
{\tt MEMORYERROR} & Memory allocation failure. \\
{\tt FILEIOERROR} & Unable to read from or write to file.
\te
\subsubsection*{Description}
{\tt read} and {\tt write} provide file manipulation routines for accessing a contour file. The format, which is in text form, is as following :
\begin{quote}
\begin{tabular}{ll}
$\underline{Field}$ & $\underline{Data type}$ \\
Magic number & 1010 (hex) \\
Mode & \_OPENED (0) or \_CLOSED (1) \\
Number of snaxels & Integer number \\
White noise variance & Exponential notation \\
Snaxel coordinates (column, row) & Double \\
Shape matrix ($\alpha$, $\beta$) & Double \\
Regularization parameter ($\lambda$) & Double \\
Normalizing constant & Exponential notation.
\end{tabular}
\end{quote}
%
\subsection{Learning shape matrix}
\subsubsection*{Synopsis}
\begin{verbatim}
void computeShape() \end{verbatim}
\subsubsection*{Description}
{\tt computeShape} models and calculates the {\em shape matrix} of a contour as in (Eqn 3.3 of \cite{kn:thesis}). $\alpha$ and $\beta$ are computed as following :
\eq
\left[
\begin{array}{c}
{\bf \alpha_{i}} \\
{\bf \beta_{i}}
\end{array}
\right] =
\left[
\begin{array}{cc}
x_{i \alpha} & x_{i \beta} \\
y_{i \beta} & y_{i \beta}
\end{array}
\right]^{-1}
\left[
\begin{array}{c}
{\bf x_{i}} \\
{\bf y_{i}}
\end{array}
\right]
\en
%
\subsection{Computing normalizing constant for classification purpose}
\subsubsection*{Synopsis}
\begin{verbatim}
void computeZ()
\end{verbatim}
\subsubsection*{Description}
{\tt computeZ} compute normaling constant $Z_{i}$ by Monte Carlo estimation. {$Z_{i}$ must be calculated during the training stage of classification. Supposes a family of contours $U \in \Omega_{i}$, then
\eq
Z_{i} = \sum_{ U \in \Omega_{i}} \exp(-E_{int}(U))
\en
%
\subsection{Computing the average vector distance l(U) between snaxels}
\subsubsection*{Synopsis}
\begin{verbatim}
double computeAvgLength()
\end{verbatim}
\subsubsection*{Returns}
Average distance of snaxels.
\subsubsection*{Description}
{\tt computeAvgLength} calculates the average distance between snaxels, $l(U)$, as following :
\eq
l(U) = \frac{1}{n}\sum_{i=1}^{n}\|u_{i+1}-u_{i}\|^{2}
\en
$l(U)$ is also the normalising constant used for internal energy calculation.
%
\subsection{Regenerating shape matrix}
\subsubsection*{Synopsis}
\begin{verbatim}
int regenerate()
\end{verbatim}
\subsubsection*{Returns}
\tb
{\tt NOERROR} & Successful operation. \\
{\tt MEMORYERROR} & Memory allocation failure. \\
{\tt PARAMERROR} & Parameter error.
\te
\subsubsection*{Description}
{\tt regenerate} generate the complete chain $U$ from {\em shape matrix} $A$ by matrix inversion if the last two snaxels on $U$ is available. This is possible by decomposing $A$ into an $(n-2)\times(n-2)$ invertible submatrix $A_{r}$ such that,
\eq
A_{r} U_{r} + b = 0 \\
\label{eqn:regenerate1}
\en
where
\eq
b = \left[ \begin{array}{c}
\ldots \\
0 \\
\ldots \\
-\beta_{n-2} u_{n-1} \\
u_{n-1}-\beta_{n}u_{n}
\end{array}
\right]
\label{eqn:regenerate2}
\en
Thus the regenerative contour $U_{r}$ is,
\eq
U_{r} = -A_{r}^{-1}b
\en
%
\subsection{Conversion of Coordinates}
\subsubsection*{Synopsis}
\begin{verbatim}
void imageCentered()
void contourCentered()
\end{verbatim}
\subsubsection*{Description}
{\tt imageCentered} defines a contour as the vector containing an ordered set of points, $V = [v_{1}, v_{2}, \ldots, v_{n}]$, where each $v_{i}$ has its origin at (0, 0) of an image. In contrast, {\tt contourCentered} defines a contour as $U = [u_{1}, u_{2}, \ldots, u_{n}]$, where each $u_{i} = v_{i} - g$ represents the displacement from the center of gravity $g$ of a contour.
%
\subsection{Calculating the internal energy of an individual snaxel}
\subsubsection*{Synopsis}
\begin{verbatim}
double EInternal (SNAXEL *sxptr)
\end{verbatim}
\subsubsection*{Arguments}
\tb
sxptr & Targeted snaxel.
\te
\subsubsection*{Returns}
Internal energy of the targeted snaxel.
\subsubsection*{Description}
{\tt EInternal} computes the internal energy of a snaxel as (Eqn 3.21 of \cite{kn:thesis}).
%
\subsection{Affine transformations of contour}
\subsubsection*{Synopsis}
\begin{verbatim}
void rotate (double angle)
void translate (int dx, int dy)
void scale (double sx, double sy)
void dilate (double idx, double idy)
void affineTransform(double sx, double sy, double rt,
double tx, double ty, double idx, double idy)
\end{verbatim}
\subsubsection*{Arguments}
\tb
{\tt angle} & Rotation angle in degrees. \\
{\tt dx, dy} & Translation vector. \\
{\tt sx, sy} & Scaling factor. \\
{\tt idx, idy} & Dilation factor.
\te
\subsubsection*{Description}
These methods provides routines for global deformations of a contour so that user can observe the effects of rigid motion on the {\em shape matrix}.
%
\subsection{Computing the centre of gravity of contour}
\subsubsection*{Synopsis}
\begin{verbatim}
void computeCG()
\end{verbatim}
\subsubsection*{Description}
{\tt computeCG} calculates the centre of gravity of a contour, $CG(U)$, as below :
\eq
CG(U) = \frac{1}{n}\sum_{i=1}^{n}v_{i}
\en
%
\subsection{Duplicating a contour}
\subsubsection*{Synopsis}
\begin{verbatim}
CONTOUR *duplicate(CONTOUR *target=NULL, short snx=0)
\end{verbatim}
\subsubsection*{Arguments}
\tb
target & Targeted contour. \\
snx & Flag (0:off, 1:on) to indicate copying of snaxels only.
\te
\subsubsection*{Returns}
Pointer to a new created contour if {\tt target} is NULL or pointer to the {\tt target} contour if otherwise. Returns NULL if memory allocation error
\subsubsection*{Description}
{\tt duplicate} creates an exact duplication of its contour if {\tt target} is NULL. Otherwise, it will copy its content or snaxels information only to the {\tt target} contour, depending on the {\tt snx} flag. Copying of snaxels will not be allowed if both contours have different number of snaxels.
%
\subsection{Retrieving and accessing of a contour content}
\subsubsection*{Synopsis}
\begin{verbatim}
SNAXEL *getHead(void)
SNAXEL *getTail(void)
SNAKEMODE getMode(void)
void putMode(SNAKEMODE _mode)
short getNumSnaxel(void)
double getCgRow(void)
double getCgCol(void)
double getZ(void)
void putCgRow(double _row)
void putCgCol(double _col)
double getSigNuSqr(void)
void putSigNuSqr(double _sig_nu_sqr)
void putDirection(short _direction)
void putZ(double _Z)
\end{verbatim}
\subsubsection*{Arguments}
\tb
{\tt \_mode} & Snake mode of a contour. \\
{\tt \_row, \_col} & Center of gravity. \\
{\tt \_sig\_nu\_sqr} & White noise variance. \\
{\tt \_direction} & Snake direction.
\te
\subsubsection*{Returns}
Head or tail of contour, snake mode, center of gravity, white noise variance ($\sigma_{\eta}^{2}$), snake direction, or normalizing constant.
\subsubsection*{Description}
These methods facilitate the retrieval and accessing of contour details.
%
\subsection{Displaying contour shape}
\subsubsection*{Synopsis}
\begin{verbatim}
void display(short mag = 1);
\end{verbatim}
\subsubsection*{Arguments}
\tb
{\tt mag} & Image magnification factor.
\te
\subsubsection*{Description}
{\tt display} shows the shape of a contour, which will always be in the center of an X window.
%
\subsection{Showing a contour on another image}
\subsubsection*{Synopsis}
\begin{verbatim}
void show(IMAGE *backgnd, unsigned char blowup=1,
int pt_Xoffset=0, int pt_Yoffset=0, short expand=1);
\end{verbatim}
\subsubsection*{Arguments}
\tb
{\tt backgnd} & Background image. \\
{\tt blowup} & Image magnification factor. \\
{\tt pt\_Xoffset, pt\_Yoffset} & Offset of a contour against
a window origin. \\
{\tt expand} & Expanding factor.
\te
\subsubsection*{Description}
{\tt show} display an expanded contour on top of the background image by an offset of (pt\_Xoffset, pt\_Yoffset).
%
\subsection{Example : Initialization of contours }
This program performs the initialization of an opened and closed contour.
\begin{verbatim}
void testmain( SNAKEMODE smode, /* snake mode */
int Sx, int Sy, /* starting point of a line */
int Ex, int Ey, /* ending point of a line */
double Radius, /* radius of circle */
short num_points, /* number of snaxels */
int mag ) /* magnification factor */
{
CONTOUR mycontour; /* CONTOUR object */
SNAXEL *sptr; /* SNAXEL objcet */
register short i = 0;
/* Initialize an arbitrary close snake */
if (smode == _CLOSED)
mycontour.init(Sy, Sx, Radius, num_points);
else
mycontour.init(Sx, Sy, Ex, Ey, num_points);
/* The average length of snaxel must be calculated first. */
mycontour.computeAvgLength();
printf("\nContour information : \n");
mycontour.print();
printf("\nPress enter to display contour.");
getchar();
mycontour.display(mag);
/* Internal energy of snake without deformation should be 0 */
printf("\nInternal energy.");
for(sptr=mycontour.getHead(); sptr; sptr=sptr->getNext(), i++)
printf("\nEmodel of snaxel %d = %f",
i, mycontour.EInternal(sptr));
printf("\nPress enter to continue");
getchar();
printf("\nEnd of test.\n");
}
\end{verbatim}
{\tt getAvgLength} must be called before the internal energy calculation so as to compute the average distant of snaxels. A contour should have internal energy of zero if no deformation happens.
%
\subsection{Example : Affine transformations of contour}
This program demonstrates the affine invariance of shape matrix. The internal energy before and after the transformation should be of the same.
\begin{verbatim}
void testmain( char *confile, /* contour file */
int mag, /* magnification factor */
double angle, /* rotation angle */
int tx, int ty, /* translation vector */
double sx, double sy, /* scaling factor */
double dx, double dy, /* dilution vector */
char *outfile) /* output file */
{
CONTOUR mycontour; /* CONTOUR object */
SNAXEL *sptr; /* SNAXEL object */
register short i;
double temp;
/* read a contour file */
if (mycontour.read(confile)) exit(-1);
mycontour.display(mag);
/* Calculate average length and internal energy of snaxel */
temp = mycontour.computeAvgLength();
mycontour.computeShape();
mycontour.print();
for(i=0, sptr=mycontour.getHead(); sptr; sptr=sptr->getNext(), i++)
printf("\nEmodel of snaxel %d = %f", i, mycontour.EInternal(sptr));
printf("\nPress enter to continue");
getchar();
/* affine transformation should be done in contour centered formed */
mycontour.contourCentered();
mycontour.affineTransform( sx, sy, angle, tx, ty, dx, dy );
printf("\nShowing contour after transformations.");
mycontour.imageCentered();
mycontour.computeCG();
mycontour.display(mag);
printf("\nPress enter to continue");
getchar();
/* internal energy should be invariant to affine transforms */
printf("\nPerforming internal energy calculation after transforms.\n");
for(i=0, sptr=mycontour.getHead(); sptr; sptr=sptr->getNext(), i++)
printf("\nEmodel of snaxel %d = %f", i, mycontour.EInternal(sptr));
/* Performing shape learning */
printf("\n\nContour and snaxel co-efficients after learning.\n");
printf("\nAverage distance: %f\n",temp);
mycontour.computeShape();
mycontour.display();
mycontour.print();
printf("\nPress enter to continue");
getchar();
/* write contour to output file */
if (outfile) {
printf("\nWriting contour to file %s", outfile);
mycontour.write(outfile);
}
}
\end{verbatim}
%
\subsection{Example : Coordinate conversion of contour}
This program shows the manual initialization of a contour with mouse. Besides, {\tt imageCentered} and {\tt contourCentered} convert snaxels coordinates from contour centered form to image centered form and vice versa.
\begin{verbatim}
void testmain( char *imgfile, /* image file */
INITMODE imode, /* manual initialization mode */
SNAKEMODE smode, /* snake mode */
int numpts, /* number of snaxels */
int mag ) /* image magnification factor */
{
CONTOUR mycontour; /* CONTOUR object */
SNAXEL *sptr; /* SNAXEL object */
IMAGE myimage; /* IMAGE object */
register short i;
/* Read and show image */
if (myimage.read(imgfile)) exit(-1);
myimage.show(mag);
/* Generating line or circle based on image automatically */
if (imode == _LOADTEMPLATE) {
int row, col;
row = myimage.getRow();
col = myimage.getCol();
if ( smode == _CLOSED )
mycontour.init( row/2, col/2, (double)MIN(row,col)/4.0,numpts );
else
mycontour.init( (short)(col/4), (short)(row/4),
(short)(3*col/4), (short)(row/2), numpts );
}
else {
/* Initialise contour with mouse*/
mycontour.init(&myimage, mag, imode, smode);
}
mycontour.display(mag);
printf("\nPress enter to continue.");
getchar();
/* first calculate Cg of contour */
mycontour.computeAvgLength();
mycontour.computeShape();
mycontour.computeCG();
printf("\nCG Row= %f CG col = %f",
mycontour.getCgRow(), mycontour.getCgCol());
/* Converting co-ordinate form */
printf("\n **** Getting contour centered co-ordinates ****\n\n");
mycontour.contourCentered();
mycontour.print();
for(sptr=mycontour.getHead(), i=0; sptr; sptr=sptr->getNext(), i++)
printf("\nInternal energy of snaxel %d = %f",
i, mycontour.EInternal(sptr));
printf("\nPress enter to continue.");
getchar();
printf("\nConverting back to image centered\n\n");
mycontour.imageCentered();
mycontour.print();
for(sptr=mycontour.getHead(), i=0; sptr; sptr=sptr->getNext(), i++)
printf("\nInternal energy of snaxel %d = %f",
i, mycontour.EInternal(sptr));
printf("\nEnd of test.\n");
}
\end{verbatim}
%
\subsection{Example : Duplication of contour}
This program shows the different modes of contour duplication.
\begin{verbatim}
void testmain(char *file1, char *file2)
{
CONTOUR con1;
CONTOUR *con3 = NULL;
CONTOUR con2;
printf("\nReading contour 1 from %s", file1);
printf("\nReading contour 2 from %s",file2);
if ( (con1.read(file1)) || (con2.read(file2)) ) exit(-1);
printf("\n\n**** Contour 1 co-ordinates ****\n");
con1.print();
printf("\n\n**** Contour 2 co-ordinates ****\n");
con2.print();
printf("\nPress enter to continue");
getchar();
printf("\nCreating new contour from contour 1.");
con3 = con1.duplicate(con3);
con3->print();
printf("\nCopying snaxel information only from contour 2");
con3 = con2.duplicate(con3, 1);
printf("\nPrinting contour information\n");
con1.print();
con3->print();
getchar();
}
\end{verbatim}
The output of the program should show that {\tt con3} have properties such as {\tt sigma\_x} and {\tt avglen} that of {\tt con1} and have snaxel information that of {\tt con2}.