ZCAM for Nuke

Something strange, possibly with the soft clipping of M, not sure, I’m just playing around…

huesweep_ZCAMishDRT.nk (396.2 KB) (have to repath the internal images to make this work)

Yeah, it mirrors what we see in that M bounds image, with the pinching at blue.

It can also be useful to visualise how much of the input gamut is falling outside of the display’s gamut triangle.

Left: ACEScg ColourWheel plotted in CIE 1976 u’ v’
Middle: ACEScg ColourWheel → Rec709 with all pixels with neg values dimmed.
Right: ZCAMishDRT result with Rec709 gamut triangle bounds overlayed.

Left: ACES ColourWheel plotted in CIE 1976 u’ v’
Middle: ACES ColourWheel → Rec709 with all pixels with neg values dimmed.
Right: ZCAMishDRT result with Rec709 gamut triangle bounds overlayed.

2 Likes

This is really curious.

According this presentation (slide 15) JzAzBz should be much more uniform in the distribution of hues than other color spaces. Unfortunately, there’s not a lot of info on how this comparison was created and it only focuses on JzAzBz not the entire Zcam model.

cough reproducible research …

1 Like

As both @nick and @priikone have noticed, I’ve made a dopey mistake with my BlueBar example.

I’d accidently selected: Input - ARRI - Curve - V3 LogC (EI800)
As opposed to : Input - ARRI - Curve - V3 LogC (EI800) - Wide Gamut
on my OCIOColorSpace node.

Below is without the RGC.

3 Likes

After much head scratching, I eventually figured out what was going on here.

The way I have to do the 2D LUT lookup means I need to pipe into the same image stream as the image being processed. If that image is smaller than 1024x1024 the Expression node was unable to sample any positions outside the frame. The HueSweep node outputs 512x533, so J/h combinations with a 2D position outside of that were unable to be sampled. I’ve now added a reformat fix inside the node to deal with this.

So it goes from this:

To this:

I’m still a little suss about the slight clustering of points around the cyan line, but the gigantic rip (and total lack of highlight compression) is gone.

Old:

New:

3 Likes

OK

I’ve made a few updates to the node.

Functionally, the biggest difference is that the edge of the gamut, and the head (for lack of a better word) are now handled seperately. For example backing off the edge of gamut compression whilst turning up the top end desaturation.


I’ve also made the process of repathing the internal gamut bounds images a bit eaiser. There is a now just a single exposed path you can point at the directory where they’re stored.

The new version is in this file here:
nukeZCAM_dev_v006.nk

3 Likes

Is the CAT working correctly? I’m getting warmer whites with D75 than with D50. Opposite happens with OpenDRT.

Great stuff @alexfry. On initial testing, that looks really good out of the box.

Is there a reason you don’t just use relative paths for the images in your Nuke script? I just set the path to [python {nuke.script_directory()}]/images/gamutBounds/

Obviously that only works for Nuke scripts in the root of the GitHub repo. But defaulting to that makes it work immediately when you just open the script.

I also added a Multiply node before the final Colorspace25 node, set to (parent.Colorspace25.colorspace_out==31) ? 100 : 1 so that it converts to absolute nits prior to ST.2084 encoding if you select that EOTF.

Again, adding custom curves could break that by changing the enum from 31, but it works initially.

EDIT: The Python expression 100 if (nuke.toNode('Colorspace25').knob('colorspace_out').value() == 'st2084') else 1 should be more robust to possible enum changes.

The time it took me to work this out shows how hacky and “trial and error” my coding is!

My version:

1 Like

The tone scale compared to ACES 1.2 is a bit off (for sRGB output), difference is mostly the dark-to-dim surround compensation. Started looking at this because I wasn’t sure if the darkening of colors I see happens because of the model or the tone scale. Is the SDR curve meant for P3D65?

It probably makes sense that the dark-to-dim is not baked into the tone scale when using a CAM, since that is a crude attempt at an appearance match, and should probably be left for the CAM to do a better job of.

Looking quickly at the internals of @alexfry’s DRT group node, all the ZCAM transforms are set to “average” surround. Some experimenting with different surround settings for the forward and inverse ZCAM transforms is probably needed.

Right, that’s a good point. Presumably this will then have to be taken into account also in the LUT image generation.

Hi.

For those of you who are interested in the alternative Nuke implementation of a ZCAM based DRT shown in todays (2021-12-15) meeting you can find my (very much work-in-progress) model here:

3 Likes

Great work @matthias.scharfenber!

I know that @Thomas_Mansencal has said that he believes a two step chromatic adaptation should really be used. But in the absence of that, do you think the Bradford matrix check-box should be set on the input Colourspace conversion to CIE XYZ? Or have I missed something, and you have a two step adaptation to D65 constructed as part of the node tree?

EDIT: I see, on further investigation that the input ZCAM conversion uses ACES, rather than D65, as the reference white, so perhaps it is handled here and the Bradford CAT should not be enabled earlier.

1 Like

I’ve got an HDR monitior (Macbook Pro M1) and have both @alexfry and @matthias.scharfenber flavors of the zCAMish DRT working via the “Enable macOS HDR Color Profile (Display P3) (Beta)” function. Looks amazing!

I’d like to compare this to ACES 1.2 and OpenDRT but am not having much luck with getting either of these to display in HDR.

ACES in HDR

