Clarification on MLX90640 scale function and temperatures


I am using the MLX90640 camera using some different temperature scales. My understanding was that they worked like the FLIR lepton, in that temp = pixel value * (max range - min range) / 255 + min range.
However, when comparing to the max temp range I am getting using read_ir(), they do not seem to correlate.
I am more confused after not using a scale. I would have assumed the min and max of the scale would be the min and max temp ranges detected, which is what the documentation seems to imply. Hence, I would have assumed that each frame would have a min and max pixel of 0 (corresponding to the lowest temp detected) and 255 (corresponding to the max temp detected). However, this is not the case, and many frames I am getting have a max of about 120-135ish. This also appears to be the case that I can never really get much above this range when specifying the scale.
My code for grabbing these frames using the default scale is:

img = fir.snapshot(x_size = w, y_size = h,
                    color_palette = None,
                    hint = drawing_hint, copy_to_fb = True,
                    hmirror = False, vflip  = False,

and when specifying a scale (scale values obviously change):

        img = fir.snapshot(x_size = w, y_size = h,
                    color_palette = None,
                    hint = drawing_hint, copy_to_fb = True,
                    hmirror = False, vflip  = False,
                    pixformat=fir.GRAYSCALE, scale = [20,30])

Any insight into this would be much appreciated!

It follows the code here:

pixel = (temp - min) * 255 / (max - min)

Which is:

temp = (pixel * (max - min) / 255) + min

And yes, if the scale is not specified then it finds the image max and min temperature and scales everything in the image to that:

Unless you know what the min/max were using read_ir() then you don’t really have a way to see what the scale is from the pixel values.

Regarding you question on why you can’t get 255. Are you scaling using blinear or bicubic? I see you are passing drawing hints. Note that the blended image may smooth out peaks… e.g. min/maxes.

Ok, so the temp function I used is correct.

As I mentioned, I was using read_ir() to get the min and max. However, these did not align with the calculated values

Yes, I have been experimenting with bicubic, however I have not been using it and getting these errors. I have had w and h set to 32 and 24 respectively. I have just tried removing the drawing_hints and I am still getting the exact same issue of max pixel value not going above 135ish

Mmm, if you use read_ir() and draw_ir() do you get the same results as snapshot()? Snapshot just composes those two functions to be easier to use.


Apologies in the delay, I was away last week.

I cannot see how to use them the same as snapshot(). Using snapshot, I am making a grayscale image, however I can only seem to use the ironbow or rainbow palettes with draw_ir().

That aside, I covered the openMV cam lens so it is just seeing black, and using the default palette (rainbow), the max of the histogram seems to be similar to snapshot(). both grayscale and RGB histograms don’t seem to have pixel values go above 150 no matter how hot an object is in front of it.

The images below show the histograms both with and without the scaling when a lighter is held in front of the camera using both read_ir() and draw_ir(), and snapshot(). Clearly, the max temp detected is well above the upper bound, especially when scaling.

Okay, this may be a big. Let me debug it.

1 Like

Great, thankyou!

Found the issue.

The default value of fir_snapshot() uses an alpha of 128. blended against a black background. Just pass an alpha of 256.

It was chosen this way to match draw_ir which is supposed to draw on an image with alpha 128.