我有一个600×600×40维的数组,每个波段(来自40个波段)代表一个600×600的图像,我想把它保存到一个多波段的.tif图像中。我已经尝试了这个功能,从scikit image和openCV,但他们不能保存超过3个波段(作为RGB)。
import cv2
cv2.imwrite('image.tif',600by600_just3band_array)
发布于 2018-12-15 01:09:45
tifffile
(https://pypi.org/project/tifffile/)支持多通道.tiff,其接口类似于scikit-image
或OpenCV
In [1]: import numpy as np
In [2]: import tifffile
In [3]: # Channel dimension should come first
In [4]: x = np.random.randint(0, 255, 4*100*100).reshape((4, 100, 100))
In [5]: tifffile.imsave('test.tiff', x)
In [6]: y = tifffile.imread('test.tiff')
In [7]: np.all(np.equal(x, y))
Out[7]: True
发布于 2018-12-14 18:42:38
您可以使用PIL/Pillow将多个图像保存在单个TIFF文件中,每个图像表示一个单独的带(灰度),甚至多个带(彩色),如下所示:
from PIL import Image
# Synthesize 8 dummy images, all greyscale, all same size but with varying brightness
size=(480,640)
b1 = Image.new('L', size, color=10)
b2 = Image.new('L', size, color=20)
b3 = Image.new('L', size, color=30)
b4 = Image.new('L', size, color=40)
b5 = Image.new('L', size, color=50)
b6 = Image.new('L', size, color=60)
b7 = Image.new('L', size, color=70)
b8 = Image.new('L', size, color=80)
# Save all 8 to single TIFF file
b1.save('multi.tif', save_all=True, append_images=[b2,b3,b4,b5,b6,b7,b8])
如果您现在在命令行中使用ImageMagick检查该文件,您可以看到所有8个区段都存在:
magick identify multi.tif
multi.tif[0] TIFF 480x640 480x640+0+0 8-bit Grayscale Gray 2.34473MiB 0.000u 0:00.000
multi.tif[1] TIFF 480x640 480x640+0+0 8-bit Grayscale Gray 2.34473MiB 0.000u 0:00.000
multi.tif[2] TIFF 480x640 480x640+0+0 8-bit Grayscale Gray 2.34473MiB 0.000u 0:00.000
multi.tif[3] TIFF 480x640 480x640+0+0 8-bit Grayscale Gray 2.34473MiB 0.000u 0:00.000
multi.tif[4] TIFF 480x640 480x640+0+0 8-bit Grayscale Gray 2.34473MiB 0.000u 0:00.000
multi.tif[5] TIFF 480x640 480x640+0+0 8-bit Grayscale Gray 2.34473MiB 0.000u 0:00.000
multi.tif[6] TIFF 480x640 480x640+0+0 8-bit Grayscale Gray 2.34473MiB 0.000u 0:00.000
multi.tif[7] TIFF 480x640 480x640+0+0 8-bit Grayscale Gray 2.34473MiB 0.000u 0:00.000
如果您使用OpenCV或Numpy数组进行处理,您可以使用以下命令将OpenCV或Numpy数组转换为PIL/Pillow图像:
PILimage = Image.fromarray(numpyImage)
反过来,从PIL/Pillow图像到Numpy数组:
NumpyImage = np.array(PILimage)
如果你想重新读一遍,你可以这样做:
# Open the multi image
im = Image.open('multi.tif')
# Iterate through frames
for frame in ImageSequence.Iterator(im):
frame.show()
如果你想移动到一个特定的波段,你可以像这样寻找:
im = Image.open('multi.tif')
im.seek(3)
im.show()
您也可以在命令行中使用ImageMagick从TIF中提取band3并另存为PNG,方法是:
magick multi.tif[3] band3.png
或者使用以下内容制作波段1、2、7 RGB合成:
magick multi.tif[1] multi.tif[2] multi.tif[7] -colorspace RGB -combine 127rgb.png
这将看起来是深蓝色的,因为红色和绿色通道非常低,并且只有蓝色通道具有较大的值。
我在Python上不是世界上最好的,所以我不确定有什么影响/错误,但我认为如果你有一个600x600x40的numpy图像数组,你可以像我建议的那样:
# Synthesize dummy array of 40 images, each 600x600
nparr = np.random.randint(0,256,(600,600,40), dtype=np.uint8)
# Make PIL/Pillow image of first
a = Image.fromarray(nparr[:,:,0])
# Save whole lot in one TIF
a.save('multi.tif', save_all=True, append_images=[Image.fromarray(nparr[:,:,x]) for x in range(1,40)])
关键词:多波段,多波段,多光谱,多光谱,卫星图像,图像,图像处理,Python,Numpy,PIL,Pillow,TIFF
发布于 2018-12-14 21:19:21
Mark的聪明答案是制作一个多页TIFF。不幸的是,imagemagick和PIL实际上是单声道/ RGB / RGBA / CMYK库,它们不直接支持多波段图像。
pyvips具有真正的多频带支持。例如:
import sys
import pyvips
import numpy as np
# make a (100, 100, 40) numpy image
array = np.zeros((100, 100, 40), dtype=sys.argv[2])
# convert to vips and save
image = numpy2vips(array)
image.write_to_file(sys.argv[1])
# read it back, convert to numpy, and show info
image2 = pyvips.Image.new_from_file(sys.argv[1])
array = vips2numpy(image2)
print("shape =", array.shape)
print("format =", array.dtype)
我可以这样运行它:
$ ./try284.py x.tif uint8
shape = (100, 100, 40)
format = uint8
$ vipsheader x.tif
x.tif: 100x100 uchar, 40 bands, srgb, tiffload
$ identify x.tif
x.tif TIFF 100x100 100x100+0+0 8-bit sRGB 400KB 0.000u 0:00.000
它还支持其他数据类型:
$ ./try284.py x.tif uint32
shape = (100, 100, 40)
format = uint32
$ ./try284.py x.tif float32
shape = (100, 100, 40)
format = float32
等等等等。
您可以将这些TIFF加载到gdal中。我想gdal也可以用来编写它们,尽管我还没有尝试过。令人恼火的是,它将40移动到最外面的维度。
$ python3
Python 3.6.7 (default, Oct 22 2018, 11:32:17)
[GCC 8.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from osgeo import gdal
>>> x = gdal.Open("x.tif")
>>> a = x.ReadAsArray()
>>> a.shape
(40, 100, 100)
vips2numpy()
和numpy2vips()
的定义如下:
https://github.com/libvips/pyvips/blob/master/examples/pil-numpy-pyvips.py
复制-粘贴以供参考:
# map vips formats to np dtypes
format_to_dtype = {
'uchar': np.uint8,
'char': np.int8,
'ushort': np.uint16,
'short': np.int16,
'uint': np.uint32,
'int': np.int32,
'float': np.float32,
'double': np.float64,
'complex': np.complex64,
'dpcomplex': np.complex128,
}
# map np dtypes to vips
dtype_to_format = {
'uint8': 'uchar',
'int8': 'char',
'uint16': 'ushort',
'int16': 'short',
'uint32': 'uint',
'int32': 'int',
'float32': 'float',
'float64': 'double',
'complex64': 'complex',
'complex128': 'dpcomplex',
}
# numpy array to vips image
def numpy2vips(a):
height, width, bands = a.shape
linear = a.reshape(width * height * bands)
vi = pyvips.Image.new_from_memory(linear.data, width, height, bands,
dtype_to_format[str(a.dtype)])
return vi
# vips image to numpy array
def vips2numpy(vi):
return np.ndarray(buffer=vi.write_to_memory(),
dtype=format_to_dtype[vi.format],
shape=[vi.height, vi.width, vi.bands])
https://stackoverflow.com/questions/53776506
复制相似问题