Reading with Pillow¶
When the TIF file is opened with Pillow, it is automatically recognized as a 32-bit floating point image with one channel.
We can verify this with Image.mode, and the value should be F.
See: https://pillow.readthedocs.io/en/stable/handbook/concepts.html#modes
In [1]:
from pathlib import Path
import matplotlib.pyplot as plt
from PIL import Image
In [2]:
rgb_path = Path("515d7757-dbe1-4bb8-a817-a917043aae9c", "RGB_camera_0.jpg")
depth_path = Path("515d7757-dbe1-4bb8-a817-a917043aae9c", "DepthRaw_camera_0.tif")
rgb = Image.open(rgb_path)
depth = Image.open(depth_path)
depth.mode
Out[2]:
'F'
In [3]:
fig, axs = plt.subplots(1, 2, figsize=(20, 8))
axs[0].imshow(rgb)
axs[1].imshow(depth);
Numpy processing¶
When we convert the PIL Image into a Numpy array, we get an array of shape (h, w), which is typical of single-channel images. We recommend the PIL -> Numpy
method when working with depth images as arrays.
The values of the array are the distances of the camera to the pixels, in meters.
In [4]:
import cv2
import numpy as np
In [5]:
depth_arr = np.array(depth) # convert from PIL to Numpy
depth_arr.shape
Out[5]:
(1080, 1920)
In [6]:
# You can also read with OpenCV, which gives the same array, but our tests use
# the Pillow approach so it is more well-maintained.
cv2_arr = cv2.imread(depth_path, cv2.IMREAD_UNCHANGED)
(depth_arr == cv2_arr).all()
Out[6]:
np.True_
In [7]:
depth_arr.min(), depth_arr.max()
Out[7]:
(np.float32(73.0333), np.float32(1061.6786))
In [8]:
plt.figure(figsize=(16, 9))
# clamp to (0, 300) for a more pronounced visualization
plt.imshow(depth_arr, vmin=0, vmax=300)
plt.colorbar()
for x, y in [
(1355, 640),
(660, 430),
(1750, 200),
]:
plt.annotate(
f"{depth_arr[y, x]:.2f} m",
(x, y),
textcoords="offset points",
xytext=(0, 10),
ha="center",
)
plt.plot(x, y, "ro")