📄 zernike.java
字号:
if (inband.getType() != BufferedImage.TYPE_BYTE_GRAY)
System.out.print( "zer_rec: Input pixel type must be unsigned byte.\n");
if (outband.getType() != BufferedImage.TYPE_BYTE_GRAY)
System.out.print("zer_rec: Output pixel type must be unsigned byte.\n");
isize = inband.getWidth();
jsize = inband.getHeight();
int[] src_1d=new int[isize*jsize];
Raster rt=inband.getData();
rt.getSamples(0,0,isize,jsize,0,src_1d);
double[] mt=ImageOps.mmt(inband);
Point centroid=new Point((int)mt[1],(int)mt[2]);
i_0 = (isize+1)/2.0;
j_0 = (jsize+1)/2.0;
i_scale = isize/2.0;
j_scale = jsize/2.0;
int[] box={0,isize-1,0,jsize-1};
transformed = new DCOMPLEX[jsize+1][isize+1];//(IDC_BAND) Imake_band(Id_complex_typ, isize, jsize);
for (i=1; i<=isize; i++)
for (j=1; j<=jsize; j++)
{
transformed[j][i]=new DCOMPLEX();
transformed[j][i].re = 0.0;
transformed[j][i].im = 0.0;
}
for (n=1; n<=order; n++)
{
for (m=-n; m<=n; m++)
{
if ((n-Math.abs(m)) %2 == 0)
{
// zer_mom(inband, n,m, a);
zer_mom(src_1d,isize,jsize,centroid, n,m, a);
// DCOMPLEX zer=Zernike2.MomentZernike(src_1d,isize,jsize,box,n,m);
// a[0]=zer.clone2();
System.out.print("zer_rec: A("+n+","+m+")=("+a[0].re+","+a[0].im+").\n");
for (i=1; i<=isize; i++)
for (j=1; j<=jsize; j++)
{
x = (i-i_0)/i_scale;
y = (j-j_0)/j_scale;
/*if (x*x + y*y <= 1.0) */
/*printf ("zer_rec: x=%6.3f y=%6.3f i=%i j=%i\n", x,y,i,j);
*/
zer_pol(n,m,x,y, v);
transformed[j][i].re += a[0].re*v[0].re - a[0].im*v[0].im;
transformed[j][i].im += a[0].re*v[0].im + a[0].im*v[0].re;
/*printf ("zer_con: x,y=(%6.3f,%6.3f), contr=(%9.6f,%9.6f),",
x,y,transformed[j][i].re,
transformed[j][i].im);*/
/*printf (" a=(%9.6f,%9.6f), v=(%9.6f,%9.6f)\n",
a.re, a.im, v.re, v.im);*/
}
}
}
}//end for
/*
* The following code fragment take imaginary of the complex into consideration
double min, max,scale;
for (i=1; i<=isize; i++)
for (j=1; j<=jsize; j++)
{
transformed[j][i].re = Math.sqrt
( transformed[j][i].re*transformed[j][i].re
+ transformed[j][i].im*transformed[j][i].im);
transformed[j][i].im = 0.0;
}
min = max = transformed[1][1].re;
for (i=1; i<=isize; i++)
for (j=1; j<=jsize; j++)
{
if (transformed[j][i].re > max)
max = transformed[j][i].re;
if (transformed[j][i].re < min)
min = transformed[j][i].re;
}
if (max == min)
scale = 0.0;
else
scale = 255.0/(max-min);
System.out.print("zer_rec: min="+min+", max="+max+", sacle="+scale+"\n");
* Code fragment ends here
*/
int[] dest=new int[isize*jsize];
int k=-1;
for (i=1; i<=isize; i++)
for (j=1; j<=jsize; j++)
{
k++;
if (transformed[j][i].re <= 0.0)
dest[k]=0;
else dest[k]=(int)transformed[j][i].re;//255;
// else if (transformed[j][i].re > 255.0)
// dest[k]=255;
// else dest[k]=(int)(transformed[j][i].re);
// outband.getRaster().setSample(j,i,0,(byte)(transformed[j][i].re));//outband[j][i] = (byte) (transformed[j][i].re);
/* printf ("zer_con: outband[%3i][%3i]=%3i\n", j, i, outband[j][i]);*/
}
outband.getRaster().setSamples(0,0,isize,jsize,0,dest);
return outband;
} /* zer_rec */
//int main(int argc, char[][] argv)
//{
// int order;
// char infile[], outfile[], args[], title[];
// BufferedImage inband, outband, tempband;
// IMAGE inimage, outimage;
// int xsize, ysize;
// long start_time, elapsed_time;
// int reconstruct;
// int status;
//
// Iset_message(TRUE);
// Iset_abort(TRUE);
// InitMessage(argc, argv, xite_app_std_usage_text(
// "Usage: %s [-n <n>] [-r] [-t <title>] <inimage> <outimage>\n"));
//
// if (argc == 1) Usage(1, NULL);
//
// args = argvOptions(argc, argv); /* Save command-line arguments. */
//
// order = read_iswitch(argc, argv, "-n", 0);
// reconstruct = read_bswitch(argc, argv, "-r");
// title = read_switch(argc, argv, "-t", 1,
// reconstruct ? "zernike reconstructed" : "zernike");
//
// if (argc < 3) Usage(2, "Illegal number of arguments.\n");
//
// infile = argv[argc-2];
// outfile = argv[argc-1];
//
// /* Start the clock */
//
// start_time = clock();
//
// /* Read input image from file */
//
// inimage = Iread_image(infile);
// inband = (BufferedImage)inimage[1]; /* First band only is used. */
//
// xsize = inband.getWidth();
// ysize = inband.getHeight();
//
// /* Make data structure for output image */
//
// outimage = Icopy_init(inimage);
// Iset_title(outimage, title);
// outband = (BufferedImage) outimage[1];
//
// if (reconstruct) {
// zer_rec (order, inband, outband);
// /* histoEq(tempband, outband, 256);*/
// } else {
// tempband = Imake_band(Iu_byte_typ, xsize, ysize);
// zer_con (order, inband, tempband);
// histoEq(tempband, outband, 256);
// Idel_band (tempband);
// }
//
// elapsed_time = clock() - start_time;
// System.out.print("Time used (CPU) : %fs\n", elapsed_time / 1e6);
//
// Ihistory(outimage, argv[0], args);
// status = Iwrite_image(outimage, outfile);
//
// return 0; /* Unix commands should return 0 */
//
//} /* main() */
/**
* return all zernike moments less or equal than the order
*/
public static Vector zer_mmts(int order, BufferedImage inband)
{
Vector mmts=new Vector();
int n, m;
int i, j;
double i_0, j_0;
double i_scale, j_scale;
int isize, jsize;
double x, y;
if(order<=0) return null;
DCOMPLEX[][] A=new DCOMPLEX[order+1][order+1];
if (inband.getType() != BufferedImage.TYPE_BYTE_GRAY)
System.out.print( "zer_rec: Input pixel type must be unsigned byte.\n");
isize = inband.getWidth();
jsize = inband.getHeight();
int[] src_1d=new int[isize*jsize];
Raster rt=inband.getData();
rt.getSamples(0,0,isize,jsize,0,src_1d);
double[] mt=ImageOps.mmt(inband);
Point centroid=new Point((int)mt[1],(int)mt[2]);
// i_0 = (isize+1)/2.0;
// j_0 = (jsize+1)/2.0;
// i_scale = isize/2.0;
// j_scale = jsize/2.0;
/**
* Only consider order above 2
* Notice |A(p,q)|=|A(p,-q)|
*/
for (n=0; n<=order; n++)
for (m=0; m<=n; m++)
{
if ((n-Math.abs(m)) %2 == 0)
{
DCOMPLEX[] a=new DCOMPLEX[1];
a[0]=new DCOMPLEX();
zer_mom(src_1d,isize,jsize,centroid, n,m, a);
A[n][m]=a[0];//.getModulus();
mmts.add(a[0]);
System.out.print("zer_mmts: A("+n+","+m+")=("+a[0].re+","+a[0].im+").\n");
}
}//end for
utility.save2DArray(A,"mmt1.mat");
DCOMPLEX[][] B=normalize(A);
// utility.save2DArray(B,"mmt2.mat");
DCOMPLEX[][] ZMI=getZMI(B);
utility.save2DArray(ZMI,"mmt3.mat");
Vector ZMIS=new Vector();
//we don't want to judge inside for loop
if(zernikeFea.fea_index!=null && zernikeFea.fea_index[0]==null){
int k=0;
for(i=0; i<ZMI.length;i++)
for(j=0;j<ZMI[i].length;j++)
if(ZMI[i][j]!=null){
ZMIS.add(ZMI[i][j]);
if(k>=2)
zernikeFea.fea_index[k-2]=new Point(i,j);
k++;
}
}
else{
for(i=0; i<ZMI.length;i++)
for(j=0;j<ZMI[i].length;j++)
if(ZMI[i][j]!=null){
ZMIS.add(ZMI[i][j]);
}
}//endif
//ignore A[0][0] and A[1][1]
ZMIS.removeElementAt(0);
ZMIS.removeElementAt(0);
return ZMIS;
// return mmts;
}//end of zer_mmts
/**
* Normalize the absolute value of Zernike moments
* According to the reference [2]
*/
static DCOMPLEX[][] normalize(DCOMPLEX[][] A){
int order=A.length-1;
DCOMPLEX[][] B=new DCOMPLEX[order+1][order+1];
B[0][0]=A[0][0].clone2();
B[1][1]=A[1][1].clone2();
for (int n=2; n<=order; n++)
for (int m=0; m<=n; m++)
if ((n-Math.abs(m)) %2 == 0){
B[n][m]=A[n][m].clone2();
if(n!=m && A[n-2][m].getModulus()!=0) {
B[n][m].mo=A[n][m].getModulus()/A[n-2][m].getModulus();
// System.out.print("B["+n+"]"+"["+m+"]="+"A["+n+"]["+m+"]/A["+(n-2)+"]["+m+"]\n");
}
// System.out.print("B["+n+"]"+"["+m+"]="+B[n][m]+"\n");
}
return B;
}//end of normalize
/**
* Compute the ZMIs(NZMIs) according to reference [2]
*/
static DCOMPLEX[][] getZMI(DCOMPLEX[][] A){
int order=A.length-1;
DCOMPLEX[][] B=new DCOMPLEX[order+1][2*order+1];
for (int n=0; n<=order; n++){
for (int m=0; m<=n; m++)
if ((n-Math.abs(m)) %2 == 0){
B[n][m]=A[n][m].clone2();
}
if(n%2==0 && n>=4){
double degree;
for(int L=4;L<=n;L+=2){
int z=L/2;
int p=2/L;
degree=p*A[n][L].theta-A[n][2].theta;
B[n][n+z]=new DCOMPLEX();
B[n][n+z].mo=2*A[n][2].getModulus()*Math.pow(A[n][L].getModulus(),p)*Math.cos(degree);
if(B[n][n+z].mo<0) B[n][n+z].mo=-B[n][n+z].mo;
}
degree=A[n-2][2].theta-A[n][2].theta;
B[n][n+1]=new DCOMPLEX();
B[n][n+1].mo=2*A[n-2][2].getModulus()*A[n][2].getModulus()*Math.cos(degree);
if(B[n][n+1].mo<0) B[n][n+1].mo=-B[n][n+1].mo;
}//endif
if(n%2==1 && n>=3){
double degree;
for(int L=3;L<=n;L+=2){
double p=1/L;
degree=p*A[n][L].theta-A[n][1].theta;
B[n][n+L]=new DCOMPLEX();
B[n][n+L].mo=2*A[n][1].getModulus()*Math.pow(A[n][L].getModulus(),p)*Math.cos(degree);
if(B[n][n+L].mo<0) B[n][n+L].mo=-B[n][n+L].mo;
}
degree=A[n-2][1].theta-A[n][1].theta;
B[n][n+1]=new DCOMPLEX();
B[n][n+1].mo=2*A[n-2][1].getModulus()*A[n][1].getModulus()*Math.cos(degree);
if(B[n][n+1].mo<0) B[n][n+1].mo=-B[n][n+1].mo;
}//endif
}//end for
return B;
}//end of normalize
}//end of zernike
// public class DCOMPLEX{
// double re, im;
// public DCOMPLEX() {
// re=0.0;
// im=0.0;
// }
//};
/*P:zernike*
________________________________________________________________
zernike
________________________________________________________________
Name: zernike - zernike moment image of a gray scale
or binary image
Syntax: zernike [-n <n>] [-r] [-t <title>] <inimage> <outimage>
Description: The Zernike moment of order 'n' and repetition 'm' of
an image f(x,y) is defined as follows:
| n+1 *
| A(n,m) = ---- Sum Sum f(x,y)[V(n,m, x,y)]
| pi x y
|
| where x^2+y^2 <= 1
|
The image V(n,m, x,y) is the Zernike basis images of
order 'n' and repetition 'm'. These basis images are
complex and orthogonal. The Zernike moments are
essentially the projections of the input image onto
these basis images.
The original image can be reconstructed from the
Zernike moments. The N-th order approximation is given
by
| ^ N
| f(x,y) = Sum Sum A(n,m) V(n,m, x,y)
| n=0 m
|
The contribution or information content of the n-th
order moments is
|
| I(x,y, n) = Sum A(n,m) V(n,m, x,y)
| m
Restrictions: 'inimage' must be single-band with pixel type unsigned byte.
Options: &-n n
Use moment order 'n'. Default 0.
&-r
Reconstruct image from moments. Default: Compute the absolute
value of I(x,y, n).
&-t title
Use 'title' for 'outimage'.
See also: zer_mom(3), zer_con(3), zer_rec(3), zer_pol(3)
References: &[1] 'A. Khotanzad and Y.H. Hong'
"Invariant image recognition by Zernike Moments",
IEEE trans. on Pattern Analysis and Machine Intelligence,
vol.12, no.5, pp.489-487, May 1990.
&[2] 'A. Khotanzad and Y.H. Hong'
"Rotation invariant image recognition using features
selected via a systematic method",
Pattern Recognition, vol.23, no.10, pp.1089-1101, 1990.
&[3] 'Thomas H. Reiss'
"Recognizing Planar Objects Using Invariant Image Features",
Lecture Notes in Computer Science, volume 676, pp. 17-20,
Springer-Verlag, 1993.
Return value: 0 : OK
Files: | xite/src/zernike/zernike.c
Author: 豬vind Due Trier, Ifi, UiO.
________________________________________________________________
*/
/**
* The experiments results:
* 1. n must be less than 14, or noise will appear in the reconstructed image
* 2. when reconstruct, only uses the real part
* 3. the result will be better when original image is 64*64 and is binary
* 4. the image size seems doesn't matter, while the larger the slower
* 5. at most two char together in one image will be recognized
* 6. the content in the center of the image is more easily recognized
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -