Can you fix a heavy banding problem in my exposure?

I hope I did not come off as rude! I want to apologize if I did. I was unsure if arrows and circles would have been helpful, so I wrote some text.

Oh it’s not? Wow. From @mike3996 's darkframe (thanks for that!) I would still expect this method to somewhat help with offset problems at least. If the gain has row- and column-wise deviations, I guess a simple row-wise (colum wise) subtraction(division?) of the average probably won’t help.
I have in the back of my head that A1ex from MagicLantern had an octave/matlab script for tackling the problem somewhere…I’ll look what I can find, buit I don’t know if that script actually uses the dark pixel read-outs of canon raws (i.e. I don’t know if Leica saves those dark pixels in their DNG).

EDIT: found it. https://wiki.apertus.org/index.php/Pattern_Noise
It was A1ex but not on the magic lantern forum but for the apertus camera. That one uses an CMOSIS sensor, which, you guessed it, is also the designer of the sensor inside of the M240. Sooo, probably many things that were done for the apertus sensor could be helpful in this case!

I remember that the non-FLOSS nik-collection denoiser Dfine2 had an option to reduce banding, I don’t remember if that was actually helping much as Dfine2 was not particularily good at denoising (it was just okay). But I guess there are algorithms out there to tackle the problem.

kudos

1 Like

I had severe banding on my Canon 5D.

After that thread, I made some tests and shot many dark frames in a row.

What I found out is that the banding lines vary, which led me to think they could result from some kind of electronic interference waves.

After that, I kind of discarded darkframe subtraction, since the bands didn’t show a static pattern.

1 Like

Apparently this is called ‘dynamic row noise’, as per the above apertus link.
Mitigation strategies exploit either the black reference colums on sensor, specific denoising strategies or both and require a good black calibration. These apertus articles go into quite some detail regarding this. A super interesting read.

1 Like

FWIW, ART has a dynamic row noise filter, that applies ideas discussed in that wiki page. But this requires that the raw contains some columns that are not exposed (which are used to measure ‘optical black’). Canon files have them, but this dng file seems already cropped to the visible image size, so the technique is not applicable…

1 Like

I tried it on a Canon 5D black frame and, although it significantly changes the image, I didn’t noticed banding reduction:

_MG_4440.CR2 (10.0 MB)

Before:

After:

Hi, three things:

  1. line noise filter is a different thing
  2. the filter is not optimized for black frames, and it will not remove the banding completely. It might mitigate the more annoying aspects of it, but whether the results are acceptable depends also on the image
  3. more importantly, there is no data in ART’s camconst.json for the Canon 5D, so the filter does nothing in this case. You can try adding this to your user camconst.json (in $HOME/.config/ART, create one if not there) and see if it helps… it won’t do magic though
    {
        "make_model" : "CANON EOS 5D",
        "masked_areas" : [40, 4, 2950, 80]
    },
1 Like

Thanks.
Out of curiosity: what masked_areas stand for?

it’s (a portion of) an unexposed area of the sensor, used to compute the black level for the picture. Here’s an example:

3 Likes

Ooof, that’s a major bummer.
So unless someone has a specialized denoiser trying to tackle this, Leica users are left out when it comes to useful postprocessing of their raw files. Ouch.

I hope I did not come off as rude! I want to apologize if I did.

No problem, @PhotoPhysicsGuy. No offence taken.

@mike3996 showed a dark frame, which confirms that we don’t have a continuous bias within each row across the entire frame. There is a local bias. There is also, of course, random noise.

The local bias within rows might be useful for denoising. Statistics might be extracted from single frames, such as the lake scene, to do this.

A cruder method is:

Use dcraw to get the linear bayer image with no white balance or auto-orient anything:

%DCRAW% -W -r 1 1 1 1 -g 1 1 -D -d -t 0 -T -6 -O x.tiff MP003322.DNG

The result is “landscape” format. Chop the image into the four linear channels leic_R.tiff etc:

call %PICTBAT%gray2rggb x.tiff leic_XX.tiff

