Python 在图形中勾勒出一个区域的轮廓

Python 在图形中勾勒出一个区域的轮廓,python,numpy,matplotlib,plot,Python,Numpy,Matplotlib,Plot,我有两个二维numpy阵列(尺寸相同),我正在使用matplotlib打印它们。我绘制的第一个数组是灰度彩色贴图。第二个代表一个光圈,但它是一个不规则的形状(一些像素被勾勒出来,是一组水平线和垂直线形成的轮廓)。我不知道如何让它绘制第二个数组。数组由三个数字(0、1和3)组成,我只需要一个值(3)的像素轮廓,但我需要轮廓来包含这些像素的区域,而不是单独的像素。我需要所有像素的内部保持透明,以便我可以通过它看到灰度彩色贴图 有人知道如何做到这一点吗 如果我理解正确的话,那是一个有趣的问题。为了确定

我有两个二维numpy阵列(尺寸相同),我正在使用matplotlib打印它们。我绘制的第一个数组是灰度彩色贴图。第二个代表一个光圈,但它是一个不规则的形状(一些像素被勾勒出来,是一组水平线和垂直线形成的轮廓)。我不知道如何让它绘制第二个数组。数组由三个数字(0、1和3)组成,我只需要一个值(3)的像素轮廓,但我需要轮廓来包含这些像素的区域,而不是单独的像素。我需要所有像素的内部保持透明,以便我可以通过它看到灰度彩色贴图


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

如果我理解正确的话,那是一个有趣的问题。为了确定您的意思,您希望在像素值为3的所有相邻区域周围绘制一条带有某种颜色的线

我不认为有一个现成的功能,但让我们不要让它阻止我们。我们需要创建自己的函数

我们可以从创建需要勾勒的区域的布尔图开始:

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)
让我们通过生成一些数据并显示它来测试这一点:

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')
之后,我们在顶部运行该过程,并获得:


如果需要的话,代码可以更加密集,但是现在注释占用了大量空间。对于大型图像,通过查找连续路径来优化图像段的创建可能是明智的。这将使要绘制的点数减少最多三倍。然而,这样做需要一点不同的代码,这并不像这个代码那么清楚。(如果有评论要求这样做,并且有适当数量的投票,我会加上:)

我刚刚注意到你没有接受我下面的回答。如果你有充分的理由,那也没什么错。然而,为了了解更多,如果你对原因发表评论,那将是非常有趣的。这样我就可以知道我的答案有什么问题,并可能对其进行改进,以便更好地回答您的问题@DrV,答案本身没有问题,但我无法使用您提供的代码重现您的结果。我正试图确定原因。我也无法根据我的目的修改您的代码,所以我想,一旦我确实找到它来回答我的问题,也许我会重新接受它作为答案。不过,我确实计划重新接受它,因为这是一个非常好的答案。如果掩码不包含任何段,则l将为空,并且失败;-)谢谢你的精彩片段!