如何使用Python的scikit-image在4波段地理基站上执行图像分割?

时间:2015-06-24 21:02:31

标签: python image-processing numpy scikit-image geotiff

我正在尝试使用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数组并执行图像分割?

2 个答案:

答案 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。因此,假设您的图片为rgbquickshift()的{​​{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);

enter image description here

修改

另外,我注意到你的图像形状是(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()转换它。