Reply by Ken Prager September 24, 20032003-09-24
In article <20030923160858147-0400@nntp.mgh.harvard.edu>,
 Eric Raas <foo@bar.net> wrote:

> > > > Are you using Cocoa for convenience or is your end goal to make a > > standalone program? If it's convenience then you might consider > > trying another viewing program such as GraphicConverter? It provides > > plenty of options for upsampling the original. Matlab (and the image > > processing toolbox) is another alternative. > > > > Thanks - you are right in that the replication of the original image > that is interleaved into the sinc interpolation is shifted - by 1/4 > pixel for 2x oversampling (I think our postings crossed). > > I am building a standalong application - overall I've found the current > version of Cocoa to be good for image display (and it has worked very > well for my current app in general). GraphicConverter is a great > program - and I do a lot of my algorithm development and proof of > concept in Matlab. My Cocoa program is actually a reimplementation of a > Matlab program that just got too big to be managable in Matlab. I am > also getting great performance using vectorized DSP stuff on the Mac ( > although in other posts I've complained about the documentation...) > > ER
I'm glad things are OK. (Note: I tend to think of replication as causing the 1/2 pixel shift, not the other way around.) BTW, those vector libraries were written in part by Mercury computer and based on their SAL library. Ken P. -- Remove _me_ for e-mail address
Reply by Eric Raas September 23, 20032003-09-23
> > Are you using Cocoa for convenience or is your end goal to make a > standalone program? If it's convenience then you might consider > trying another viewing program such as GraphicConverter? It provides > plenty of options for upsampling the original. Matlab (and the image > processing toolbox) is another alternative. >
Thanks - you are right in that the replication of the original image that is interleaved into the sinc interpolation is shifted - by 1/4 pixel for 2x oversampling (I think our postings crossed). I am building a standalong application - overall I've found the current version of Cocoa to be good for image display (and it has worked very well for my current app in general). GraphicConverter is a great program - and I do a lot of my algorithm development and proof of concept in Matlab. My Cocoa program is actually a reimplementation of a Matlab program that just got too big to be managable in Matlab. I am also getting great performance using vectorized DSP stuff on the Mac ( although in other posts I've complained about the documentation...) ER
Reply by Eric Raas September 23, 20032003-09-23
...
> > I guess that if my image shifts, that means I am effectively convolving > it with a shifted sinc function, which means I'm multiplying the 2D FFT > data with a phase-modulated rect function (i.e. somehow disturbing the > phase of the original data). I don't see how just zero-padding could do > that though.
... D'oh!! Just realized the reason for this shift is painfully obvious. Sinc interpolation (say oversampling by a factor of two) will interleave interpolated pixels between the 'true' pixels, which will comprise an exact copy of the original image. If you superimpose the interpolated image over the original image, the interpolated image will have to be squashed to make it the same size. This squashing (excuse my technical language) forces the 'true' pixels to move over slightly to make room for the interpolated pixels. In the case of 2x oversampling, the center of the 'true' pixel in the sinc-interpolated image will be shifted by 1/4 of the spacing of the pixels in the original image. This accounts for the slight sub-pixel shift that has been driving me nuts... can probably fix this by applying a phase modulation to the Fourier data.
Reply by Ken Prager September 23, 20032003-09-23
In article <20030922225830754-0400@news.verizon.net>,
 Eric Raas <foo@bar.net> wrote:

