Inspired by a recent thread on CloudyNights, I decided to reevaluate how I was using luminance data. I’ve never been fully happy with what I was getting. My typical approach has been to use LRGBCombination with the method suggested by Juan on the PI forums years ago. This has now become the accepted approach, it seems:
- Extract a luminance image from your color image.
- LinearFit your luminance data to this extracted luminance image.
- Use LRGBCombination to apply the now “fitted” luminance data onto your color image.
- To limit desaturation of colors, I apply it with the L channel set at around 0.50 and the saturation slider moved to around 0.25-0.40.
The result is usually an image with less noise (better SNR), but without the full apparent contrast in the luminance data–the LinearFit step mostly removes that. Of course, you can now proceed to process the image to add contrast, and this is the recommended approach.
Many people report that not only do they lose the contrast of their luminance data, but they also find that colors shift. (This is actually true whenever you brighten an image–colors will tend to converge toward pure colors.) I’d never thought much about it, but I decided to run some experiments to compare the LRGBCombination method with another suggested method: using ChannelCombination’s HSL mode.
First, we need to create a very colorful image, preferably with every hue. With a little PixelMath magic (okay, it’s just math), you can create* a full rainbow of hues. In this case, they are all fully saturated and at 49% brightness. We also need an image with all luminance values. This is very straightforward to create with PixelMath. We’ll run them horizontally so we can combine them with the hues above later. Here are the two images we’re going to combine.
What happens if we just combine them with LRGBCombination? This is with the default settings of 100% L channel and no change to saturation:
Yikes! The color shift is very apparent. As is the loss of saturation. This is why it’s probably not a good idea to use LRGBCombination with the default settings. What if we use the preferred approach listed above, where we linear fit the L image to the luminance data of the color image? This is where things get a little weird. Here is the extracted luminance from the hue image next to the original luminance that has been LinearFit-ted to it:
Granted, this is an extreme example, but this shows the loss of contrast the results from applying LinearFit to a high-contrast luminance image. We basically just end up with a nearly solid gray image.
Now let’s combine this very low contrast luminance image with our color image. We’ll do this with three different settings: first, the default of L channel = 1.0 and Saturation at 0.5, second with the L channel reduced to 0.5, and third with the L channel at to 0.5 and saturation boosted with a 0.25 setting.
You can see that this definitely improves things as far as color saturation and color accuracy… but we completely lost our luminance. There’s no fade from left to right anymore! It seems that there is a tradeoff with LRGBCombination between color fidelity and luminance contrast.
Now, let’s try ChannelCombination to merge our “AllHues” and “AllLums” images. ChannelCombination gives us two options for this: HSI (intensity) and HSV (value). Let’s try each and compare.
I think the “HSI” results generally match what most people would expect when applying luminance to color. Color fidelity is maintained, and saturation is only lost in proportion to the brightness. HSV is interesting, as it seems to prioritize hue over luminance at the brightest levels. Perhaps this might be useful for apply star colors.
- This analysis did not consider the impact of these combination methods on noise (luminance or chrominance). It’s not clear if that is a third factor that is traded off. Further experiments are needed here. Maybe in a future post.
- I did not show the CIE L*a*b* or CIE L*c*h* approaches in ChannelCombination, but the results are similar to LRGBCombination.
* I created the following formula for PixelMath based on the description of HSL on this site. Apply it to an image 1000 pixels high, and it creates every hue along the vertical axis. L = .49; S = 1; H = y()/1000; t1=L*(1+S); t2=2*L-t1; tc=iif((H +.333)<0, (H +.333)+1, iif((H +.333)>1, (H +.333)-1, (H +.333))); iif(6*tc<1, t2+(t1-t2)*6*tc, iif(2*tc<1, t1, iif(3*tc<2, t2+(t1-t2)*6*(.666-tc), t2))); Symbols: L, S, H, t1, t2, tc