【问题标题】:Displaying tif files in jupyter notebook vie ipywidgets在 jupyter notebook vie ipywidgets 中显示 tif 文件
【发布时间】:2021-04-12 08:27:11
【问题描述】:

我正在尝试使用 jupyter-notebooks 中的 ipywidgets 显示 .tif 图像。以下代码适用于 .png 和 .jpg 文件

from ipywidgets import Image
png_image_path = r"C:\Users\xxxxxxxx\Work\Exercises\images\000000000.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 中没有正确显示

【问题讨论】:

  • 我不使用 jupyter 或它的小部件,但是......在第一个示例中,您将传递带有 PNG 标头、日期、位/像素、颜色类型和压缩像素数据的 PNG 编码图像.在 GDAL 的情况下,您传递的是没有标题的未压缩像素......非常不同的东西。
  • 我也尝试了第一种方法来处理 tif 文件,但没有奏效。然后我看到Image小部件中传递的im类型是字节,所以我认为将图像读取为字节可以用于tif图像。
  • 尝试打印im[:40],您会看到/x89PNGIHDR,这就是PNG 标头在磁盘上的样子。对您的 TIFF 执行相同操作,您将看不到 TIFF 标头(以 IIMM 开头)。
  • 可能还有其他方法,但您可以使用 ImageMagick 将 TIFF 转换为带有 magick input.tif output.png 的 PNG。或者您可以在 Python 中使用 OpenCV imencode() 将 GDAL 读取的 Numpy 数组放入 "in-memory" PNG。

标签: jupyter-notebook tiff ipywidgets


【解决方案1】:

您只需在 PNG 图像上执行file.read() 的事实对我来说意味着 Jupyter 小部件需要一个带有标头和压缩像素数据的 PNG 或 JPEG 编码图像。

如果您使用 GDAL 打开 TIFF,您将拥有一个 Numpy 数组,因此您需要在传递给 Jupyter 小部件之前将其编码为 “内存中” PNG 或 JPEG。您可以像这样使用 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)

正如您在 cmets 中正确指出的那样,OpenCV 使用 BGR 排序,因此您需要使用以下命令反转颜色通道的顺序:

RGBimage =  cv2.cvtColor(BGRimage, cv2.COLOR_BGR2RGB)

作为引入 OpenCV 依赖项及其奇怪的通道排序的替代方法,您可以使用使用常规 RGB 排序的 PIL/Pillow。在这种情况下,您将从 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 值,因此您可能需要重新缩放数据以适应较小的范围。

【讨论】:

  • 只是一个小注释 - opencv 以 BRG 格式读取图像,要将图像转换为 RGB 格式,我们需要执行 inmem_img = cv2.imencode('.png', cv2.cvtColor(img, cv2. COLOR_BGR2RGB))[1].tobytes()
  • 嗨阿努拉格。我更新了我的答案以澄清几件事。
猜你喜欢
  • 2021-02-06
  • 1970-01-01
  • 2019-11-01
  • 2022-12-01
  • 2017-10-04
  • 2016-07-20
  • 1970-01-01
  • 2018-06-14
  • 1970-01-01
相关资源
最近更新 更多