如何使用 Python 的 scikit-image 在 4 波段 geotiff 上执行图像分割?
How to perform image segmentation on 4-band geotiff using Python's scikit-image?
我正在尝试读取 4 波段(红、绿、蓝、近红外)geotiff(example data) and perform a quickshift segmentation 使用 Python 中的 scikit-image
模块。
我创建了以下脚本(基于 scikit example):
from __future__ import print_function
from osgeo import gdal
import matplotlib.pyplot as plt
import numpy as np
from skimage.segmentation import felzenszwalb, slic, quickshift
from skimage.segmentation import mark_boundaries
from skimage.util import img_as_float
image = r'C:\path\to\my\geotiff.tif'
img = io.imread(image, as_grey=False, plugin="gdal")
segments_quick = quickshift(img, kernel_size=3, max_dist=6, ratio=0.5)
我收到以下错误:
ValueError: the input array must be have a shape == (.., ..,[ ..,] 3)), got (4, 436, 553)
我很确定 numpy 数组需要以某种方式重塑。如何正确地将多波段 geotiff 读入 numpy 数组并执行图像分割?
链接页面示例中的 2 条关键行,
from skimage.util import img_as_float
img = img_as_float(image[::2, ::2])
也就是说,你是对的。您确实需要将图像转换为另一种格式。使用 img_as_float().
转换它
我认为您的问题是 quickshift()
认为您的图像是 rgb
。我从您提供的 link 下载了一个 运行dom 图像并将其读入 skimage。
img = io.imread('./m_4111722_ne_11_1_20100704.tif')
我将它的大小调整为 128x128x4(以便于计算)
img = transform.resize(img, (128, 128, 4))
然后 运行 quickshift()
segments = quickshift(img, kernel_size=3, max_dist=6, ratio=0.5)
并得到同样的错误。
ValueError: the input array must be have a shape == (.., ..,[ ..,] 3)), got (128, 128, 4)
在堆栈跟踪的较高位置它说
skimage/segmentation/_quickshift.pyx inskimage.segmentation._quickshift.\
quickshift (skimage/segmentation/_quickshift.c:1710)()
/****/****/anaconda/lib/python2.7/site-packages/skimage/color/colorconv.pyc in rgb2lab(rgb)
901 This function uses rgb2xyz and xyz2lab.
902 """
--> 903 return xyz2lab(rgb2xyz(rgb))
因此您可以看到 _quickshift.pyx
正在尝试转换 rgb --> xyz
,然后 xyz --> lab
。所以它 假设 你的图像是 rgb
。 quickshift()
的 skimage docs 显示它有一个标志 convert2lab
,默认为 True
。
convert2lab : bool, optional (default True) Whether the input should be converted to Lab colorspace prior to segmentation. For this purpose, the input is assumed to be RGB.
如果我重新运行你的函数并将该标志设置为False
segments = quickshift(img, kernel_size=3, convert2lab=False, max_dist=6, ratio=0.5)
它运行s.
plt.imshow(segments);
编辑:
顺便说一句,我注意到你的图像形状是 (4, 436, 553)
这也是有问题的。 skimage
预计颜色通道是最后一个。这可以用
补救
img = img.transpose(1, 2, 0)
我正在尝试读取 4 波段(红、绿、蓝、近红外)geotiff(example data) and perform a quickshift segmentation 使用 Python 中的 scikit-image
模块。
我创建了以下脚本(基于 scikit example):
from __future__ import print_function
from osgeo import gdal
import matplotlib.pyplot as plt
import numpy as np
from skimage.segmentation import felzenszwalb, slic, quickshift
from skimage.segmentation import mark_boundaries
from skimage.util import img_as_float
image = r'C:\path\to\my\geotiff.tif'
img = io.imread(image, as_grey=False, plugin="gdal")
segments_quick = quickshift(img, kernel_size=3, max_dist=6, ratio=0.5)
我收到以下错误:
ValueError: the input array must be have a shape == (.., ..,[ ..,] 3)), got (4, 436, 553)
我很确定 numpy 数组需要以某种方式重塑。如何正确地将多波段 geotiff 读入 numpy 数组并执行图像分割?
链接页面示例中的 2 条关键行,
from skimage.util import img_as_float
img = img_as_float(image[::2, ::2])
也就是说,你是对的。您确实需要将图像转换为另一种格式。使用 img_as_float().
转换它我认为您的问题是 quickshift()
认为您的图像是 rgb
。我从您提供的 link 下载了一个 运行dom 图像并将其读入 skimage。
img = io.imread('./m_4111722_ne_11_1_20100704.tif')
我将它的大小调整为 128x128x4(以便于计算)
img = transform.resize(img, (128, 128, 4))
然后 运行 quickshift()
segments = quickshift(img, kernel_size=3, max_dist=6, ratio=0.5)
并得到同样的错误。
ValueError: the input array must be have a shape == (.., ..,[ ..,] 3)), got (128, 128, 4)
在堆栈跟踪的较高位置它说
skimage/segmentation/_quickshift.pyx inskimage.segmentation._quickshift.\
quickshift (skimage/segmentation/_quickshift.c:1710)()
/****/****/anaconda/lib/python2.7/site-packages/skimage/color/colorconv.pyc in rgb2lab(rgb)
901 This function uses rgb2xyz and xyz2lab.
902 """
--> 903 return xyz2lab(rgb2xyz(rgb))
因此您可以看到 _quickshift.pyx
正在尝试转换 rgb --> xyz
,然后 xyz --> lab
。所以它 假设 你的图像是 rgb
。 quickshift()
的 skimage docs 显示它有一个标志 convert2lab
,默认为 True
。
convert2lab : bool, optional (default True) Whether the input should be converted to Lab colorspace prior to segmentation. For this purpose, the input is assumed to be RGB.
如果我重新运行你的函数并将该标志设置为False
segments = quickshift(img, kernel_size=3, convert2lab=False, max_dist=6, ratio=0.5)
它运行s.
plt.imshow(segments);
编辑:
顺便说一句,我注意到你的图像形状是 (4, 436, 553)
这也是有问题的。 skimage
预计颜色通道是最后一个。这可以用
img = img.transpose(1, 2, 0)