Import¶
import senxor
List available devices¶
You can list all available devices by calling the list_senxor
function.
addrs = senxor.list_senxor()
for addr in addrs:
print(addr)
You can also specify the type of device to list.
addrs = senxor.list_senxor("serial") # list all usb serial devices
Connect to senxor¶
Once you have the device address, you can connect to the device.
There are several ways to connect to a Senxor device.
- Use the context manager provided by the
connect
function.
addr = addrs[0]
with senxor.connect(addr, "serial") as dev:
print(dev.is_connected)
print(dev.is_connected)
The with
statement will ensure that the connection is closed after the block is executed.
It's equivalent to:
dev = senxor.connect(addr, "serial")
print(dev.is_connected)
dev.close()
You can also use the connect
without specifying the address or type.
In this case, the function will automatically find the first available device.
dev = senxor.connect()
print(dev.is_connected)
To be compatible with the old version, below is the equivalent code.
from senxor.utils import connect, connect_senxor
dev = connect()
print(dev.is_connected)
dev = connect_senxor()
print(dev.is_connected)
Start Stream and Read Data¶
Once you have connected to the device, you can start the stream and read data from the device.
dev.start_stream()
header, frame = dev.read()
if frame is not None:
print(f"Frame shape: {frame.shape}, dtype: {frame.dtype}")
# Output: Frame shape: (120, 160), dtype: float32
print(f"Frame min: {frame.min()} C, max: {frame.max()} C, mean: {frame.mean():.1f} C")
# Output: Frame min: 20.3 C, max: 34.1 C, mean: 27.2 C
dev.close() # Stop the stream and close the connection
The read
method will return a tuple of (header, frame)
or (None, None)
if the frame is not available(if block is False).
The header
is a uint16 np.ndarray with some information about the frame.
In default, the frame
is a 2D float32 np.ndarray, which is the temperature in Celsius.
The read
method is default in blocking mode, which means it will wait until a new frame is available.
You can set the block
parameter to False
to make the read
method non-blocking.
header, frame = dev.read(block=False)
if frame is None:
print("No new frame is available")
Process the data¶
You can use the senxor.proc
module to process the data.
import senxor.proc
Convert the frame to uint8 grayscale image.
Note: Due to the uint8 grayscale image has only 256 possible values, some information of the temperature frame may be lost.
uint8_image = senxor.proc.normalize(frame, dtype=np.uint8)
# Or use the `remap`, it's equivalent to `normalize(frame, dtype=np.uint8)`
uint8_image = senxor.proc.remap(frame)
Convert the frame to float32 grayscale image.
The float grayscale image can keep all the information of the temperature frame.
float32_image = senxor.proc.normalize(frame, dtype=np.float32)
Simply enlarge the image with a integer scale factor.
enlarged_image = senxor.proc.enlarge(frame, scale=2) # only support integer scale factor
Get a built-in cv2 colormap or matplotlib colormap.
cmap_cv_inferno = senxor.proc.get_colormap("inferno", "cv")
cmap_mpl_inferno = senxor.proc.get_colormap("inferno", "mpl")
Apply a colormap to the image.
# This returns a RGB image
colored_image = senxor.proc.apply_colormap(frame, lut=cmap_cv_inferno)
Tip
To keep the lightweight of the pysenxor, the get_colormap
and apply_colormap
doesn't need cv2
or matplotlib
as dependencies. They are based on the colormap_tool
and numpy
only.
Display or save the thermal image¶
You can use the cv2
or matplotlib
to display or save the thermal image.
import cv2
# Note: The cv2 uses BGR format instead of RGB format.
bgr_image = cv2.cvtColor(colored_image, cv2.COLOR_RGB2BGR)
cv2.imshow("senxor", bgr_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
import matplotlib.pyplot as plt
plt.imshow(colored_image)
plt.show()
Multi-threading¶
senxor
is designed to be thread-safe.
You can interact with the device in multiple threads.
For example, you can read the data in a background thread, and read/write registers in the main thread. Which is useful for GUI applications.