Author Topic: New Script: Batch Automatic STF Stretch  (Read 13461 times)

Offline Juan Conejero

  • PTeam Member
  • PixInsight Jedi Grand Master
  • ********
  • Posts: 7111
    • http://pixinsight.com/
New Script: Batch Automatic STF Stretch
« on: 2010 July 30 04:02:27 »
Hi all,

In response to many user requests, here is a simple script that applies automatic STFs to all open images (main views only). Tired of clicking the "A" button? Just open your raw images and run the script. Automatic screen stretch made easy!

At the beginning of the script you can find three macro definitions: SHADOWS_CLIP, TARGET_BKG and RGB_LINK, whose meanings are explained in code comments. These define the script's operating parameters. Their values are the default values applied by the standard ScreenTransferFunction tool, so you normally won't need to change them.

Just a word of caution. If your machine is on the slow side and you have a lot of images open, please be patient as the script can't be interrupted. However this shouldn't cause any practical problems unless you open really many images, say 100 or so.

Enjoy!

EDIT (2013 August 12): Two years ago I discovered that the MTF function is nicely invertible. An MTF function with midtones balance parameter m is given by:


The above equation can be derived from the Bulirsch-Stoer algorithm (see for example R. Bulirsch, J. Stoer et al., Introduction to Numerical Analysis, Third Edition, Springer, 2010, sect. 2.2) for evaluation of the diagonal rational function, given the three fixed data points of the MTF function.

The inverse problem to solve in this script is as follows: Given input and output background values b0 and b1, respectively, find the required midtones balance mb for the MTF function such that:

b1 = MTF( b0, mb )

It can be shown that the answer is:

mb = MTF( b1, b0 )

Before discovering this nice property, we were using a binary search algorithm to find the value of mb. I have updated the script below accordingly (sorry for not having done this before, but I overlooked this post). The original binary search routine is left commented for "historical reasons" :)

Code: [Select]
/*
 * AutoSTF
 *
 * A simple script to apply automatic screen transfer functions (STF) to all
 * open images.
 *
 * Copyright (C) 2010-2013, Pleiades Astrophoto S.L.
 * Written by Juan Conejero (PTeam)
 */

#feature-id    Utilities > AutoSTF

#feature-info  A script that applies automatic screen transfer functions (STF) \
   to all open images.<br/>\
   <br/>\
   Written by Juan Conejero (PTeam)<br/>\
   Copyright (C) 2010-2013 Pleiades Astrophoto

/*
 * Default STF Parameters
 */

// Shadows clipping point measured in sigma units from the main histogram peak.
#define SHADOWS_CLIP -1.25

// Target background in the [0,1] range.
#define TARGET_BKG    0.25

// Whether to apply the same STF to all channels, or treat each channel separately.
#define RGB_LINK      true

/*
 * Find a midtones balance value that transforms v1 into v0 through a midtones
 * transfer function (MTF), within the specified tolerance eps.
 *
 * ### This routine is no longer used - See the following forum thread for more
 * information:
 *    http://pixinsight.com/forum/index.php?topic=2116
 */
 /*
function findMidtonesBalance( v0, v1, eps )
{
   if ( v1 <= 0 )
      return 0;

   if ( v1 >= 1 )
      return 1;

   v0 = Math.range( v0, 0.0, 1.0 );

   if ( eps )
      eps = Math.max( 1.0e-15, eps );
   else
      eps = 5.0e-05;

   var m0, m1;
   if ( v1 < v0 )
   {
      m0 = 0;
      m1 = 0.5;
   }
   else
   {
      m0 = 0.5;
      m1 = 1;
   }

   for ( ;; )
   {
      var m = (m0 + m1)/2;
      var v = Math.mtf( m, v1 );

      if ( Math.abs( v - v0 ) < eps )
         return m;

      if ( v < v0 )
         m1 = m;
      else
         m0 = m;
   }
}
 */

/*
 * STF Auto Stretch routine
 */
