Skip to main content

Correlating Images

7 replies [Last post]
shrieky
Offline
Joined: 2007-11-26

Hi,
I am Correalting two images using DFT.... I found output to be a dark image. Please till me if i am doing anything wrong.
Thanks in advance.

ParameterBlock pb = new ParameterBlock();
pb.addSource(imageSource);
pb.add(DFTDescriptor.SCALING_NONE);
pb.add(DFTDescriptor.REAL_TO_COMPLEX);
RenderedOp source = JAI.create("dft", pb ,null);

imageTarget = (RenderedImage)JAI.create("fileload",
"C:\\Winter1024.jpg");
imageSource = (RenderedImage)JAI.create("fileload",
"C:\\WinterNew.jpg");
pb.removeSources();
pb.removeParameters();
pb.addSource(imageTarget);
pb.add(DFTDescriptor.SCALING_NONE);
pb.add(DFTDescriptor.REAL_TO_COMPLEX);
RenderedOp target = JAI.create("dft",pb);

pb.removeSources();
pb.removeParameters();
pb.addSource(target);
RenderedOp Conj = JAI.create("conjugate",pb);

pb.removeSources();
pb.removeParameters();
pb.addSource(source);
pb.addSource(Conj);
RenderedImage multiply = JAI.create("MultiplyComplex",pb);
pb.removeSources();
pb.removeParameters();
pb.addSource(multiply);
pb.add(IDFTDescriptor.SCALING_NONE);
pb.add(IDFTDescriptor.COMPLEX_TO_REAL);
RenderedImage idft = JAI.create("idft",pb,null);
pb.removeSources();
pb.removeParameters();
pb.addSource(idft);
RenderedImage formatted = JAI.create("log",pb);

pb.removeSources();
pb.removeParameters();
pb.addSource(formatted);
pb.add(DataBuffer.TYPE_BYTE);
formatted = JAI.create("format",pb);
Save(formatted);

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Fork Labs

Hello shrieky,

First, try no re-using your parameter block. Have a new one for each operation.

Second,

> ParameterBlock pb = new ParameterBlock();
> pb.addSource(imageSource);
> pb.add(DFTDescriptor.SCALING_NONE);
> pb.add(DFTDescriptor.REAL_TO_COMPLEX);
> RenderedOp source = JAI.create("dft", pb ,null);
>
> imageSource = (RenderedImage)JAI.create("fileload",
> "C:\\WinterNew.jpg");

the order seems pretty odd ...

Regards,

Daniel Léonard

---------------------------------------------------------------------
To unsubscribe, e-mail: interest-unsubscribe@jai.dev.java.net
For additional commands, e-mail: interest-help@jai.dev.java.net

shrieky
Offline
Joined: 2007-11-26

Hi Leonard,

That was a copy paste error. My Operations seems to be like this

RenderedImage imageSource = (RenderedImage)JAI.create("fileload",
"/home/isduser/WinterNew.jpg");

ParameterBlock pb = new ParameterBlock();
pb.addSource(imageSource);
pb.add(DFTDescriptor.SCALING_NONE);
pb.add(DFTDescriptor.REAL_TO_COMPLEX);
RenderedOp source = JAI.create("dft", pb ,null);

RenderedImage imageTarget = (RenderedImage)JAI.create("fileload",
"/home/isduser/Winter1024.jpg");

imageTarget = RotateDescriptor.create(imageTarget,
(float)imageTarget.getWidth()/2,
(float)imageTarget.getHeight()/2,
(float)Math.toRadians(90),
null,
null,
null);

ParameterBlock pb1 = new ParameterBlock();
pb1.addSource(imageTarget);

pb1.add(DFTDescriptor.SCALING_NONE);
pb1.add(DFTDescriptor.REAL_TO_COMPLEX);
RenderedOp target = JAI.create("dft",pb1);

ParameterBlock pb2 = new ParameterBlock();
pb2.addSource(target);
RenderedOp Conj = JAI.create("conjugate",pb2);

ParameterBlock pb3 = new ParameterBlock();
pb3.addSource(source);
pb3.addSource(Conj);
RenderedImage multiply = JAI.create("MultiplyComplex",pb3);
ParameterBlock pb4 = new ParameterBlock();
pb4.addSource(multiply);
pb4.add(IDFTDescriptor.SCALING_UNITARY);
pb4.add(IDFTDescriptor.COMPLEX_TO_REAL);
RenderedImage idft = JAI.create("idft",pb4,null);

ParameterBlock pb5 = new ParameterBlock();
pb5.addSource(idft);
RenderedImage formatted = JAI.create("log",pb5);

