如何在Python中读取一个大的TIF文件?

5

我正在从http://oceancolor.gsfc.nasa.gov/DOCS/DistFromCoast/加载一个tiff文件。

from PIL import Image
im = Image.open('GMT_intermediate_coast_distance_01d.tif')

数据很大(im.size=(36000, 18000) 1.3GB),传统的转换方法不起作用,即 imarray.shape 返回 ()

import numpy as np 
imarray=np.zeros(im.size)
imarray=np.array(im)

我该如何将这个tiff文件转换为numpy.array?

1
传统转换不起作用 - 它为什么不起作用?你的输出是什么?它与你期望的有什么不同?你是否收到错误提示?如果是,回溯信息显示了什么? - That1Guy
2
尝试使用tifffile.py - cgohlke
@That1Guy imarray 是一个空数组。 - ilciavo
你有64位的Python吗? - Mark Ransom
@MarkRansom 是的,它是64位的。 - ilciavo
谢谢@cgohlke,现在我可以得到一个numpy.array了...加载数据需要一些时间。 - ilciavo
5个回答

4

你可能没有足够的内存来处理这张图片。你需要至少有1.3GB以上的可用内存。

我不知道你在做什么,如果可以的话,我建议你逐个像素地读取图片,以避免电脑崩溃。你可以使用Image.getdata(),每次返回一个像素。

此外,请阅读此链接中关于Image.open的更多信息:

http://www.pythonware.com/library/pil/handbook/


3

到目前为止,我已经测试了许多替代方案,但只有gdal总是能够正常工作,即使处理巨大的16位图像也是如此。

您可以使用以下方式打开图像:

from osgeo import gdal
import numpy as np
ds = gdal.Open("name.tif")
channel = np.array(ds.GetRasterBand(1).ReadAsArray())

如何安装GDAL以在Python中使用? - lesolorzanov

2

我有一些1到3 GB的大型tif文件,通过手动更改Image.py源代码中MAX_IMAGE_PIXELS的值为一个任意大的数字,最终成功使用Image.open()打开它们:

最初的回答:

from PIL import Image
im = np.asarray(Image.open("location/image.tif")

4
呃!别这么做!维护起来太麻烦了!只需在你自己的脚本中更改为 Image.MAX_IMAGE_PIXELS = None 即可。 - Mark Setchell

1

您可以尝试使用“dask”库:

import dask_image.imread

ds = dask_image.imread.imread('name.tif')

1
对于Python 32位,版本2.7而言,您在一次性向堆栈添加的字节数方面存在限制。其中一个选项是分部读取图像,然后调整个别块大小并重新组合成需要更少RAM的图像。
我建议使用libtiffopencv库来实现。
import os
os.environ["PATH"] += os.pathsep + "C:\\Program Files (x86)\\GnuWin32\\bin"
import numpy as np
import libtiff
import cv2

tif = libtiff.TIFF.open("HUGETIFFILE.tif", 'r')
width = tif.GetField("ImageWidth")
height = tif.GetField("ImageLength")
bits = tif.GetField('BitsPerSample')
sample_format = tif.GetField('SampleFormat')

ResizeFactor = 10 #Reduce Image Size by 10
Chunks = 8 #Read Image in 8 Chunks to prevent Memory Error (can be increased for 
# bigger files)

ReadStrip = tif.ReadEncodedStrip
typ = tif.get_numpy_type(bits, sample_format)


#ReadStrip
newarr = np.zeros((1, width/ResizeFactor), typ)
for ii in range(0,Chunks):
    pos = 0
    arr = np.empty((height/Chunks, width), typ)
    size = arr.nbytes
    for strip in range((ii*tif.NumberOfStrips()/Chunks),((ii+1)*tif.NumberOfStrips()/Chunks)):
        elem = ReadStrip(strip, arr.ctypes.data + pos, max(size-pos, 0))
        pos = pos + elem

    resized = cv2.resize(arr, (0,0), fx=float(1)/float(ResizeFactor), fy=float(1)/float(ResizeFactor))

    # Now remove the large array to free up Memory for the next chunk
    del arr
    # Finally recombine the individual resized chunks into the final resized image.
    newarr = np.vstack((newarr,resized))

newarr = np.delete(newarr, (0), axis=0)
cv2.imwrite('resized.tif', newarr)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接