Author Topic: Removing Canon Banding with PJSR  (Read 58017 times)

Offline vicent_peris

  • PTeam Member
  • PixInsight Padawan
  • ****
  • Posts: 988
    • http://www.astrofoto.es/
Re: Removing Canon Banding with PJSR
« Reply #30 on: 2009 May 30 12:27:05 »
Hi,

last night I went to be, and when I was almost sleeping I came to a possible solution to this problem. :)

My idea is to calculate the average value of each pixel row. Then, you substract, from this unidimensional function, the smaller wavelet layers, wich will be representatives of the banding. :)

As we cannot make an unidimensional wavelet transform, we can generate an image from this calculated pixel column. This image would be one with "cloned" columns. Thus, we can make a bidimensional wavelet transform to extract banding.

My intuition says me that this method will have some problems. I can see some solutions a priori... but I need to see how it works. I think for the moment it can be a good starting point.


What do you think?
Regards,
Vicent.

Offline georg.viehoever

  • PTeam Member
  • PixInsight Jedi Master
  • ******
  • Posts: 2132
Re: Removing Canon Banding with PJSR
« Reply #31 on: 2009 June 06 03:23:32 »
Vincent,

sounds interesting. But I am not sure if I understand what the advantage compared to the currently implemented method would be. Can you explain a bit?

Georg
Georg (6 inch Newton, unmodified Canon EOS40D+80D, unguided EQ5 mount)

Offline georg.viehoever

  • PTeam Member
  • PixInsight Jedi Master
  • ******
  • Posts: 2132
Re: Removing Canon Banding with PJSR
« Reply #32 on: 2009 June 07 14:55:46 »
Juan,

can you share the sources for the Scrollbox script that you used in http://pixinsight.com/forum/index.php?topic=1159.msg5786#msg5786 ? I did not find an example in the PI distribution.

Georg
Georg (6 inch Newton, unmodified Canon EOS40D+80D, unguided EQ5 mount)

Offline Juan Conejero

  • PTeam Member
  • PixInsight Jedi Grand Master
  • ********
  • Posts: 7111
    • http://pixinsight.com/
Re: Removing Canon Banding with PJSR
« Reply #33 on: 2009 June 07 15:02:43 »
Sure thing:

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

function MyTabPageControl( parent )
{
   this.__base__ = ScrollBox;
   if ( parent )
      this.__base__( parent );
   else
      this.__base__();

   this.bmp = TranslucentPlanets( planetsData );

   this.autoScroll = true;
   this.tracking = true;

   this.initScrollBars = function()
   {
      this.pageWidth = this.bmp.width;
      this.pageHeight = this.bmp.height;
      this.setHorizontalScrollRange( 0, Math.max( 0, this.bmp.width - this.viewport.width ) );
      this.setVerticalScrollRange( 0, Math.max( 0, this.bmp.height - this.viewport.height ) );
      this.viewport.update();
   };

   this.viewport.onResize = function()
   {
      this.parent.initScrollBars();
   };

   this.onHorizontalScrollPosUpdated = function( x )
   {
      this.viewport.update();
   };

   this.onVerticalScrollPosUpdated = function( y )
   {
      this.viewport.update();
   };

   this.viewport.onPaint = function( x0, y0, x1, y1 )
   {
      var g = new Graphics( this );
      g.fillRect( x0, y0, x1, y1, new Brush( 0xff000000 ) );
      g.drawBitmap( this.parent.scrollPosition.symmetric(), this.parent.bmp );
      g.end();
   };

   this.initScrollBars();
}

MyTabPageControl.prototype = new ScrollBox;