> > > >> I have used sinc interpolation (by zero padding 2D FFT) to oversample > >> an image along one axis. The results look good, but if I make the > >> new and old images the same size and overlay them, the interpolated > >> image seems to be shifted by about a pixel (maybe less) along the > >> direction of interpolation. > > > > What are you using to make the old image the same size? Could the > > error be there? > > > > The original image is 64x64 and the new image is 128x64. I am viewing > them onscreen using C libraries (Apple's Cocoa framework) which allow > you to specify the desired display size (in screen pixels) of an image. > I am drawing both the old and new images to a view with the same nominal > size in screen pixels (the edges of the two images are in aligment - it > is the content that seems to shift). The viewing size is somewhat > larger than the original bitmap sizes, and the images are rendered using > pixel replication (they look 'blocky'). > > Of course the library must do other pixel transformations to render the > small bitmaps on the screen as larger bitmaps - maybe the problem is > related to this, although the shift looks too large to just be due to > monitor resolution (it is on the order of the much larger pixels of the > processed bitmaps - not the screen pixels). > > I guess that if my image shifts, that means I am effectively convolving > it with a shifted sinc function, which means I'm multiplying the 2D FFT > data with a phase-modulated rect function (i.e. somehow disturbing the > phase of the original data). I don't see how just zero-padding could do > that though. > > On a related note I have also noticed funny shifts/warping in images > when I turn Apple's Quartz antialiasing on or off (it smooths the edges > of blocky pixels in enlarged bitmaps - is really intended for text). > Maybe I should try making my image view sizes an even power of two...
It sounds like your original image is being replicated. This would lead to a one-pixel shift (in the image space, not viewing space). I have only had a little experience with Cocoa's built-in functions for image display but found them to be flaky. For one thing, the older version, used with 10.1.x did not implement all of the functionality. Bottom line is that I have seen Cocoa's IP routines offer less control over the display process and I would not rely on them to upsample the original image. Are you using Cocoa for convenience or is your end goal to make a standalone program? If it's convenience then you might consider trying another viewing program such as GraphicConverter? It provides plenty of options for upsampling the original. Matlab (and the image processing toolbox) is another alternative. HTH, KP -- Remove _me_ for e-mail address
Reply by Eric Raas September 22, 20032003-09-22
> >> I have used sinc interpolation (by zero padding 2D FFT) to oversample >> an image along one axis. The results look good, but if I make the >> new and old images the same size and overlay them, the interpolated >> image seems to be shifted by about a pixel (maybe less) along the >> direction of interpolation. > > What are you using to make the old image the same size? Could the > error be there? >
The original image is 64x64 and the new image is 128x64. I am viewing them onscreen using C libraries (Apple's Cocoa framework) which allow you to specify the desired display size (in screen pixels) of an image. I am drawing both the old and new images to a view with the same nominal size in screen pixels (the edges of the two images are in aligment - it is the content that seems to shift). The viewing size is somewhat larger than the original bitmap sizes, and the images are rendered using pixel replication (they look 'blocky'). Of course the library must do other pixel transformations to render the small bitmaps on the screen as larger bitmaps - maybe the problem is related to this, although the shift looks too large to just be due to monitor resolution (it is on the order of the much larger pixels of the processed bitmaps - not the screen pixels). I guess that if my image shifts, that means I am effectively convolving it with a shifted sinc function, which means I'm multiplying the 2D FFT data with a phase-modulated rect function (i.e. somehow disturbing the phase of the original data). I don't see how just zero-padding could do that though. On a related note I have also noticed funny shifts/warping in images when I turn Apple's Quartz antialiasing on or off (it smooths the edges of blocky pixels in enlarged bitmaps - is really intended for text). Maybe I should try making my image view sizes an even power of two...
Reply by Ken Prager September 22, 20032003-09-22
In article <20030922134949292-0400@nntp.mgh.harvard.edu>,
 Eric Raas <foo@bar.net> wrote:

> I have used sinc interpolation (by zero padding 2D FFT) to oversample an > image along one axis. The results look good, but if I make the new and > old images the same size and overlay them, the interpolated image seems > to be shifted by about a pixel (maybe less) along the direction of > interpolation.
What are you using to make the old image the same size? Could the error be there? KP -- Remove _me_ for e-mail address
Reply by Eric Raas September 22, 20032003-09-22
I have used sinc interpolation (by zero padding 2D FFT) to oversample an 
image along one axis.  The results look good, but if I make the new and 
old images the same size and overlay them, the interpolated image seems 
to be shifted by about a pixel (maybe less) along the direction of 
interpolation.

The scheme I used was pretty simple (described here for interpolation of 
rows):

1) take 2D FFT of original 64x64 image

2) zero pad 2D FFT array to create a 128x64 array (taking shifted 
quadrants produced by FFT function into account)

3) compute inverse 2D FFT of the zero-padded array

I understand that a one-pixel image shift corresponds to a 2*pi phase 
roll over the rows of the 2D FT matrix, but am not sure why this would 
happen.  Any ideas?

Code fragement (using Apple vDSP libraries) attached below:

  // Compute 2D FFT of original image
  fft2d_zip ( setup, &origImage, rowStride, columnStride, log2nc, log2nr, 
FFT_FORWARD );

  // Zero-pad the rows of the data here
  COMPLEX_SPLIT padImage;
  padImage.realp = (float*)calloc(n*2, sizeof(float));
  padImage.imagp = (float*)calloc(n*2, sizeof(float)); // Is all zero

  memcpy( padImage.realp, origImage.realp, ( n/2 * sizeof (float)));
  memcpy( padImage.imagp, origImage.imagp, ( n/2 * sizeof (float)));
  memcpy( &(padImage.realp[n + n/2]), &(origImage.realp[n/2]), ( n/2 * 
sizeof ( float ) ) );
  memcpy( &(padImage.imagp[n + n/2]), &(origImage.imagp[n/2]), ( n/2 * 
sizeof ( float ) ) );

  // Now compute inverse FFT
  fft2d_zip ( setup, &padImage, rowStride, columnStride, log2nc, 
log2nr+1, FFT_INVERSE );
  
  // scale the result
  float scale = 1.0 / (float)n;    // get scale factor
  vsmul( padImage.realp, 1, &scale, padImage.realp, 1, 2*n);
  vsmul( padImage.imagp, 1, &scale, padImage.imagp, 1, 2*n);