function ApplyAutoSTF( view, shadowsClipping, targetBackground, rgbLinked )
{
   var stf = new ScreenTransferFunction;

   var n = view.image.isColor ? 3 : 1;

   if ( rgbLinked )
   {
      /*
       * Try to find how many channels look as channels of an inverted image.
       * We know a channel has been inverted because the main histogram peak is
       * located over the right-hand half of the histogram. Seems simplistic
       * but this is consistent with astronomical images.
       */
      var invertedChannels = 0;
      for ( var c = 0; c < n; ++c )
      {
         view.image.selectedChannel = c;
         if ( view.image.median() > 0.5 )
            ++invertedChannels;
      }
      view.image.resetSelections();

      if ( invertedChannels < n )
      {
         // Noninverted image

         var c0 = 0;
         var m = 0;
         for ( var c = 0; c < n; ++c )
         {
            view.image.selectedChannel = c;
            var median = view.image.median();
            var avgDev = view.image.avgDev();
            c0 += median + shadowsClipping*avgDev;
            m  += median;
         }
         view.image.resetSelections();
         c0 = Math.range( c0/n, 0.0, 1.0 );
         m = Math.mtf( targetBackground, m/n - c0 );

         stf.STF = [ // c0, c1, m, r0, r1
                     [c0, 1, m, 0, 1],
                     [c0, 1, m, 0, 1],
                     [c0, 1, m, 0, 1],
                     [0, 1, 0.5, 0, 1] ];
      }
      else
      {
         // Inverted image

         var c1 = 0;
         var m = 0;
         for ( var c = 0; c < n; ++c )
         {
            view.image.selectedChannel = c;
            var median = view.image.median();
            var avgDev = view.image.avgDev();
            m  += median;
            c1 += median - shadowsClipping*avgDev;
         }
         view.image.resetSelections();
         c1 = Math.range( c1/n, 0.0, 1.0 );
         m = 1 - Math.mtf( targetBackground, c1 - m/n );

         stf.STF = [ // c0, c1, m, r0, r1
                     [0, c1, m, 0, 1],
                     [0, c1, m, 0, 1],
                     [0, c1, m, 0, 1],
                     [0, 1, 0.5, 0, 1] ];
      }
   }
   else
   {
      var A = [ // c0, c1, m, r0, r1
               [0, 1, 0.5, 0, 1],
               [0, 1, 0.5, 0, 1],
               [0, 1, 0.5, 0, 1],
               [0, 1, 0.5, 0, 1] ];

      for ( var c = 0; c < n; ++c )
      {
         view.image.selectedChannel = c;
         var median = view.image.median();
         var avgDev = view.image.avgDev();

         if ( median < 0.5 )
         {
            // Noninverted channel
            var c0 = Math.range( median + shadowsClipping*avgDev, 0.0, 1.0 );
            var m  = Math.mtf( targetBackground, median - c0 );
            A[c] = [c0, 1, m, 0, 1];
         }
         else
         {
            // Inverted channel
            var c1 = Math.range( median - shadowsClipping*avgDev, 0.0, 1.0 );
            var m  = 1 - Math.mtf( targetBackground, c1 - median() );
            A[c] = [0, c1, m, 0, 1];
         }
      }

      stf.STF = A;

      view.image.resetSelections();
   }

   console.writeln( "<end><cbr/><br/><b>", view.fullId, "</b>:" );
   for ( var c = 0; c < n; ++c )
   {
      console.writeln( "channel #", c );
      console.writeln( format( "c0 = %.6f", stf.STF[c][0] ) );
      console.writeln( format( "m  = %.6f", stf.STF[c][2] ) );
      console.writeln( format( "c1 = %.6f", stf.STF[c][1] ) );
   }

   stf.executeOn( view );

   console.writeln( "<end><cbr/><br/>" );
}

function main()
{
   console.show();
   var images = ImageWindow.windows;
   for ( var i in images )
   {
      processEvents();
      ApplyAutoSTF( images[i].mainView, SHADOWS_CLIP, TARGET_BKG, RGB_LINK );
      processEvents();
   }
}