function MyTabbedDialog()
{
   this.__base__ = Dialog;
   this.__base__();

   this.pages = new Array;
   this.pages.push( new MyTabPageControl( this ) );
   this.pages.push( new MyTabPageControl( this ) );
   this.pages.push( new MyTabPageControl( this ) );
   this.pages.push( new MyTabPageControl( this ) );

   this.tabs = new TabBox( this );
   this.tabs.setMinSize( 400, 400 );
   this.tabs.addPage( this.pages[0], "First" );
   this.tabs.addPage( this.pages[1], "Second" );
   this.tabs.addPage( this.pages[2], "Third" );
   this.tabs.addPage( this.pages[3], "Fourth" );

   this.okButton = new PushButton( this );
   this.okButton.text = "OK";
   this.okButton.onClick = function()
   {
      this.dialog.ok();
   }

   // Group the three buttons into a horizontal row
   this.buttons = new HorizontalSizer;
   this.buttons.addStretch();
   this.buttons.add( this.okButton );

   // Setup the dialog layout.
   this.sizer = new VerticalSizer;
   this.sizer.margin = 6;
   this.sizer.spacing = 6;
   this.sizer.add( this.tabs );
   this.sizer.add( this.buttons );

   // Set the dialog title and geometry
   this.windowTitle = "ScrollBox Test Script";
   this.adjustToContents();
   //this.setFixedSize(); // don't allow the user to resize this dialog
}

MyTabbedDialog.prototype = new Dialog;

/**
 * The TranslucentPlanetsData object defines functional parameters for the
 * TranslucentPlanets routine.
 */
function TranslucentPlanetsData()
{
   this.size = 800;                   // Size in pixels of the generated image
   this.maxRadius = 60;               // Maximum planet radius
   this.numberOfPlanets = 120;        // Number of translucent planets
   this.networkFrequency = 25;        // Frequency of network lines
   this.skyTopColor = 0xff000000;     // Top background color (solid black by default)
   this.skyBottomColor = 0xff000050;  // Bottom background color (dark blue by default)
   this.networkColor = 0xffff8000;    // Network color (solid orange by default)
   this.networkBkgColor = 0xff000000; // Network background color (solid black by default)
   this.planetTransparency = 0x80;    // Alpha value of all random planet colors
}

// Global TranslucentPlanets parameters.
var planetsData = new TranslucentPlanetsData;

/**
 * Renders a TranslucentPlanets scene as a newly created bitmap.
 */
function TranslucentPlanets( data )
{
   function ARGBColor( r, g, b )
   {
      return (data.planetTransparency << 24) | (r << 16) | (g << 8) | b;
   }

   // Working bitmap
   var bmp = new Bitmap( data.size, data.size );

   // Create a graphics context to draw on our working bitmap
   var g = new Graphics( bmp );

   // We want high-quality antialiased graphics
   g.antialiasing = true;

   // Fill the background with a linear gradient
   var lg = new LinearGradientBrush( new Point( 0 ), new Point( bmp.height ),
                                     [[0, data.skyTopColor], [1, data.skyBottomColor]] );
   g.fillRect( bmp.bounds, lg );

   // Draw random circles
   for ( var i = 0; i < data.numberOfPlanets; ++i )
   {
      // Random colors in the range [0,255]
      var red = Math.round( 255*Math.random() );
      var green = Math.round( 255*Math.random() );
      var blue = Math.round( 255*Math.random() );

      // Avoid too dark circles
      if ( red < 24 && green < 24 && blue < 24 )
      {
         --i;
         continue;
      }

      // 32-bit AARRGGBB color values
      var color1 = ARGBColor( red, green, blue );
      var color2 = ARGBColor( red >> 1, green >> 1, blue >> 1 );

      // Random center and radius
      var center = new Point( data.size*Math.random(), data.size*Math.random() );
      var radius = data.maxRadius*Math.random();

      // Define working objects
      g.pen = new Pen( color2 );
      g.brush = new RadialGradientBrush( center, radius, center, [[0, color1], [1, color2]] );

      // Draw this planet
      g.drawCircle( center, radius );
   }

   // Erase the network region by drawing a dense network
   g.antialiasing = false;
   g.pen = new Pen( data.networkBkgColor );
   for ( var i = 0; i < data.size; ++i )
      g.drawLine( i-1, data.size, -1, i+1 );

   // Generate the network
   g.antialiasing = true;
   g.pen = new Pen( data.networkColor );
   for ( var i = 0; i < data.size; i += data.networkFrequency )
      g.drawLine( i, data.size-1, 0, i );
   g.drawLine( data.size-1, data.size-1, 0, data.size-1 );

   // End painting
   g.end();

   return bmp;
}

