在图中勾勒出一个区域 [英] Outline a region in a graph

查看:49
本文介绍了在图中勾勒出一个区域的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个使用matplotlib绘制的二维(相同尺寸)numpy数组.我绘制的第一个数组是灰度的彩色图.第二个代表孔,但它是不规则形状(某些像素被勾勒出轮廓,并且是形成轮廓的一组水平和垂直线).我不确定如何要求它绘制第二个数组.该数组由三个数字(0、1和3)组成,我只需要勾勒一个值(3)的像素,但是我需要勾勒轮廓来包围这些像素的区域,而不是单个像素.我需要所有像素的内部保持透明,以便可以通过它看到灰度色图.

I have two 2D numpy arrays (of the same dimensions) that I am plotting using matplotlib. The first array I've plotted as a color map in gray-scale. The second one represents an aperture, but it is an irregular shape (some of the pixels get outlined, and it is a set of horizontal and vertical lines that form the outline). I am not sure how to ask it to plot this second array. The array is composed of three numbers (0, 1, and 3), and I only need the pixels of one value (3) to be outlined, but I need the outline to encompass the region of these pixels, not the pixels individually. I need the interior of all the pixels to remain transparent so that I can see the gray-scale color map through it.

有人知道如何做到这一点吗?

Does anyone know how to accomplish this?

推荐答案

如果我正确理解的话,这是一个有趣的问题.为了确保您的意思,您想在像素值为3的所有连续区域周围绘制一条带有某种颜色的线.

That is an interesting question, if I understood it correctly. In order to make sure what you mean, you would like to draw a line with some color around all contiguous areas where the pixel value is 3.

我认为没有现成的功能,但是我们不要阻止它.我们将需要创建自己的函数.

I do not think there is a ready-made function for that, but let's not let that stop us. We will need to create our own function.

我们可以先创建一个需要概述区域的布尔图:

We can start by creating a boolean map of the area which needs to be outlined:

import numpy as np
import matplotlib.pyplot as plt

# our image with the numbers 1-3 is in array maskimg
# create a boolean image map which has trues only where maskimg[x,y] == 3
mapimg = (maskimg == 3)

# a vertical line segment is needed, when the pixels next to each other horizontally
#   belong to diffferent groups (one is part of the mask, the other isn't)
# after this ver_seg has two arrays, one for row coordinates, the other for column coordinates 
ver_seg = np.where(mapimg[:,1:] != mapimg[:,:-1])

# the same is repeated for horizontal segments
hor_seg = np.where(mapimg[1:,:] != mapimg[:-1,:])

# if we have a horizontal segment at 7,2, it means that it must be drawn between pixels
#   (2,7) and (2,8), i.e. from (2,8)..(3,8)
# in order to draw a discountinuous line, we add Nones in between segments
l = []
for p in zip(*hor_seg):
    l.append((p[1], p[0]+1))
    l.append((p[1]+1, p[0]+1))
    l.append((np.nan,np.nan))

# and the same for vertical segments
for p in zip(*ver_seg):
    l.append((p[1]+1, p[0]))
    l.append((p[1]+1, p[0]+1))
    l.append((np.nan, np.nan))

# now we transform the list into a numpy array of Nx2 shape
segments = np.array(l)

# now we need to know something about the image which is shown
#   at this point let's assume it has extents (x0, y0)..(x1,y1) on the axis
#   drawn with origin='lower'
# with this information we can rescale our points
segments[:,0] = x0 + (x1-x0) * segments[:,0] / mapimg.shape[1]
segments[:,1] = y0 + (y1-y0) * segments[:,1] / mapimg.shape[0]

# and now there isn't anything else to do than plot it
plt.plot(segments[:,0], segments[:,1], color=(1,0,0,.5), linewidth=3)

让我们通过生成一些数据并显示它来对其进行测试:

Let us test this by generating some data and showing it:

image = np.cumsum(np.random.random((20,20))-.5, axis=1)
maskimg = np.zeros(image.shape, dtype='int')
maskimg[image > 0] = 3

x0 = -1.5
x1 =  1.5
y0 = 2.3
y1 = 3.8

plt.figure()
plt.imshow(maskimg, origin='lower', extent=[x0,x1,y0,y1], cmap=plt.cm.gray, interpolation='nearest')
plt.axis('tight')

此后,我们在顶部运行该过程,并获得:

After that we run the procedure on the top, and get:

如果需要,可以使代码更密集,但是现在注释占用了大量空间.对于大图像,通过查找连续路径来优化图像片段创建可能是明智的.这样可以将要绘制的点数减少多达三倍.但是,这样做需要一些不同的代码,这不像此代码那么清楚. (如果会出现要求提供评论和适当数量的支持的投票,我将其添加:)

The code can be made much denser, if needed, but now comments take a lot of space. With large images it might be wise to optimize the image segment creation by finding continuous paths. That will reduce the number of points to plot by a factor of up to three. However, doing that requires a bit different code, which is not as clear as this one. (If there will appear comments asking for that and an appropriate number of upvotes, I'll add it :)

这篇关于在图中勾勒出一个区域的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