Thermal Raw Data

The Spot CAM+IR payload allows capture of thermal data in the forms of .raw or .pgm files. Raw data files allow for more versatility when compared to a thermal jpeg image because they allow the thermal data to be rendered or analyzed as needed. For example, re-construction of a thermal image from the raw thermal data enables viewing with custom color palettes or to perform specific image processing in more advanced applications.

Understanding thermal data

The raw thermal data from the Spot CAM+IR contains 327,680 (640x512) 16-bit unsigned values. Each value describes a temperature in units of decikelvin. To get the value in units of kelvin, divide the value by 10.

The two bytes encoding each data value are given in big endian, meaning that the most significant byte of the two is given first when reading the data from left to right. There is an exception to this for version 3.1.0 of the Spot CAM+IR software, in which the byte order of the data was reversed to little endian.

SpotCAM+IR Software Version Endianness
v3.1.0 Little endian
All other versions Big endian

Thermal file types (.pgm vs .raw)

Raw data captured using the SDK is captured as .pgm while the same data captured using callbacks is captured as .raw. Both contain the same data, except that the .pgm file contains additional header lines. In general, .pgm files are downloaded when using the spot SDK while .raw files are downloaded when downloading through the data service. The example script can read both file types, but it throws away any header files. The .pgm headers are necessary to parse the data if the width and height of the image are variable.

Rendering raw thermal data

Some image viewers can natively open .pgm files as a grayscale image. To instead show with a particular color palette, a lookup-table can be referenced to map from temperature to a color. For example, the lookup tables used by matplotlib can be referenced at this link

Scaling the color mapping

The left image is a render using the min and max temperatures mapping directly to the min and max values in the color map. The image on the right shows the same image but with the mapping adjusted so that the lower temperature values are less prominent. This allows for more contrast and improved visibility of the hotter areas. Thermal Ironbow Example

Color palettes:

The following renderings are generated from a single thermal data capture and rendered with OpenCV. Thermal Custom Palettes Example

Example code

import matplotlib.pyplot as plt
import numpy

# width and height based on the Spot CAM+IR thermal camera
height = 512
width = 640
filename = "/path/to/pgm/or/raw/file"
endianness = '>' # '>' For big-endian and '<' for little-endian
with open(filename, 'rb') as f:
    buffer = f.read()

    try:
        # For .pgm and .raw files transferred from the tablet or downloaded from Scout
        processed_data = numpy.frombuffer(buffer, dtype=f'{endianness}u2')
    except ValueError:
        # For .pgm and .raw files from the SpotCam+IR itself (using the Media Log service)
        # The last element for both .pgm and .raw files is the data after splitting by newline
        split_buffer = buffer.splitlines()
        processed_data = numpy.frombuffer(split_buffer[len(split_buffer) - 1], dtype=f'{endianness}u2')

    processed_data = processed_data.reshape((int(height), int(width)))

    image = list(processed_data) 
    plt.imshow(image, plt.cm.inferno) # some alternate colormaps: inferno, plasma, viridis, ocean, cubehelix, rainbow
    plt.show()