var dlg = new MyTabbedDialog;
dlg.execute();

Happy coding! ;)
Juan Conejero
PixInsight Development Team
http://pixinsight.com/

Offline vicent_peris

  • PTeam Member
  • PixInsight Padawan
  • ****
  • Posts: 988
    • http://www.astrofoto.es/
Re: Removing Canon Banding with PJSR
« Reply #34 on: 2009 June 07 15:11:34 »
Vincent,

sounds interesting. But I am not sure if I understand what the advantage compared to the currently implemented method would be. Can you explain a bit?

Georg


Hi,

it's not a matter of advantages... it's simply, perhaps, a different way to solve the same problem.


Vicent.

Offline georg.viehoever

  • PTeam Member
  • PixInsight Jedi Master
  • ******
  • Posts: 2132
Bug in PJSR, or in my head? Re: Removing Canon Banding with PJSR
« Reply #35 on: 2009 June 08 09:33:06 »
Juan,

I am working to convert the script to work with ScrollBox based previews. However, I cannot get the script working properly. Something fails in applying corrective factors to an image. The following code has been reduced to the essentials, just adding 1.0 to all channels. However, as can be seen in the attached screenshot, only the red channel is changed, and by no means all red pixels as I would expect from the code. Can you have a look to make sure this is not a PI bug, and confirm that it is a bug in my head  ;) ?

Thanks,
Georg

Code: [Select]
function main(){
      var window = ImageWindow.activeWindow;
      var targetView=window.currentView;
      var targetImage=targetView.image;
      targetView.beginProcess();
      var resultImage=new Image( targetImage.width, targetImage.height,
                                 targetImage.numberOfChannels, targetImage.colorSpace,
                                 (targetImage.bitsPerSample < 32) ? 32 : 64, SampleType_Real );
      targetImage.resetSelections();
      resultImage.resetSelections();
      resultImage.assign(targetImage);
      var iResultHeight=resultImage.height;
      var lineRect=new Rect(resultImage.width,1);
      resultImage.resetSelections();
      // for each channel
      for (var chan=0; chan<resultImage.numberOfChannels;++chan){
            resultImage.selectedChannel=chan;
            // and each row
            for (var row=0; row<iResultHeight;++row) {
               lineRect.moveTo(0,row);
               resultImage.selectedRect=lineRect;
               resultImage.apply(1.0,ImageOp_Add);
            }  //for row
         }  //for channel
      resultImage.resetSelections();
      targetImage.resetSelections();
      targetImage.assign( resultImage );
      // end transaction
      targetView.endProcess();
}

main();

Georg (6 inch Newton, unmodified Canon EOS40D+80D, unguided EQ5 mount)

Offline Juan Conejero

  • PTeam Member
  • PixInsight Jedi Grand Master
  • ********
  • Posts: 7111
    • http://pixinsight.com/
Re: Removing Canon Banding with PJSR
« Reply #36 on: 2009 June 08 10:04:25 »
Hi Georg,

