Author Topic: Can anyone with JSR experience tell me how to achieve this simple Histogram process ?  (Read 7189 times)

Offline Niall Saunders

  • PTeam Member
  • PixInsight Jedi Knight
  • *****
  • Posts: 1456
  • We have cookies? Where ?
Hi all,

I am trying to call a simple Histo instance from within a JSR script. I can do this with 'fixed' parameters, but really want to be able to use 'dynamic' parameters instead.

What I am trying to achieve is the ability to call a Histo instance that clips my RGB image to the 'edges' of each channel's histogram (with NO loss of pixel data)

The code I thought I would be able to use 'doesn't work' (no surprises there  :cry: )
Quote

         var RdMin = ImageStatistics.minimum(outputImage[0]); // minimum value of the Rd channel
         var RdMax = ImageStatistics.maximum(outputImage[0]); // maximum value of the Rd channel

         var GnMin = ImageStatistics.minimum(outputImage[1]); // minimum value of the Gn channel
         var GnMax = ImageStatistics.maximum(outputImage[1]); // maximum value of the Gn channel

         var BuMin = ImageStatistics.minimum(outputImage[2]); // minimum value of the Bu channel
         var BuMax = ImageStatistics.maximum(outputImage[2]); // maximum value of the Bu channel

         // apply histogram transformation
         var clipEdgesNoLosses = new HistogramTransformation;

         with ( clipEdgesNoLosses )
         {
            H = // shadows, midtones, highlights, rescale0, rescale1
            [
            [RdMin, 0.5, RdMax, 0.0, 1.0], // red
            [GnMin, 0.5, GnMax, 0.0, 1.0], // green
            [BuMin, 0.5, BuMax, 0.0, 1.0], // blue
            [ 0.0 , 0.5,  1.0 , 0.0, 1.0], // luminance (RGB)
            [ 0.0 , 0.5,  1.0 , 0.0, 1.0]  // alpha
            ];

            executeOn(outputView);
         }


What do I need to use for the (e.g.) RdMin variable?

Is there an entirely more efficient method of calling an instance that will do what I am looking for?

Thanks in advance,
Cheers,
Niall Saunders
Clinterty Observatories
Aberdeen, UK

Altair Astro GSO 10" f/8 Ritchey Chrétien CF OTA on EQ8 mount with homebrew 3D Balance and Pier
Moonfish ED80 APO & Celestron Omni XLT 120
QHY10 CCD & QHY5L-II Colour
9mm TS-OAG and Meade DSI-IIC

Offline Juan Conejero

  • PTeam Member
  • PixInsight Jedi Grand Master
  • ********
  • Posts: 7111
    • http://pixinsight.com/
Hi Niall,

Your code is 100% correct, but it doesn't work because HistogramTransformation parameters don't work as you think :)

The shadows clipping point, midtones balance and highlights clipping point columns of the H table parameter are all expressed in the [0,1] range. Note that these three values are independent from the existing extreme values in the target image. This is the power of HistogramTransformation --well, this is the power of PixInsight, actually :)

As long as shadows=0 and highlights=1, there will be no clipping at all. So you just don't need to do an HistogramTransformation!

I guess what you want is to rescale the image without clipping it. Try this one:

Code: [Select]
outputView.beginProcess( UndoFlag_NoSwapFile ); // don't generate any swap file
outputView.image.rescale();
outputView.endProcess();


rescale() performs a linear rescaling operation to redistribute all existing pixel values within the [0,1] range. Note that rescale() takes into account the existing minimum and maximum values in all nominal channels, so it won't change the existing color balance in the image.

Along with rescale(), we also have normalize(). Normalization is a conditional rescaling operation: the image is rescaled only if it contains pixel values outside [0,1]; otherwise, nothing is done.

Finally, note that rescale() and normalize() only make sense for floating point images, since integer images are bounded by nature.

Is this what you want, or am I missing anything?
Juan Conejero
PixInsight Development Team
http://pixinsight.com/

Offline Niall Saunders

  • PTeam Member
  • PixInsight Jedi Knight
  • *****
  • Posts: 1456
  • We have cookies? Where ?
Hi Juan,

When I complete my deBayer routine, I (obviously) end up with an RGB tri-colour image.
The last thing I do (at the moment) before saving to disk, is to issue a <rescale()> command.

However, if I then open that image in PI, and the open a Histogram process, I find that I can ALWAYS, ALWAYS, throw a 'clip to shadows' and 'clip to highlights' command at the image, and I will ALWAYS get an 'expansion' of the R, G and B histo-curves to fit the full 0 to 1 range.

It do this, manually, by clicking on the appropriate buttons within the Histo dialog, whilst looking at the RGB/K panel. The results that I then see if I examine the individual R, G or B panels are exactly the same as had I clicked the 'clip to min' and 'clip to max' buttons on each individual colour panel. They are also exactly the same as had I looked at the Image Statistics window for the image, and 'copied and pasted' the Min and Max values over, for each colour plane.