Now we denoise each channel as follows. We create a version that is blurred in one direction, vertically, with a Gaussian sigma of 4 pixels. Then we make an output that is the input leic_R.tiff etc but limited (clamped) to the minimum and maximum of a local 3x5 window in the blur. The min/max window could be 1x5, but making it wider reduces the obviousness of the blur.

%IMG7%magick leic_R.tiff -morphology Convolve Blur:0x4,90 +depth leic_bl_R.tiff
call %PICTBAT%limitMinMax leic_bl_R.tiff leic_R.tiff leic_nn_R.tiff 3x5

%IMG7%magick leic_G0.tiff -morphology Convolve Blur:0x4,90 +depth leic_bl_G0.tiff
call %PICTBAT%limitMinMax leic_bl_G0.tiff leic_G0.tiff leic_nn_G0.tiff 3x5

%IMG7%magick leic_G1.tiff -morphology Convolve Blur:0x4,90 +depth leic_bl_G1.tiff
call %PICTBAT%limitMinMax leic_bl_G1.tiff leic_G1.tiff leic_nn_G1.tiff 3x5

%IMG7%magick leic_B.tiff -morphology Convolve Blur:0x4,90 +depth leic_bl_B.tiff
call %PICTBAT%limitMinMax leic_bl_B.tiff leic_B.tiff leic_nn_B.tiff 3x5

Now we have four denoised images, we average the greens and apply a simple white-balancing, combine the channels, and convert from linear RGB to non-linear sRGB:

%IMG7%magick ^
  ( leic_nn_R.tiff -evaluate Multiply 2.47 ) ^
  ( leic_nn_G0.tiff leic_nn_G1.tiff -evaluate-sequence Mean ) ^
  ( leic_nn_B.tiff -evaluate Multiply 1.09 ) ^
  -combine ^
  -set colorspace RGB -colorspace sRGB ^
  +write leic_srgb.tiff ^
  -equalize ^
  leic_eq.tiff

I show a JPEG of the equalised version, leic_eq.tiff:


The result is not perfect. In the equalised version, some trace of the original banding is still visible, but it is massively reduced. Instead, we get some blurring in a direction parallel to the horizon. I suggest this isn’t an aesthetic problem in the water or clouds. It is a problem in the distant lights; a mask could solve that problem.

3 Likes

well, there’s a difference between becoming a “tripod person” and carrying one on the occasions you want to take photos in the middle of a cloudy night…

seeing as there’s basically no foreground here you easily could have taken this shot wide open to save yourself two stops though. Even if the Summicron isn’t all that sharp there (I would personally want to hope it is!) any degradation would have to be far less damaging to shot like this than having the ISO so high.

Oh, but this is taken wide open at f/2. The exif lies. :slight_smile:

1 Like

How local do you mean exactly? If I use a 900 pixel wide one-dimensional blur (I lack the means of just summing up along one direction, this is my silly workaround) for subtracting off of the original, I get a very good suppression of the line features. Sorry for the downsize and compression, uploading pictures of noise does naturally not compress well!

(If I do the same directional blur diagonally, the features persist as if doing a gaussian blur before subtraction)

Now of course this is just the darkframe and the banding features are visible at higher pixel illumination, hence I think there is a gain variability per line not just an offset problem per line. Your method shows that directional denoising helps a lot and probably could be done twice for both directions.

@mike3996 linked to MP003426.DNG, a dark frame. That dark frame was taken about eleven days after the sky/lake photo, and 3 hours earlier in the day, so I don’t suppose it is useful for denoising the sky/lake. But I explore it here.

I de-bayer etc with dcraw, and equalize the histogram to see the noise in all its glory:

%DCRAW% -W -6 -T -O darkf.tiff MP003436.DNG

%IMG7%magick darkf.tiff -equalize darkfe.tiff

darkfe.tiff has visible horizontal bands, such as one I crop here, and magnify x4:

%IMG7%magick darkfe.tiff -crop 171x116+2177+680 +repage -scale 400% darkfs.tiff

darkfs
The dark band is about 75 pixels wide, and maybe 6 pixels high, centred at about y=735.