Your code snippet works fine (provided you #include <pjsr/SampleType.jsh> and <pjsr/ImageOp.jsh>).

Bear in mind that all real images are naturally bounded to the [0,1] range in PixInsight. A real image can indeed have values outside [0,1], but then it won't be correctly represented on the screen. The screen rendering engine expects all real images bounded to [0,1], and translates [0,1] to [0,255] to generate screen bitmaps. In other words, real values outside [0,1] are accepted but cause overflow and hence invalid screen renditions.

In addition, the PJSR uses the [0,1] virtual range for all pixel sample types. This allows you to work in a homogeneous way that is independent on data types. The PCL/C++ framework uses templates to manage different data types uniformly, but this is not possible in JavaScript, hence the need for a virtual representation.

Since you are adding 1.0, you are surely exceeding the [0,1] range. You just need to call Image.rescale() at the end of your process (before representing your image into a Bitmap) to rescale everything to [0,1].

Does this make sense? :)
Juan Conejero
PixInsight Development Team
http://pixinsight.com/

Offline georg.viehoever

  • PTeam Member
  • PixInsight Jedi Master
  • ******
  • Posts: 2132
Re: Removing Canon Banding with PJSR
« Reply #37 on: 2009 June 08 10:21:15 »
Juan,

I am afraid it does not make sense for me. I zoomed into the lower left of the image. If you compare the left unprocessed image to the right one (see new attachement), you see that most pixels did not change their value at all. In many cases, the R channel did not change at all. And I could not find  a case where G or B changed at all. I dont see how this matches with what you expect. I appears to me that if R=1.0, then any operation to G or B dont happen.

Georg
Georg (6 inch Newton, unmodified Canon EOS40D+80D, unguided EQ5 mount)

Offline Juan Conejero

  • PTeam Member
  • PixInsight Jedi Grand Master
  • ********
  • Posts: 7111
    • http://pixinsight.com/
Re: Removing Canon Banding with PJSR
« Reply #38 on: 2009 June 08 10:49:12 »
Hi Georg,

I've just made a test and Image.apply() seems to work correctly. This is the test script (a slightly modified version of your initial snippet):

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

var valuesToAdd = [ -0.1, +0.1, +0.2 ];

function main(){
      var window = ImageWindow.activeWindow;
      var targetView=window.currentView;
      var targetImage=targetView.image;
      targetView.beginProcess();
      var resultImage=new Image( targetImage.width, targetImage.height,
                                 targetImage.numberOfChannels, targetImage.colorSpace,
                                 (targetImage.bitsPerSample < 32) ? 32 : 64, SampleType_Real );
      targetImage.resetSelections();
      resultImage.resetSelections();
      resultImage.assign(targetImage);
      var iResultHeight=resultImage.height;
      var lineRect=new Rect(resultImage.width,1);
      resultImage.resetSelections();
      // for each channel
      for (var chan=0; chan<resultImage.numberOfChannels;++chan){
            resultImage.selectedChannel=chan;
            // and each row
            for (var row=0; row<iResultHeight;++row) {
               lineRect.moveTo(0,row);
               resultImage.selectedRect=lineRect;
               resultImage.apply( valuesToAdd[chan], ImageOp_Add );  /* ### */
            }  //for row
         }  //for channel
      resultImage.resetSelections();
      targetImage.resetSelections();
      targetImage.assign( resultImage );
      // end transaction
      targetView.endProcess();
}

main();

See the attached screenshot. The image to the left (test1) has been generated with NewImage as a RGB image with initial values R=0.25, G=0.5, B=0.75. The test2 image is a copy of test1 after applying the above script. The final values are R=0.15, G=0.6, B=0.95, as expected (see the valuesToAdd array).

