在 jupyter notebook 中显示 tif 文件 vie ipywidgets
Displaying tif files in jupyter notebook vie ipywidgets
我正在尝试使用 jupyter-notebooks 中的 ipywidgets 显示 .tif 图像。以下代码适用于 .png 和 .jpg 文件
from ipywidgets import Image
png_image_path = r"C:\Users\xxxxxxxx\Work\Exercises\images[=10=]0000000.png"
file = open(png_image_path, "rb")
im = file.read()
Image(
value=im,
width=300,
height=400,
)
type(im) # <class 'bytes'>
上述代码中的 ipywidget 呈现了所需的图像。为了读取 tif
文件,我使用 gdal
.
img = gdal.Open(tif_img_path).ReadAsArray()
print(img.shape) # (3, 1024, 1024)
print(img.transpose(1,2, 0).shape) # (1024, 1024, 3)
type(img.transpose(1,2,0).tobytes()) # <class 'bytes'>
Image(
value=img.transpose(1,2,0).tobytes(),
width=300,
height=400,
)
我得到以下输出,图像在 ipywidget 中显示不正确
事实上,您只是对 PNG 图像执行 file.read()
这意味着 Jupyter 小部件需要 PNG 或 JPEG-encoded 图像,具有 header 和压缩像素数据。
如果你用 GDAL 打开你的 TIFF 你会得到一个 Numpy 数组,所以你需要在传递之前将它编码成 "in-memory" PNG 或 JPEG到 Jupyter 小部件。你可以用 OpenCV 这样做:
import cv2
# Open TIFF image into Numpy array
img = gdal.Open(tif_img_path).ReadAsArray()
# Encode into in-memory PNG for Jupyter
_, PNG = cv2.imencode('.png', img)
正如您在评论中正确指出的那样,OpenCV 使用 BGR 排序,因此您需要通过以下方式反转颜色通道的顺序:
RGBimage = cv2.cvtColor(BGRimage, cv2.COLOR_BGR2RGB)
作为引入 OpenCV 依赖项及其怪异通道顺序的替代方法,您可以使用 PIL/Pillow,它使用常规RGB排序。在这种情况下,您将从 GDAL 获得的 Numpy 数组转换为 PNG 格式:
from io import BytesIO
im = ... read from GDAL ...
# Write Numpy array to in-memory PNG
membuf = BytesIO()
Image.fromarray(im).save(membuf, format="png")
... you can now use membuf.getvalue()
另请注意,通常 TIFF 可能包含无法用 8 位 JPEG 表示的 float 或 float64 值,因此您可能需要 re-scale 您的数据以适应较小的范围。
我正在尝试使用 jupyter-notebooks 中的 ipywidgets 显示 .tif 图像。以下代码适用于 .png 和 .jpg 文件
from ipywidgets import Image
png_image_path = r"C:\Users\xxxxxxxx\Work\Exercises\images[=10=]0000000.png"
file = open(png_image_path, "rb")
im = file.read()
Image(
value=im,
width=300,
height=400,
)
type(im) # <class 'bytes'>
上述代码中的 ipywidget 呈现了所需的图像。为了读取 tif
文件,我使用 gdal
.
img = gdal.Open(tif_img_path).ReadAsArray()
print(img.shape) # (3, 1024, 1024)
print(img.transpose(1,2, 0).shape) # (1024, 1024, 3)
type(img.transpose(1,2,0).tobytes()) # <class 'bytes'>
Image(
value=img.transpose(1,2,0).tobytes(),
width=300,
height=400,
)
我得到以下输出,图像在 ipywidget 中显示不正确
事实上,您只是对 PNG 图像执行 file.read()
这意味着 Jupyter 小部件需要 PNG 或 JPEG-encoded 图像,具有 header 和压缩像素数据。
如果你用 GDAL 打开你的 TIFF 你会得到一个 Numpy 数组,所以你需要在传递之前将它编码成 "in-memory" PNG 或 JPEG到 Jupyter 小部件。你可以用 OpenCV 这样做:
import cv2
# Open TIFF image into Numpy array
img = gdal.Open(tif_img_path).ReadAsArray()
# Encode into in-memory PNG for Jupyter
_, PNG = cv2.imencode('.png', img)
正如您在评论中正确指出的那样,OpenCV 使用 BGR 排序,因此您需要通过以下方式反转颜色通道的顺序:
RGBimage = cv2.cvtColor(BGRimage, cv2.COLOR_BGR2RGB)
作为引入 OpenCV 依赖项及其怪异通道顺序的替代方法,您可以使用 PIL/Pillow,它使用常规RGB排序。在这种情况下,您将从 GDAL 获得的 Numpy 数组转换为 PNG 格式:
from io import BytesIO
im = ... read from GDAL ...
# Write Numpy array to in-memory PNG
membuf = BytesIO()
Image.fromarray(im).save(membuf, format="png")
... you can now use membuf.getvalue()
另请注意,通常 TIFF 可能包含无法用 8 位 JPEG 表示的 float 或 float64 值,因此您可能需要 re-scale 您的数据以适应较小的范围。