我正在尝试使用Python中的scikit-image
模块读取4波段(红色,绿色,蓝色,近红外)geotiff(example data)并执行quickshift segmentation。
我创建了以下脚本(基于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数组需要以某种方式重新塑造。如何正确地将多波段地理数据读入一个numpy数组并执行图像分割?
答案 0 :(得分:3)
我相信您的问题是quickshift()
认为您的图片是rgb
。我从您提供的链接中下载了一张随机图片,然后将其读入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()
的{{3}}显示其标记为convert2lab
,默认为True
。
convert2lab :bool,optional(默认为True)在分段之前是否应将输入转换为Lab色彩空间。为此,输入假定为RGB 。
如果我将该标志设置为False
segments = quickshift(img, kernel_size=3, convert2lab=False, max_dist=6, ratio=0.5)
它运行。
plt.imshow(segments);
修改强>:
另外,我注意到你的图像形状是(4, 436, 553)
,这也是有问题的。 skimage
期望颜色通道最后。这可以通过
img = img.transpose(1, 2, 0)
答案 1 :(得分:0)
链接页面中示例的两个关键行
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.awt.geom.Path2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
@SuppressWarnings("serial")
public class RosePanel extends JPanel {
private static final int PREF_W = 400;
private static final int PREF_H = PREF_W;
private static final int MAX = 100;
private static final double SCALE = 150.0;
private static final double DELTA_X = 200;
private static final double DELTA_Y = DELTA_X;
private static final Color ROSE_COLOR = Color.red;
private static final Stroke ROSE_STROKE = new BasicStroke(8f);
private Path2D path = new Path2D.Double();
public RosePanel() {
for (int i = 0; i < MAX; i++) {
double theta = i * 2 * Math.PI / MAX;
double r = Math.cos(2 * theta);
double dX = SCALE * r * Math.cos(theta) + DELTA_X;
double dY = SCALE * r * Math.sin(theta) + DELTA_Y;
if (i == 0) {
path.moveTo(dX, dY);
} else {
path.lineTo(dX, dY);
}
}
path.closePath();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(ROSE_COLOR);
g2.setStroke(ROSE_STROKE);
g2.draw(path);
}
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private static void createAndShowGui() {
RosePanel mainPanel = new RosePanel();
JFrame frame = new JFrame("RosePanel");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
也就是说,你是对的。您需要将图像转换为其他格式。使用img_as_float()转换它。