【问题标题】:Extract image segment from polygon, with skimage使用 skimage 从多边形中提取图像片段
【发布时间】:2016-05-08 18:52:11
【问题描述】:

我想获取从图像中剪切出多边形得到的子图像。

我在 skimage 中有一个图像,我在 matplotlib.patches 中有一个多边形。

怎么做?

以下是我尝试过的。我不一定要寻找类似于下面的方法,我正在寻找最干净、最有效的实现方式。


使用此代码,多边形正确地覆盖了我要提取的图像部分(但不提取感兴趣的部分):

import numpy as np
import skimage.io as io
import matplotlib.pyplot as plt
from matplotlib.collections import PatchCollection
from matplotlib.patches import Polygon

I = io.imread(fp) # fp is path to image
plt.imshow(I)
ax = plt.gca()

polygons, color = [], []   
c = np.random.random((1, 3)).tolist()[0]
for seg in ann['segmentation']:
    poly = np.array(seg).reshape((len(seg)/2, 2))
    polygons.append(Polygon(poly, True,alpha=0.4))
    color.append(c)
p = PatchCollection(polygons, facecolors=color, edgecolors=(0,0,0,1), linewidths=3, alpha=0.4)

ax.add_collection(p)

但是当我尝试使用此代码获取分段图像时,覆盖显示错误:

fig, ax = plt.subplots()
im = ax.imshow(I)
im.set_clip_path(polygon)
plt.axis('off')
plt.show()

看起来多边形的 Y 坐标只需要翻转(特别是因为上图显示 Y 轴以其他方式排列),但事实并非如此:

a = polygons[0].xy.copy()
a[:,1] = im._A.shape[0] - a[:,1]
newPoly = Polygon(a, True,alpha=0.4)
fig, ax = plt.subplots()
im = ax.imshow(I)
im.set_clip_path(newPoly)
plt.axis('off')
plt.show()

(其实不止X坐标有偏移问题,Y坐标也有比例问题,不知道为什么)

【问题讨论】:

  • 什么是an in the loop?对于 seg 在 ann['segmentation']: poly = np.array(seg).reshape((len(seg)/2, 2)) polygons.append(Polygon(poly, True,alpha=0.4)) color.append (c)

标签: python matplotlib scikit-image


【解决方案1】:

我也无法解释这种奇怪的行为。无论如何,最近在another question 中,我提出了一个可能对这里有所帮助的食谱(尽管我不会称其为最干净的解决方案)。使用这个(不是很漂亮)代码:

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
from matplotlib import path

class LineBuilder:
    def __init__(self, line,ax,color):
        self.line = line
        self.ax = ax
        self.color = color
        self.xs = []
        self.ys = []
        self.cid = line.figure.canvas.mpl_connect('button_press_event', self)
        self.counter = 0
        self.shape_counter = 0
        self.shape = {}
        self.precision = 10

    def __call__(self, event):
        if event.inaxes!=self.line.axes: return
        if self.counter == 0:
            self.xs.append(event.xdata)
            self.ys.append(event.ydata)
        if np.abs(event.xdata-self.xs[0])<=self.precision and np.abs(event.ydata-self.ys[0])<=self.precision and self.counter != 0:
            self.xs.append(self.xs[0])
            self.ys.append(self.ys[0])
            self.ax.scatter(self.xs,self.ys,s=120,color=self.color)
            self.ax.scatter(self.xs[0],self.ys[0],s=80,color='blue')
            self.ax.plot(self.xs,self.ys,color=self.color)
            self.line.figure.canvas.draw()
            self.shape[self.shape_counter] = [self.xs,self.ys]
            self.shape_counter = self.shape_counter + 1
            self.xs = []
            self.ys = []
            self.counter = 0
        else:
            if self.counter != 0:
                self.xs.append(event.xdata)
                self.ys.append(event.ydata)
            self.ax.scatter(self.xs,self.ys,s=120,color=self.color)
            self.ax.plot(self.xs,self.ys,color=self.color)
            self.line.figure.canvas.draw()
            self.counter = self.counter + 1

def create_shape_on_image(data,cmap='jet'):
    def change_shapes(shapes):
        new_shapes = {}
        for i in range(len(shapes)):
            l = len(shapes[i][1])
            new_shapes[i] = np.zeros((l,2),dtype='int')
            for j in range(l):
                new_shapes[i][j,0] = shapes[i][0][j]
                new_shapes[i][j,1] = shapes[i][1][j]
        return new_shapes
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.set_title('click to include shape markers (10 pixel precision to close the shape)')
    line = ax.imshow(data) 
    ax.set_xlim(0,data[:,:,0].shape[1])
    ax.set_ylim(0,data[:,:,0].shape[0])
    linebuilder = LineBuilder(line,ax,'red')
    plt.gca().invert_yaxis()
    plt.show()
    new_shapes = change_shapes(linebuilder.shape)
    return new_shapes

img = mpimg.imread('wm4HA.png')

shapes = create_shape_on_image(img)[0]

xx,yy = np.meshgrid(range(img.shape[0]),range(img.shape[1]))
shapes = np.hstack((shapes[:,1][:,np.newaxis],shapes[:,0][:,np.newaxis]))
p = path.Path(shapes)
for i in range(img.shape[0]):
    for j in range(img.shape[1]):
        if not p.contains_point((i,j)):
            img[i,j,:] = np.array([0,0,0,0])

plt.imshow(img)

plt.show()

我可以构建您想要的结果:

对你来说最重要的代码是这样的:

img = mpimg.imread('wm4HA.png')

shapes = create_shape_on_image(img)[0] # Here I'm calling a function to build a polygon.

xx,yy = np.meshgrid(range(img.shape[0]),range(img.shape[1]))
shapes = np.hstack((shapes[:,1][:,np.newaxis],shapes[:,0][:,np.newaxis]))
p = path.Path(shapes)
for i in range(img.shape[0]):
    for j in range(img.shape[1]):
        if not p.contains_point((i,j)):
            img[i,j,:] = np.array([0,0,0,0])

plt.imshow(img)

plt.show()

在这种情况下,我使用配方逐点构建多边形并单击:

使用该多边形,我将 alpha 通道(在 RGBA 中,我认为 JPEG 只是 RGB)设为 0 以表示透明度。

我知道它并不完美,但我希望它有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-10-26
    • 2020-09-02
    • 1970-01-01
    • 2015-09-03
    • 2014-05-05
    • 2013-03-02
    • 2014-03-09
    相关资源
    最近更新 更多