I gave this problem a break, and came back to it later. There were two problems, and it’s solved.
-
I’m pretty sure the CvtColor function is not fully 32F compatible, despite what the manual says. My guess is that the data is at some point rounded into a reduced number of quantization levels introducing quantization error. I haven’t counted them, but if I convert my data into L*ab / HSV / HLS and directly back again, it has lost precision, and therefore, a lot of detail. I have re-implemented these functions maintaining floating-point arithmetic and 32F precision, it is seems to be fine now.
-
My BGR2Lab function in my last post missed a key step that is not documented in the manual. I now understand that the RGB bands need inverse companding before they can be converted to XYZ and then to L*ab. I’ve not been interested in the details of color space conversion before, and so this detail had escaped me until now.