Certainly, some of the Max/Min values might actually already be AT either '0.0', or '1.0' - but they will not ALL be thus.

I have proved, empirically, that my best deBayer results come from this Histo Expansion, followed by a PixelMath step that aligns all the R, G and B 'median' to the 'highest' median of the trio, followed by an empirically derived 'Hue' Curve derived on the camera that actually gathered the data in the first place.

Certainly, with these three steps, I can recreate almost PERFECT colours from a 'daylight-exposed' image - and I am trying to establish whether this approach is valid for astro-imaging as well (it seems a reasonably hypothesis to me anyway, as I cannot see how the camera would know WHERE the incoming photons were coming from, all it can do is count such photons as they arrive, withing the constraints of the exposure time)

So, what I need to be able to do is to determine the Min and Max values for each colour plane, and to pass these values to the H array for the Histo process.

I do NOT believe that 'rescale()' is the answer to this problem.

In any case, I would also like to know how to access 'any' of the parameters available from the 'ImageStatistics' property - I am sure that this ability may well be of use in other applications that I have in mind.

Cheers,
Cheers,
Niall Saunders
Clinterty Observatories
Aberdeen, UK

Altair Astro GSO 10" f/8 Ritchey Chrétien CF OTA on EQ8 mount with homebrew 3D Balance and Pier
Moonfish ED80 APO & Celestron Omni XLT 120
QHY10 CCD & QHY5L-II Colour
9mm TS-OAG and Meade DSI-IIC

Offline Niall Saunders

  • PTeam Member
  • PixInsight Jedi Knight
  • *****
  • Posts: 1456
  • We have cookies? Where ?
Juan, anyone?

I am basically 'stuck' at this point - until someone can tell me how to extract the Max, Min values for each channel of an image.

Can anyone help?

Cheers,
Cheers,
Niall Saunders
Clinterty Observatories
Aberdeen, UK

Altair Astro GSO 10" f/8 Ritchey Chrétien CF OTA on EQ8 mount with homebrew 3D Balance and Pier
Moonfish ED80 APO & Celestron Omni XLT 120
QHY10 CCD & QHY5L-II Colour
9mm TS-OAG and Meade DSI-IIC

Offline Juan Conejero

  • PTeam Member
  • PixInsight Jedi Grand Master
  • ********
  • Posts: 7111
    • http://pixinsight.com/
Hi Niall,

Morning! Sorry, I'm a bit slow in my answers here. The Image object has a number of methods that provide direct pixel statistics. An example:

Code: [Select]
var img = new Image
// ...
var mn = img.minimum(); // minimum sample value
var mx = img.maximum(); // maximum sample value
var md = img.median(); // median
var av = img.mean(); // arithmetic mean
var sd = img.stdDev(); // standard deviation


and, in PI 1.5, you'll also have:

Code: [Select]
var ad = img.avgDev(); // average median deviation

Of course, all values are provided in the [0,1] range for all pixel data types. The values are calculated for the current image selection. For example, if you want to calculate the median of the blue channel (assuming img is a RGB color image):

Code: [Select]
img.selectedChannel = 2;
var md = img.median(); // median of channel #2


Furthermore, you can also define a rectangular ROI (region of interest) and a range of image channels:

Code: [Select]
img.selectedChannel = 1; // select green channel
img.selectedRect = new Rect( 10, 15, 250, 375 ); // define a ROI
var md = img.median(); // median of ROI in channel #1
// ...
img.resetRectSelection(); // forget ROI and re-select the entire image
img.firstSelectedChannel = 0; // select a channel range from red
img.lastSelectedChannel = 1; // to green
var md = img.median();
// ...
img.resetSelections(); // reset all selections: no ROI and all channels


Along with direct image statistics, there is also the ImageStatistics object. You use ImageStatistics as in the following example:

Code: [Select]
var img = new Image;
// ...
var stats = new ImageStatistics( img );
console.writeln( "The median is: %.5f", stats.median );
// ...
stats.generate( img ); // you can reuse a ImageStatistics object
console.writeln( "Now the median is: %.5f", stats.median );


As happens with direct statistics, ImageStatistics performs its calculations for the current image selection (ROI and channel range).

Hope this helps.
Juan Conejero
PixInsight Development Team
http://pixinsight.com/

Offline Niall Saunders

  • PTeam Member
  • PixInsight Jedi Knight
  • *****
  • Posts: 1456
  • We have cookies? Where ?
Thanks Juan,

As always, you have answered with exactly what I am after  :D

Of course, I can't wait to get back to the PC to implement the changes.

Cheers,
Cheers,
Niall Saunders
Clinterty Observatories
Aberdeen, UK

Altair Astro GSO 10" f/8 Ritchey Chrétien CF OTA on EQ8 mount with homebrew 3D Balance and Pier
Moonfish ED80 APO & Celestron Omni XLT 120
QHY10 CCD & QHY5L-II Colour
9mm TS-OAG and Meade DSI-IIC