Strange encounter in the red channel/RPi HQ Camera

Hmm… - that’s an interesting challenge. One way to handle this would be to use the raw data to drive your histogram directly. Difficulty here: the huge amount of data (4k) to handle - the update frequency of the histogram would be no fun to watch.

Another option would be to misuse the “main” or even the low res image stream for that purpose. You would need to take the main culprit, namely the already discussed color matrices, out of the equation. The relevant section in the tuning files starts with something like this here:

			"rpi.ccm": {
				"ccms": [
					{
						"ct": 2000,
						"ccm": [
							1.6564872670680853,
							-0.36969756274013368,
							-0.2867897043279514,
							-0.4247450786701745,
							1.542991437580725,
							-0.11824635891055065,
							0.24901133306238788,
							-1.5422051484893296,
							2.2931938154269417
						]
					},

Note the negative entries here. They are the ones which spoil the fun. That is, these are values which cause the mapping of raw data values outside of the bounds given by libcamera’s processing pipeline - which are most probably limited to 0x0000 to 0xffff. If you set these values to the unity matrix (that is, either 1.0 or 0.0) , there should be no out-of-bounds values occuring during processing. Just a guess/suggestion for an experiment. The following examples were not produced by libcamera, but simulated with my software. But libcamera is performing these steps as well, based on the data in the tuning files.

If you modify the color matrices, you would still have the rec709 contrast curve applied. For this to “go away”, you’d would need to replace the section starting with

{
			"rpi.contrast": {
				"ce_enable": 0,
				"gamma_curve": [
					0,
					0,
					512,
					2304,
					1024,

with a straight (linear) curve.

Using such a modified tuning file, libcamera should deliver at it’s “main” end point data which is pretty similar to the raw values the sensor is seeing - only that the dynamical range would be limited to 8-bit per color channel.

But of course, the image would look visually aweful - certainly no point in saving that image.

Here’s what you could expect with such a tuning file (again: only simulated at this point in time - one would need to check whether this is really the case with libcamera + modified tuning file):

Since the contrast curve is not applied, the shadow areas are all rather dark.

If you keep the rec709-contrast curve in the tuning file, something like this here


is to be expected. Visually better, but of course the colors are all wrong and the values remapped - since the complete color science is missing. So maybe a modified tuning file were the complete set of color matrices is replaced by a single unit-matrix, leaving the contrast curve in place might do the trick.

For reference, here are the color channels of the image with rec709 contrast curve:


showing that no clipping is occurring, as desired.

Personally, I think such an approach would only be interesting if the data obtained is to act as a base for a histogram. Not sure whether I would take such an image as the base of film captures (that is: color grading), as the colors are not correct - for certain.

But: in your modified camera setup (change of IR-blockfilter), the color matrices in the tuning file are anyway only approximations, so that might be something for you to look into.

(To be a little bit more precise: the images shown above are basically the debayered raw data (a greenish image, compare this thread here) with the appropriate white balance applied, plus an additional rec709 contrast curve to brighten up the shadow areas.)

EDIT: there is a tuning file available in the RP-distribution which is called “uncalibrated.json”. This is used in camera calibration tasks and it uses the following color matrix:

"rpi.ccm":
            {
                "ccms": [
                    {
                        "ct": 4000,
                        "ccm":
                        [
                            2.0, -1.0, 0.0,
                            -0.5, 2.0, -0.5,
                            0, -1.0, 2.0
                        ]
                    }
                ]
            }

Which is not the unity matrix I proposed above. So I might be wrong that a unity matrix is the appropriate thing to use here. It might be a little bit more complicated than I remember. Well, I would need to look into this in more detail to give a definite hint. @PM490: If you do some experiments - let us know the outcome!

EDIT2: it’s been a long time since I did that color stuff, and I guess I forgot quite a bit. So what I have written above is not totally correct. See post below for a more detailed discussion.

1 Like