main();
« Last Edit: 2014 April 19 11:39:10 by Juan Conejero »
Juan Conejero
PixInsight Development Team
http://pixinsight.com/

Offline Jack Harvey

  • PTeam Member
  • PixInsight Padawan
  • ****
  • Posts: 975
    • PegasusAstronomy.com & Starshadows.com
Re: New Script: Batch Automatic STF Stretch
« Reply #1 on: 2010 July 30 06:34:05 »
Great  Thanks, this is handy
Jack Harvey, PTeam Member
Team Leader, SSRO/PROMPT Imaging Team, CTIO

Offline Nocturnal

  • PixInsight Jedi Council Member
  • *******
  • Posts: 2727
    • http://www.carpephoton.com
Re: New Script: Batch Automatic STF Stretch
« Reply #2 on: 2010 August 01 08:48:54 »
Interesting, the script seems to repeat the A functionality rather than reuse it from the STF process. You can't instantiate an STF object and call the appropriate method to do an automatic stretch?
Best,

    Sander
---
Edge HD 1100
QHY-8 for imaging, IMG0H mono for guiding, video cameras for occulations
ASI224, QHY5L-IIc
HyperStar3
WO-M110ED+FR-III/TRF-2008
Takahashi EM-400
PIxInsight, DeepSkyStacker, PHD, Nebulosity

Offline Jordi Gallego

  • PixInsight Addict
  • ***
  • Posts: 279
Re: New Script: Batch Automatic STF Stretch
« Reply #3 on: 2010 August 02 11:43:17 »
Thanks Juan, it is useful ;)
Jordi Gallego
www.astrophoto.es

Offline FunTomas

  • PixInsight Addict
  • ***
  • Posts: 135
    • Astrofoto.sk
Re: New Script: Batch Automatic STF Stretch
« Reply #4 on: 2013 August 07 13:54:21 »
I want to process a set of images (>300). I modified this script to apply HistogramTransformation (like Mike Schuster, but his script is no longer awailable for download).
When I try to run this script on opened image, everything is O.K.
When I run this modified script on ImageContainer, it fails. I made icon instance of script on desktop, and then drag and drop triangle icon from ImageContainer.

I prepared small script for testing what am I  doing wrong.

Code: [Select]
function main() {
   var av = ImageWindow.activeWindow;
   console.writeln("activeWindow ... ", av);
   if (av) {
      var img = av.mainView.image;
      console.writeln("isColor ... ", img.isColor);
      console.writeln("width x height ... ", img.width, " x ", img.height);
   }
}

Running this script on image container, img is undefined. Please help, if anybody know.

Offline Juan Conejero

  • PTeam Member
  • PixInsight Jedi Grand Master
  • ********
  • Posts: 7111
    • http://pixinsight.com/
Re: New Script: Batch Automatic STF Stretch
« Reply #5 on: 2013 August 12 01:40:07 »
Hi Tomas,

Try this:

Code: [Select]
function main() {
   var av = ImageWindow.activeWindow;
   console.writeln("activeWindow ... ", av);
   if (!av.isNull) {
      var img = av.mainView.image;
      console.writeln("isColor ... ", img.isColor);
      console.writeln("width x height ... ", img.width, " x ", img.height);
   }
}

main();

You have to use the ImageWindow.isNull property to check if a window is valid.
Juan Conejero
PixInsight Development Team
http://pixinsight.com/

Offline Juan Conejero

  • PTeam Member
  • PixInsight Jedi Grand Master
  • ********
  • Posts: 7111
    • http://pixinsight.com/
Re: New Script: Batch Automatic STF Stretch
« Reply #6 on: 2013 August 12 04:41:21 »
By the way, I have updated the original AutoSTF script that I published in this thread. See the first thread post for more information.
Juan Conejero
PixInsight Development Team
http://pixinsight.com/