Scrolling left and right across the image, this row has other dark patches between areas of random noise. Towards the right side, I would say there are no dark patches. Perhaps they are buried in the general noise.

The average of row 735 is significantly darker than adjacent rows. We could correct the entire row by that factor. This would under-correct the dark bands and over-correct areas that have no dark bands. And the band is actually more than one row high.

To remove the horizontal banding from this dark frame, I suggest:

  1. Use three sliding windows, each of maybe 75x5 pixels. Window1 is directly above Window2, which is directly above Window3. (In effect, we have one sliding window of 75x15 pixels.)

  2. For each window, find the mean.

  3. If mean(Window2) is outside the range of the other two means, and is significantly lighter or darker than either, then remove the offset by adjusting the central column (or maybe just the central pixel) of Window2.

The means of the windows can be found quickly with Integral images.

As @PhotoPhysicsGuy says, there may also be gain variability.

1 Like

G’mic has a very good debanding filter

Original

Filtered

Try with this parameters

5 Likes

Okay. An algorithm is: for every pixel, and for every RGB channel in that pixel:

  1. Find the mean of Window1, the mean of Window2, and the mean of Window3.

  2. set MAX = max(mean(Window1),mean(Window3))

  3. set MIN = min(mean(Window1),mean(Window3))

  4. set dMax = max(0, mean(Window2) - Max)

  5. set dMin = max(0, Min - mean(Window2))

  6. set out_value = in_value - dMax + dMin

For the window size, I use 75x5 pixels. I use the same size for all three windows, but they could be different. Performance is independent of window size. For the dark frame, there seems to be a secondary effect that can be processed with a second pass with larger windows, eg 150x100 pixels.

This seems to successfully reduce the banding, with no apparent side-effects aside from also reducing reflections of lights, in the dark-frame and an equalized version of the sky/lake images. (If you have a better monitor or eyesight, feel free to report problems.)

For the sky/lake version, the algorithm takes 26 seconds on my laptop and changes 93% of pixels, but the change is generally slight (overall RMSE 1.8%).

Equalized sky/lake image (JPG version):


Denoised result (JPG version):

Code (Windows BAT script, using ImageMagick, incorporating my process modules for integral images):

%IM7DEV%magick ^
  %INFILE% ^
  ( +clone ^
    -process 'integim' ^
    ( -clone 0 ^
      -process 'deintegim window %WinW%x%WinH% offsetY -%WinH%' ^
    ) ^
    ( -clone 0 ^
      -process 'deintegim window %WinW%x%WinH%' ^
      +write mpr:W2 ^
    ) ^
    ( -clone 0 ^
      -process 'deintegim window %WinW%x%WinH% offsetY +%WinH%' ^
    ) ^
    ( -clone 1,3 ^
      -evaluate-sequence Max ^
      +write mpr:MAX ^
      +delete ^
    ) ^
    ( -clone 1,3 ^
      -evaluate-sequence Min ^
      +write mpr:MIN ^
      +delete ^
    ) ^
    -delete 0--1 ^
  ) ^
  ( mpr:W2 mpr:MAX ^
    -compose MinusSrc -composite ^
  ) ^
  -compose MinusSrc -composite ^
  ( mpr:W2 mpr:MIN ^
    -compose MinusDst -composite ^
  ) ^
  -compose Plus -composite ^
  %OUTFILE%
1 Like

My attempt with RTdev (commit 548f2103e).

Noise helps a lot to conceal banding, but if you look closer it is there, yet.


MP003322.jpg.out.pp3 (15.5 KB)

And it was a surprise to me, but Lanczos doesn’t work well in this image to downscale it.

WOW! I think that solves @mike3996’s problem.
(Thanks @Iain! That module is from you, right?)

1 Like

Yes, I made that debanding filter.

1 Like

Really wonderful result. Had some trouble following the directions until I noticed you did actually post the example values as well. My Vertical cutoff values were way too high to make any difference in the picture. :smiley:

And kudos to @Iain as well for writing this!

2 Likes