【问题标题】:Working with TIFFs (import, export) in Python using numpy使用 numpy 在 Python 中处理 TIFF(导入、导出)
【发布时间】:2011-11-26 00:58:48
【问题描述】:

我需要一个 python 方法来打开 TIFF 图像并将其导入 numpy 数组,这样我就可以分析和修改像素数据,然后再次将它们保存为 TIFF。 (它们基本上是灰度的光强度图,代表每个像素的相应值)

我找不到任何有关 TIFF 的 PIL 方法的文档。我试图弄清楚,但只有“错误模式”或“不支持文件类型”错误。

我需要在这里使用什么?

【问题讨论】:

    标签: python numpy python-imaging-library tiff


    【解决方案1】:

    首先,我从this page 下载了一个名为a_image.tif 的测试TIFF 图像。然后我用 PIL 像这样打开:

    >>> from PIL import Image
    >>> im = Image.open('a_image.tif')
    >>> im.show()
    

    这显示了彩虹图像。要转换为 numpy 数组,很简单:

    >>> import numpy
    >>> imarray = numpy.array(im)
    

    我们可以看到图像的大小和数组的形状匹配:

    >>> imarray.shape
    (44, 330)
    >>> im.size
    (330, 44)
    

    并且该数组包含uint8 值:

    >>> imarray
    array([[  0,   1,   2, ..., 244, 245, 246],
           [  0,   1,   2, ..., 244, 245, 246],
           [  0,   1,   2, ..., 244, 245, 246],
           ..., 
           [  0,   1,   2, ..., 244, 245, 246],
           [  0,   1,   2, ..., 244, 245, 246],
           [  0,   1,   2, ..., 244, 245, 246]], dtype=uint8)
    

    一旦你完成了数组的修改,你可以像这样把它变成一个 PIL 图像:

    >>> Image.fromarray(imarray)
    <Image.Image image mode=L size=330x44 at 0x2786518>
    

    【讨论】:

    • 我遇到了数据类型的问题。对某些人来说效果很好,例如如果我的数组中有 numpy.int16 数字,但对于 numpy.uint16 image.fromarray 产生:“TypeError:无法处理此数据类型”
    • 看fromarray的源码,貌似不是处理无符号16位数组的。
    • @Jakob 截至 2020 年 6 月 PIL doesn't support color images with more than 8 bits per color,您将不得不使用不同的库(或自己贡献功能)。
    • 这是我在尝试打开一个对 PIL 来说太大的图像时得到的结果:DecompressionBombError: Image size (900815608 pixels) exceeds limit of 178956970 pixels, could be decompression bomb DOS attack.
    • 对我来说 imarray.shape 给 (x,y , 3) ??我错过了什么??
    【解决方案2】:

    我使用 matplotlib 来读取 TIFF 文件:

    import matplotlib.pyplot as plt
    I = plt.imread(tiff_file)
    

    I 将是ndarray 类型。

    根据文档,虽然它实际上是 PIL 在处理 TIFF 时在幕后工作,因为 matplotlib 仅在本机读取 PNG,但这对我来说效果很好。

    还有一个plt.imsave 函数用于保存。

    【讨论】:

    • 这是迄今为止使用 TIFF 最简单的方法!尝试了十几种方法,这就是票。一定要点赞!
    • 观看部分怎么样?
    • 看来matplotlib改变了策略:ValueError: Only know how to handle extensions: ['png']; with Pillow installed matplotlib can handle more images
    【解决方案3】:

    您也可以使用 GDAL 来执行此操作。我知道它是一个地理空间工具包,但没有什么要求您拥有制图产品。

    链接到用于 windows 的预编译 GDAL 二进制文件(假设这里是 windows) http://www.gisinternals.com/sdk/

    访问数组:

    from osgeo import gdal
    
    dataset = gdal.Open("path/to/dataset.tiff", gdal.GA_ReadOnly)
    for x in range(1, dataset.RasterCount + 1):
        band = dataset.GetRasterBand(x)
        array = band.ReadAsArray()
    

    【讨论】:

    • 上面的代码是单页TIF还是多页TIF?我想使用 gdal 将 16 位 tiff 堆栈加载到 nparrays 中。
    • 这应该读入输入数据类型或将所有内容移动到numpy的float64。您可以在ReadAsArray() 调用的末尾添加.astype(sometype) 调用以进行转换。不确定这是否可以复制(只是尚未测试)。
    • @Chikinn 点评来源: stackoverflow.com/review/suggested-edits/17962780 xrange 没有错字,xrangerange 的python 2 版本。我接受了这个编辑,因为 python 3 仍在积极改进中,而 python 2 没有。
    【解决方案4】:

    PyLibTiff 对我来说比 PIL 效果更好,截至 2021 年 5 月,still doesn't support 彩色图像的每种颜色超过 8 位。

    from libtiff import TIFF
    
    tif = TIFF.open('filename.tif') # open tiff file in read mode
    # read an image in the current TIFF directory as a numpy array
    image = tif.read_image()
    
    # read all images in a TIFF file:
    for image in tif.iter_images(): 
        pass
    
    tif = TIFF.open('filename.tif', mode='w')
    tif.write_image(image)
    

    您可以使用安装 PyLibTiff

    pip3 install numpy libtiff
    

    PyLibTiff 的自述文件中也提到了tifffile 库,但我没有尝试过。

    【讨论】:

    • 这很好。到目前为止,tifffile 已包含在 SciKit skimage.external.tifffile 中,但如果您从 Christoph Gohlke 先生那里下载 tifffile.py,它也可以作为模块导入
    • pip install 不会在 Windows 上“正常工作”,请参阅 stackoverflow.com/questions/39483328/…
    【解决方案5】:

    在图像堆栈的情况下,我发现使用scikit-image 更容易阅读,matplotlib 更容易显示或保存。我已经使用以下代码处理了 16 位 TIFF 图像堆栈。

    from skimage import io
    import matplotlib.pyplot as plt
    
    # read the image stack
    img = io.imread('a_image.tif')
    # show the image
    plt.imshow(img,cmap='gray')
    plt.axis('off')
    # save the image
    plt.savefig('output.tif', transparent=True, dpi=300, bbox_inches="tight", pad_inches=0.0)
    

    【讨论】:

    • 而不是“plt.imshow(mol...”你的意思是“plt.imshow(img...”吗?
    【解决方案6】:

    您也可以使用我是作者的pytiff

    import pytiff
    
    with pytiff.Tiff("filename.tif") as handle:
        part = handle[100:200, 200:400]
    
    # multipage tif
    with pytiff.Tiff("multipage.tif") as handle:
        for page in handle:
            part = page[100:200, 200:400]
    

    这是一个相当小的模块,可能没有其他模块那么多的功能,但它支持平铺的 TIFF 和 BigTIFF,因此您可以读取大图像的一部分。

    【讨论】:

    • 这个功能正是我需要的! (能够读取大文件的一小部分)。但是,当我尝试 pip install 时,我收到 gcc 错误
    • 如果您创建一个带有错误消息的issue,我会看看能否找出问题所在。
    • 是的,我也很感兴趣,但在我尝试安装它时也遇到了错误。我是通过 pip 在 Windows 和 Ubuntu 下完成的。不幸的是,它不起作用!我在这里创建了一个问题:github.com/FZJ-INM1-BDA/pytiff/issues/15
    • 无法安装
    【解决方案7】:

    有一个名为tifffile 的不错的包,它使处理 .tif 或 .tiff 文件变得非常容易。

    使用 pip 安装包

    pip install tifffile
    

    现在,以 numpy 数组格式读取 .tif/.tiff 文件:

    from tifffile import tifffile
    image = tifffile.imread('path/to/your/image')
    # type(image) = numpy.ndarray
    

    如果要将 numpy 数组保存为 .tif/.tiff 文件:

    tifffile.imwrite('my_image.tif', my_numpy_data, photometric='rgb')
    

    tifffile.imsave('my_image.tif', my_numpy_data)
    

    你可以阅读更多关于这个包的信息here

    【讨论】:

    • 只有这个解决方案对我有用,谢谢!
    • pip install tifffile 对我来说还不够。您可能还需要pip install imagecodecs
    【解决方案8】:

    使用 cv2

    import cv2
    image = cv2.imread(tiff_file.tif)
    cv2.imshow('tif image',image)
    

    【讨论】:

    • 这里最简单的方法!
    【解决方案9】:

    我建议使用 Python 绑定到 OpenImageIO,它是处理 vfx 世界中各种图像格式的标准。与 PIL 相比,我发现它在读取各种压缩类型方面更可靠。

    import OpenImageIO as oiio
    input = oiio.ImageInput.open ("/path/to/image.tif")
    

    【讨论】:

    • Borderline 无法在 Windows 上安装,除非您已经有编译器。
    【解决方案10】:

    如果你想用geoTiff 保存 tiff 编码。你可以使用rasterio

    一个简单的代码:

    import rasterio
    
    out = np.random.randint(low=10, high=20, size=(360, 720)).astype('float64')
    new_dataset = rasterio.open('test.tiff', 'w', driver='GTiff',
                                height=out.shape[0], width=out.shape[1],
                                count=1, dtype=str(out.dtype),
                                )
    new_dataset.write(out, 1)
    new_dataset.close()
    

    有关 numpy 2 GEOTiff 的更多详细信息。您可以点击:https://gis.stackexchange.com/questions/279953/numpy-array-to-gtiff-using-rasterio-without-source-raster

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-09
      • 1970-01-01
      • 2016-06-05
      • 1970-01-01
      • 2017-03-12
      • 1970-01-01
      • 2010-11-19
      • 1970-01-01
      相关资源
      最近更新 更多