(To further help you, I'd need to see your code)TM
Juan Conejero
PixInsight Development Team
http://pixinsight.com/

Offline georg.viehoever

  • PTeam Member
  • PixInsight Jedi Master
  • ******
  • Posts: 2132
Re: Removing Canon Banding with PJSR
« Reply #39 on: 2009 June 08 11:12:45 »
Juan,

thanks for the help. The code appears to work properly after I added a
Code: [Select]
resultImage.normalize();
The problem seems to be that when there are RGB values that are outside of [0,1], the rendering on the screen appears to work in unexpected ways (or is it assign() that clips values, I did not investigate). When hovering over pixels with the mouse pointer, the values for RGB displayed in the PI status line never exceeded values of 1.0. I guess this is why I never suspected this was a problem.

Thanks again!

Georg
Georg (6 inch Newton, unmodified Canon EOS40D+80D, unguided EQ5 mount)

Offline georg.viehoever

  • PTeam Member
  • PixInsight Jedi Master
  • ******
  • Posts: 2132
Juan,

I have now succeeded in creating a scrollbox that shows a basic preview of the resulting image. Unfortunately, I do have a problem as soon as I begin to move the "Amount" slider. The system becomes unresponsive, and after a while I get all kinds of problems, such as GUI elements that dont work any longer, or a "PCL Win 32 System Exception: At address 20202020 with exception code C000005: Access violation : invalid memory write operation at address 20202020" and PI no longer responds.

My gut feeling is that the system is flodded with events, to which it cannot respond properly due to the calculations done. However, it may be something different, and I dont know of a remedy yet. Please have a look at the attached script, and tell me how to work around this issue.

Thanks,
Georg

Note: This version of the script is not yet recommended for general use!
Georg (6 inch Newton, unmodified Canon EOS40D+80D, unguided EQ5 mount)

Offline Juan Conejero

  • PTeam Member
  • PixInsight Jedi Grand Master
  • ********
  • Posts: 7111
    • http://pixinsight.com/
Re: Removing Canon Banding with PJSR
« Reply #41 on: 2009 June 08 15:30:23 »
Hi georg,

Hmmm, this is interesting. Your code is causing a freeze of the JavaScript runtime. This should *never* happen! It seems (although it isn't apparent) that you're doing something very complex in your BandingEngine.doResult() routine. I need to analyze your code in detail. Be sure we'll catch the problem, of course ;)

Thanks for pushing the things to the limit --that's the only way to improve!
Juan Conejero
PixInsight Development Team
http://pixinsight.com/

Offline Fco. Bosch

  • Member
  • *
  • Posts: 66
Re: Removing Canon Banding with PJSR
« Reply #42 on: 2009 June 09 16:03:17 »
Hey Georg! In your sript for removing Canon banding I have obtained the following error:

run -x=auto C:/PCL/src/scripts/CanonBanding.js
Processing script file: C:/PCL/src/scripts/CanonBanding.js
Canon Banding Script started
Canon Banding Script computing
Writing swap files...
38.20 MB/s
*** Error [000]: C:/PCL/src/scripts/CanonBanding.js, line 106: ImageStatistics.Set(): invalid argument type: boolean value expected..
Reading swap files...
38.60 MB/s

I can`t interpret it ...

Thank you!

Fco. Bosch

Offline georg.viehoever

  • PTeam Member
  • PixInsight Jedi Master
  • ******
  • Posts: 2132
Re: Removing Canon Banding with PJSR
« Reply #43 on: 2009 June 10 00:29:02 »
Hi Fco.,

it is this line in the code:
Code: [Select]
           highRejectionEnabled=doHighlightProtect;

Somehow (I cannot reproduce it here), the value of "doHighlightProtect" is undefined. It is usually set to "true" or "false" when you toggle the "Do Higlight Protect" box in the dialog. Try toggleing the box. If everything fails, set the value to a constant by modifying the code:
Code: [Select]
           highRejectionEnabled=false; // or true

I am working on a new version of the script, and I hope the issue disappears with the new version.

Georg
Georg (6 inch Newton, unmodified Canon EOS40D+80D, unguided EQ5 mount)

Offline Fco. Bosch

  • Member
  • *
  • Posts: 66
Re: Removing Canon Banding with PJSR
« Reply #44 on: 2009 June 10 09:02:23 »
HI Georg!
I have changed the line 106 including the constant "=false", and it works very well. Otherwise, with "=true" the bands don't disappear...

I don't know why!!   :o

Thanks you!!
Fco. Bosch