DataBufferFloat db=(DataBufferFloat) formatted.getData().getDataBuffer();

db.setElemFloat(0,(float)0);
RenderedImage ext = JAI.create("extrema", formatted);
double[][] extrema = (double[][])ext.getProperty("extrema");
double max = extrema[1][0];
double min = extrema[0][0];
db.setElemFloat(0,(float)max);
RenderedImage rescaleddisplay = JAI.create("rescale",idft,
new double[] {(0xFF /(max - min))},
new double[] {((0xFF * min)/(min-max))});
RenderedImage display = JAI.create("format", rescaleddisplay,
DataBuffer.TYPE_BYTE);

readAndSave((RenderedOp)display,"/home/isduser/imageNew.tiff");.

Iam getting completely a dark image. I have tried without rotating the target image by 90degres too. Iam confused whether iam following a right method to correlate.
Thank You,
Shrieky.

Fork Labs

Hello Shrieky,

First, the scaling for the DFT and IDFT must match :

1) NONE followed by DIMENSIONS (or the inverse)
2) UNITARY followed by UNITARY

> ParameterBlock pb3 = new ParameterBlock();
> pb3.addSource(source);
> pb3.addSource(Conj);
> RenderedImage multiply = JAI.create("MultiplyComplex",pb3);

Multiplying an image in the spectral domain by an image in the spatial domain ?

Otherwise, I would suggest breaking you code in methods and then
taking a look at extrema output. Also, make sure to pick a value if
both min and max are the same.

Regards,

Daniel Léonard

---------------------------------------------------------------------
To unsubscribe, e-mail: interest-unsubscribe@jai.dev.java.net
For additional commands, e-mail: interest-help@jai.dev.java.net

shrieky
Offline
Joined: 2007-11-26

The source and target images are of both 1024x1024.
Iam assuming the operation sequence to be
1 . DFT of both source image and target image.
2 . Conjugate of target image.
3 . Complex multiplication of both result images.
4. IDFT of the result image.
5. Log of result image.
6. Byte scaling.

As you have questioned about multiplication of spectral and spatial domain, i am doing the spectral vs spectral multiplication.

i can list my code in parts.

/*** source DFT *****/
RenderedImage imageSource = (RenderedImage)JAI.create("fileload",
"/home/isduser/WinterNew.jpg");
ParameterBlock pb = new ParameterBlock();
pb.addSource(imageSource);
pb.add(DFTDescriptor.SCALING_UNITARY);
pb.add(DFTDescriptor.REAL_TO_COMPLEX);
RenderedOp sourceDFT = JAI.create("dft", pb ,null);

/*************************************************************/
/*********** Target DFT *****************************/
RenderedImage imageTarget = (RenderedImage)JAI.create("fileload",
"/home/isduser/Winter1024.jpg");
ParameterBlock pb1 = new ParameterBlock();
pb1.addSource(imageTarget);

pb1.add(DFTDescriptor.SCALING_UNITARY);
pb1.add(DFTDescriptor.REAL_TO_COMPLEX);
RenderedOp targetDFT = JAI.create("dft",pb1);
/*********************************************************/

/*********** Target DFT Conjugate *****************************/
ParameterBlock pb2 = new ParameterBlock();
pb2.addSource(targetDFT);
RenderedOp Conj = JAI.create("conjugate",pb2);
/*****************************************************/

/******** Multiply Source DFT and Conj *****************/
ParameterBlock pb3 = new ParameterBlock();
pb3.addSource(sourceDFT);
pb3.addSource(Conj);
RenderedImage multiply = JAI.create("MultiplyComplex",pb3);

/****************************************************************/

/***************IDFT ****************************/
ParameterBlock pb4 = new ParameterBlock();
pb4.addSource(multiply);
pb4.add(IDFTDescriptor.SCALING_UNITARY);
pb4.add(IDFTDescriptor.COMPLEX_TO_REAL);
RenderedImage idft = JAI.create("idft",pb4,null);

/******************LOG************************/

ParameterBlock pb5 = new ParameterBlock();
pb5.addSource(idft);
RenderedImage formatted = JAI.create("log",pb5);

/**********BYTE SCALING **************************/
DataBufferFloat db=(DataBufferFloat) formatted.getData().getDataBuffer();

db.setElemFloat(0,(float)0);
RenderedImage ext = JAI.create("extrema", formatted);
double[][] extrema = (double[][])ext.getProperty("extrema");
double max = extrema[1][0];
double min = extrema[0][0];
db.setElemFloat(0,(float)max);
RenderedImage rescaleddisplay = JAI.create("rescale",idft,
new double[] {(0xFF /(max - min))},
new double[] {((0xFF * min)/(min-max))});
RenderedImage display = JAI.create("format", rescaleddisplay,
DataBuffer.TYPE_BYTE);

