For a project, I'm using the MLX90461 IR camera. And I'm using some C++ code to read the data of the camera.
The data of this camera is stored in an array of 192 elements (16x12 RES). In this array, I store the measured temperature for that pixel.
Next, I convert that temperature to RGB values and store those as well. Because I need 3 values per pixel the array has 576 elements. (192 * 3).
So now I have an array filled with data. And I want to make an image of all this data.
I followed this example and it works great.
Now comes the but... But:
- It outputs a
.ppm
file - The output is just 16x12 pixels
And I want to use the output as a sort of live stream, so the .ppm
file type is not really great.
So My questions are.
- Is this way of doing things in the right direction?
- Is there a way to output a more "common" file type like a
.png
- Is C++ the best way to do this type of data processing I was thinking to use Python to make an image based on the array.
The end result I'm liking to have is something like this: visualization on display (see GIF below code)
void print_pixels(){
static uint8_t pixels[576];
uint16_t l = 0;
for(int i = 0 ; i < 12 ; i++){ //rows
for(int j = 0 ; j < 16 ; j++){ // cols
struct CRGB color = tempToColor(temperatures[j+16*i]);
pixels[l] = color.r;
l++;
pixels[l] = color.g;
l++;
pixels[l] = color.b;
l++;
printf("T%4.2f,R%i,G%i,B%i : ", temperatures[j+16*i], pixels[l - 3], pixels[l - 2], pixels[l - 1]);
}
std::cout << "\n\n";
}
FILE *imageFile;
int height=12,width=16;
imageFile=fopen("/home/pi/output_IR_camera.ppm","wb");
if(imageFile==NULL){
perror("ERROR: Cannot open output file");
exit(1);
}
fprintf(imageFile,"P6\n"); // P6 filetype
fprintf(imageFile,"%d %d\n",width,height); // dimensions
fprintf(imageFile,"255\n"); // Max pixel
fwrite(pixels,1,576,imageFile);
fclose(imageFile);
}
struct CRGB tempToColor(float temp) {
struct CRGB color;
if (temp > MAX_TEMP) {
color.r = 255;
color.g = 0;
color.b = 255;
} else if (temp >= MIN_TEMP + PEAK_STEPS * 4) {
color.r = round(255 * (temp - (MIN_TEMP + PEAK_STEPS * 4.0)) / PEAK_STEPS);
color.g = 0;
color.b = 255;
} else if (temp >= MIN_TEMP + PEAK_STEPS * 3) {
color.r = 0;
color.g = round(255 * (6 - (temp - (MIN_TEMP + PEAK_STEPS * 3.0)) / PEAK_STEPS));
color.b = 255;
} else if (temp >= MIN_TEMP + PEAK_STEPS * 2) {
color.r = 0;
color.g = 255;
color.b = round(255 * (temp - (MIN_TEMP + PEAK_STEPS * 2.0)) / PEAK_STEPS);
} else if (temp >= MIN_TEMP + PEAK_STEPS * 1) {
color.r = round(255 * (6 - (temp - (MIN_TEMP + PEAK_STEPS * 1.0)) / PEAK_STEPS));
color.g = 255;
color.b = 0;
} else if (temp >= MIN_TEMP) {
color.r = 255;
color.g = round(255 * ((temp - MIN_TEMP) / PEAK_STEPS));
color.b = 0;
} else {
color.r = 255;
color.g = 0;
color.b = 0;
}
return color;
}