Author Topic: is there a way to extract the transformation that SA does?  (Read 2692 times)

Offline pfile

  • PTeam Member
  • PixInsight Jedi Grand Master
  • ********
  • Posts: 4729
i ran into a situation where i had build up star masks and other masks for an image, but then needed to register the image (and it's masks) to another image.

since one of the masks had the stars deleted, it was a little hard to run SA on it :). is there a way to somehow save and apply just the transformation that SA computed between two images, so that i can arbitrarily apply it to other images?

thanks

rob

Offline Juan Conejero

  • PTeam Member
  • PixInsight Jedi Grand Master
  • ********
  • Posts: 7111
    • http://pixinsight.com/
Re: is there a way to extract the transformation that SA does?
« Reply #1 on: 2013 October 07 12:47:04 »
Try the following script:

Code: [Select]
#include <pjsr/SampleType.jsh>
#include <pjsr/ColorSpace.jsh>

/*
 * Projective transformation matrix.
 */
var H = new Matrix(
     +1.0000,    +0.0000,    +0.0000,
     +0.0000,    +1.0000,    +0.0000,
     +0.0000,    +0.0000,    +1.0000
);

/*
 * If working with an inverse projection matrix (e.g., StarAlignment), leave
 * the next line as is.
 */
var matrix = H;
/*
 * If working with a direct projection matrix, uncomment the next line and
 * comment out the previous one.
 */
//var matrix = H.inverse();

/*
 * Filling color for unmapped target image pixels.
 */
var backgroundColor = 0;

var h00 = matrix.at( 0, 0 );
var h01 = matrix.at( 0, 1 );
var h02 = matrix.at( 0, 2 );
var h10 = matrix.at( 1, 0 );
var h11 = matrix.at( 1, 1 );
var h12 = matrix.at( 1, 2 );
var h20 = matrix.at( 2, 0 );
var h21 = matrix.at( 2, 1 );
var h22 = matrix.at( 2, 2 );
if ( 1 + h22 == 1 )
   throw new Error( "Zero or insignificant transformation scale." );

var window = ImageWindow.activeWindow;
if ( window.isNull )
   throw Error( "No image window." );
var sourceImage = window.mainView.image;

var targetWindow = new ImageWindow (
    sourceImage.width, sourceImage.height, sourceImage.numberOfChannels,
    sourceImage.bitsPerSample,
    sourceImage.sampleType == SampleType_Real,
    sourceImage.colorSpace != ColorSpace_Gray,
    "projected"
);
var targetView = targetWindow.currentView;
var targetImage = targetView.image;

targetView.beginProcess();

targetImage.fill( backgroundColor );

console.show();
console.writeln( "<end><cbr><br><b>" + ImageWindow.activeWindow.mainView.id + "</b>" );
console.abortEnabled = true;

targetImage.statusEnabled = true;
targetImage.initializeStatus( "Homographic projection",
                              targetImage.bounds.area*targetImage.numberOfChannels );

/*
 * Interpolate target image by inverse coordinate mapping.
 */
for ( var ch = 0; ch < targetImage.numberOfChannels; ++ch )
{
   targetImage.initSampleIterator( targetImage.bounds, ch );

   for ( var y = 0; y < targetImage.height; ++y )
   {
      var h01yh02 = h01*y + h02;
      var h11yh12 = h11*y + h12;
      var h21yh22 = h21*y + h22;

      for ( var x = 0; x < targetImage.width; ++x, targetImage.nextSample() )
      {
         var w  =  h20*x + h21yh22;
         var x0 = (h00*x + h01yh02)/w;
         var y0 = (h10*x + h11yh12)/w;

         // Assert x0 and y0 are within source image bounds
         if ( x0 >= 0 && y0 >= 0 && x0 < sourceImage.width && y0 < sourceImage.height )
            targetImage.setSampleValue( sourceImage.interpolate( x0, y0, ch ) );
      }

      targetImage.advanceStatus( targetImage.width );
   }
}

targetView.endProcess();

targetWindow.show();
targetWindow.zoomToOptimalFit();
targetWindow.bringToFront();

Simply replace the components of the H matrix at the top of the script with the ones that SA writes to the console, select the image that you want to transform, and run the script. You may have to crop the transformed image to the same dimensions of the reference image; the script cannot do this automatically. This is easy if you use SA matrices, since then the transformed image will match the reference image at {0,0} (= top left corner).

Let me know if this helps.

(Edited: Replaced script with a new version with better error checking)
« Last Edit: 2013 October 07 12:55:51 by Juan Conejero »
Juan Conejero
PixInsight Development Team
http://pixinsight.com/

Offline pfile

  • PTeam Member
  • PixInsight Jedi Grand Master
  • ********
  • Posts: 4729
Re: is there a way to extract the transformation that SA does?
« Reply #2 on: 2013 October 07 13:10:03 »
thanks! this will be useful.

you're implementing simple bilinear interpolation here, right? this should be fine for a mask or whatnot.

i will have to try it on some synthetic examples because the files i was working on are the ones that went away in the recent crash. not sure i have the patience to find and restore all of them from the .swp files...

thanks again,

rob

Offline mschuster

  • PTeam Member
  • PixInsight Jedi
  • *****
  • Posts: 1087
Re: is there a way to extract the transformation that SA does?
« Reply #3 on: 2013 October 07 13:15:33 »
This is useful for me also.

Would it be possible for SA to print more digits of precision for the matrix coefs?

As it is now, 1 part in 10000 for the scaling coefs on a 4k image is about 0.4px. Sometimes rms alignment errors are less than 0.4px, so more digits might help reuse accuracy slightly.

Also, maybe a script could be written to do the initial SA itself and then get full double precision accuracy on the matrix from a process parameter?

I would like to reuse the matrix to try aligning my master flat on a per sub basis to see if per pixel weighting helps at all in my integrations (Ignacio's post). I want to combine the current II per frame scale and noise weighting scheme with an additional per pixel multiplicative factor, in Matlab as a quick test.

Thanks,
Mike