For ACES I’m using the Nuke ACES 1.2 OCIO config with the view transform set to P3-D65 1000 nits (ACES), and it displays in SDR (i.e. it is clamping at 1). If I switch the view transform to Raw it does display in HDR.

OpenDRT

@jedsmith 's OpenDRT v90b4 is just showing pitch black. This is coming from the Display Scale node (i.e. disabling it make the image appear again).

Can some one point me in the right direction?

Looks like in Nuke 13 and in some scripts, a knob named s in the expression node was not returning the right value. I’ve pushed a fix.

2 Likes

I’ve put together a clip with a bunch of example footage and still images running through the 3 DRTs.

Left Column: ZCAMishDRT Alpha 0.6
Middle Column: OpenDRT v0/0/90b2
Right Column: ACES 1.2

Top Row: -5 Stops
Middle Row: Standard Exposure
Bottow Row: +5 Stops

Still frames all do a -5 to +5 Exposure sweep over 51 frames.

The idea with the -5 and +5 offsets is to give you something to compare when trying to get a sense of “does this image feel like the same image, or are the proportions shuffled around as exposure changes?”

Whilst ZCAMishDRT’s approach to gamut compression helps here, by always preferencing Brightness over Colour intensity, it can lead some images feeling like they desat too fast. The question there is, which matters more? The colour of the light, or the quantity of the light?

Currently, the area that looks the worst to me is ZCAMishDRT’s handling of very bright, but only moderately saturated, areas holding on to too much saturation as they approach the clipping point. This can most clearly be seen on the clips outside the Mercedes Benz museum. Perhaps it’s going to need an explict highlight desat tied to the tonemapping section, rather than the gamut volume compressor alone?

4 Likes

Hey Derek

I’ve got a modified ACES 1.2 OCIO config here, that supports Nuke’s Display P3 Extended mode:

If you don’t want to download the whole thing, the only required files are:
config.ocio
/luts/srgbf.spi1d

Generally though, if you have a Rec2100 (Rec2020/ST2084) Image, the following nodes will flip it to Display P3 Extended.

  • ST2084/Rec2020 → Linear P3 D65
  • Mult down by .01 to convert 100 absolutle nits to 1.0
  • Apply peicewise sRGB inverse EOTF (with the rest of the curve above 1.0 being exptrapolated out)
set cut_paste_input [stack 0]
version 13.0 v3
push $cut_paste_input
Colorspace {
 colorspace_in st2084
 primary_in Rec.2020
 primary_out DCI-P3
 name Colorspace3
 label "Rec2100 to Linear P3 D65"
 selected true
 xpos 1531
 ypos -21
}
Multiply {
 value 0.01
 name Multiply2
 label "100nits -> 1.0"
 selected true
 xpos 1531
 ypos 11
}
Colorspace {
 primary_in DCI-P3
 colorspace_out sRGB
 primary_out DCI-P3
 name Colorspace4
 label "Linear P3 D65 -> Display P3 (sRGB EOTF extended)"
 selected true
 xpos 1531
 ypos 53
}
3 Likes

Hi,

Just wanted to show a quick comparison between a few CAMs with sRGB.

  • First Column: Uniform Lightness Ramp, Constant Chroma (Varying Per-Row), Varying Hue
  • Second Column: Out-of-Gamut Colours
  • Third Column: First Column Converted to Luminance

CIECAM02

CAM16

Kim et al. (2009)

ZCAM

A few quick notes:

  • A significant portion of the visual artefacts are cause by OOG colours.
  • CIECAM02 and its CAM16 child do not work well with dark colourful colours.
  • Kim et al. (2009) exhibit some strange artefacts, there is no reference implementation so maybe we broke something.
  • ZCAM behaves the best of the 4 models, simpler is better.

Colab Notebook: Google Colab

5 Likes

That’s great video! Overall I really like the color that comes out of ZCAMishDRT but there’s also issues beyond the blues going towards cyan. As you noted there’s some issues with bright colors.

These are +2 stops. Notice how all reds, and oranges go kind of pink:



Here’s image with clipped sky:



But overall the color is great. But, wIth the SSTS and darkening of greens and reds it does plus the blues going toward cyan, the look out of this DRT is very filmic.

1 Like

I’ve been experimenting with comparing the zCAMish DRT on and HDR and SDR monitor side by side. Wanted to share my observations.

One difference is that the SDR crushes the shadows, whereas the HDR does not. My understanding is that this is not so much an issue with the color, but with the tone scale, and precisely this crushing of shadows has been also noted of the ACES transform. It also makes sense that this “slightly less contrast” tone mapping is not an issue with HDR since it (by definition) has a bigger range between dark and light. So I guess the tone curve used for SDR should not be the same as for HDR?

The other thing I’m seeing is issues with clipped sky in the SDR, which does not happen with the HDR. Here’s the image in ACES:

Here it is in zCAM. Note how the blue in the sky is overwhelmed by the orange. This does not happen with zCAM in HDR, just in SDR:

Finally, here is zCAM with an adjustment using the ZoneSat:

This looks closer to how it appears in HDR, with the difference being that the saturated colors on the clouds are retained in the HDR, while the SDR they go to white.

If the goal is to have SDR and HDR look sort of similar, this can be done by applying the zoneSat with the same settings to the HDR which causes it to desat the highlights a bit, matching what the SDR is doing.

Hope that’s helpful.

1 Like