I am not deviating from any of the above steps. But still i guess I am doing some mistake. If you could make it, I would be grateful to you.

Thanks,
Shrieky

mh1b
Offline
Joined: 2006-07-15

It looks mostly ok, the issue is probably in your scaling code. A couple notes,

- step 5 (log of result image) is not necessary
- the result image will be quadrant-swapped, and you can use 'periodicshift' to correct it

Here's code that works for me, sorry if some of the lines are kinda long,

final int MIN = 0, MAX = 1;
String fileLeft = "C:\\temp\\jai_corr_test_l.png";
String fileRight = "C:\\temp\\jai_corr_test_r.png";
try {
// file load
RenderedOp opLoadLeft = FileLoadDescriptor.create(fileLeft, null, null, null);
RenderedOp opLoadRight = FileLoadDescriptor.create(fileRight, null, null, null);

// dft
RenderedOp opDFTLeft = DFTDescriptor.create(opLoadLeft, DFTDescriptor.SCALING_NONE, DFTDescriptor.REAL_TO_COMPLEX, null);
RenderedOp opDFTRight = DFTDescriptor.create(opLoadRight, DFTDescriptor.SCALING_NONE, DFTDescriptor.REAL_TO_COMPLEX, null);

// conjugate
RenderedOp opDFTLeftConj = ConjugateDescriptor.create(opDFTLeft, null);
// multiply
RenderedOp opCrossPowerSpec = MultiplyComplexDescriptor.create(opDFTRight, opDFTLeftConj, null);

// inverse dft
opCrossPowerSpec = IDFTDescriptor.create(opCrossPowerSpec, IDFTDescriptor.SCALING_DIMENSIONS, IDFTDescriptor.COMPLEX_TO_COMPLEX, null);

// magnitude
RenderedOp opCrossPowerMagn = MagnitudeDescriptor.create(opCrossPowerSpec, null);
// log (not necessary)
opCrossPowerMagn = LogDescriptor.create(opCrossPowerMagn, null);
// put origin at center
opCrossPowerMagn = PeriodicShiftDescriptor.create(opCrossPowerMagn, new Integer(opCrossPowerMagn.getWidth() / 2), new Integer(opCrossPowerMagn.getHeight() / 2), null);

// extrema
RenderedOp opExtrema = ExtremaDescriptor.create(opCrossPowerMagn, new ROIShape(opCrossPowerMagn.getBounds()), 1, 1, Boolean.TRUE, 1, null);
// - minimum and maximum locations
int[] maxLocation = (int[])((List[])opExtrema.getProperty("maxLocations"))[0].get(0);
// - minimum and maximum pixel values
double[][] extrema = (double[][])opExtrema.getProperty("extrema");
double c = 255.0 / (extrema[MAX][0] - extrema[MIN][0]);
double o = -extrema[MIN][0] * c;

System.out.println("Maximum value " + extrema[MAX][0] + " found at (" + maxLocation[0] + "," + maxLocation[1] + ")");

// set up output image
// - image layout
Rectangle bounds = opCrossPowerMagn.getBounds();
SampleModel sm = new PixelInterleavedSampleModel(DataBuffer.TYPE_BYTE, bounds.width, bounds.height, 1, bounds.width, new int[] {0});
ColorModel cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_GRAY), false, false, ColorModel.OPAQUE, DataBuffer.TYPE_BYTE);
ImageLayout layout = new ImageLayout(opCrossPowerMagn.getTileGridXOffset(), opCrossPowerMagn.getTileGridYOffset(), opCrossPowerMagn.getTileWidth(), opCrossPowerMagn.getTileHeight(), sm, cm);
// - rescale pixel values to (0, 255)
RenderedOp opRescale = RescaleDescriptor.create(opCrossPowerMagn, new double[] {c}, new double[] {o}, new RenderingHints(JAI.KEY_IMAGE_LAYOUT, layout));
// - write output
RenderedOp opStore = FileStoreDescriptor.create(opRescale, "jai_corr_out.png", "png", null, null, null);
}catch (Exception ex){
ex.printStackTrace();
}

shrieky
Offline
Joined: 2007-11-26

Hi,
Is it working on simple images only or all complex images. I mean to say on the images which has 256 colors in it.

Shrieky

shrieky
Offline
Joined: 2007-11-26

i have solved it using native methods of Cross correlation