matplotlib标记/图像像素上的掩码

时间:2015-01-23 03:39:16

标签: python matplotlib

所以我有一个图像,我有一个像素掩码,其中掩码与图像大小相同,包含0和1的值,如果是0,我不想修改图像,如果是1,我想在图像的像素上添加透明色。

基本上我想要突出显示图像的某些部分,但仍然可以看到底部的内容。

现在我已经搜索过高低,但还没有找到一个简单的方法来做到这一点。我使用带掩码的np.where来获取1的像素位置以用于绘图函数。我首先尝试使用较小的标记大小并且没有边缘颜色(small scatter plot markers in matplotlib are always black)的散点图,但标记不是一个图像像素的大小,它们似乎是绝对大小,因此取决于图的大小透明度受到影响,并且重叠标记会创建奇怪的图案。

只是常规的Pyplot绘图函数创建了我想要的精确外观(颜色是平滑的并且对图形大小不变)但是它还在面具中的不相交的段之间着色水平连接(因为它是我想的绘制线),所以我无法使用它。

效果最好的是补丁,我在这个问题中遇到过:(How to set a fixed/static size of circle marker on a scatter plot?)。我发现宽度和高度为1的矩形贴片给了我精确的效果,我可以在图像的某些像素上放置透明色。然而,这被证明可以为某些图像产生一吨(数万)矩形,因此它非常慢。即使使用PatchCollection而不是每次它仍然很慢时调用addPatch。

现在我可以加入相邻的矩形以减少需要绘制的东西的数量,但我只是想知道是否有更简单的方法来做到这一点?

感谢。

3 个答案:

答案 0 :(得分:2)

您可以使用蒙版数组或在 RGBA图像中设置Alpha值来进行半透明叠加。这两个都是通过(使用放置在圆形图案上的三个半透明红色正方形的例子),并且它们给出相似的图像(所以我只展示一个):

enter image description here

from pylab import *
from numpy import ma

x = y = linspace(-6, 6, 100)
X, Y = meshgrid(x, y)

z3 = X*X + Y*Y  # circular pattern

# first, do this with a masked array
figure()
# z4 = 3 diagonal square
# zm = a uniform image (ones), with a mask of squares (~z4)
z4 =  np.repeat(np.repeat(eye(3, dtype=bool), 40, axis=0), 40, axis=1)
zm = ma.masked_where(~z4, ones((120,120)))
imshow(z3, cmap=cm.jet)
imshow(zm, cmap=cm.bwr, alpha=.3, vmin=0, vmax=1) #cm.bwr is an easy way to get red

# do this by changing alpha for each pixel
figure()
z5 = zeros((120, 120, 4), dtype=float)
z5[..., 0] = 1
z5[..., 3] = .4*z4.astype(float)
imshow(z3, cmap=cm.jet)
imshow(z5)

show()

我认为这两种方法都能为所有案例产生相同的结果,但是: 1。如果蒙版或合成变得复杂,蒙版阵列可以是更直接的方法,并且蒙版可以更灵活地绘制叠加图像,例如,您可以使用色彩映射而不是指定每个像素都有完整的RGBA,但是,
2。屏蔽数组方法不会像RGBA那样对alpha值进行完整的逐像素控制。

enter image description here

z1 = sin(X*Y)
z1 = cos(2*X)
z2 = cos(5*(X+Y))

zm = ma.masked_where( (z2<.5) & (Y>0), z1)

figure()
imshow(z3)
imshow(zm, cmap=cm.gray, alpha=.4, vmin=-2, vmax=2)
show()

这有点疯狂,但这是正在发生的事情:主图像是一个从蓝色到红色的圆形图案(z3)。然后有一些垂直条纹使这个(z1)模糊不清,但只有一半的数字和另一半的窄交替对角线条带(由于掩模)。这是使用蒙版数组的更复杂的图像:

答案 1 :(得分:0)

为了补充tom10发布的内容,屏蔽数组可以很好地处理色彩映射,但同时我还编写了一个小函数,可以处理任何RGB颜色元组。

def overlayImage(im, mask, col, alpha):
    maskRGB = np.tile(mask[..., np.newaxis], 3)
    untocuhed = (maskRGB == False) * im
    overlayComponent = alpha * np.array(col) * maskRGB
    origImageComponent = (1 - alpha) * maskRGB * im
    return untocuhed + overlayComponent + origImageComponent

im是rgb图片

mask是图像的布尔掩码,例如mask.shape +(3,)= im.shape

col只是您要用

屏蔽图像的3元组rgb值

alpha只是面具的alpha值/透明度

答案 2 :(得分:0)

我的区域也需要清晰的轮廓。因此,您可以轻松地在顶部添加等高线图:例如,创建虚拟numpy数组并在每个感兴趣的区域中设置不同的值。 这是一个基于tom10的答案,以不同条件构建的示例:

x = y = linspace(-6, 6, 100)
X, Y = meshgrid(x, y)

z3 = X*X + Y*Y  # circular pattern

# first, do this with a masked array
figure()
imshow(z3, cmap=cm.jet, extent = (-6,6,-6,6));
zm = ma.masked_where((z3>=0.7) & (z3<=1.5), ones(np.shape(z3)));
imshow(zm, cmap=cm.bwr, alpha=.4, vmin=0, vmax=1, extent = (-6,6,-6,6)) #cm.bwr is an easy way to get red
# Build dummy array of 1s and 0s (you can play with different values to obtain different contours for different regions):
temp_vector = ones(np.shape(z3));
temp_vector[(z3>=0.7) & (z3<=1.5)] = 0.0;
temp_vector[(z3>8.2)] = 2.0; # etc.
# Create contour. I found only one contour necessary:
contour(X, Y, temp_vector, 1, colors=['r','g']);


show()

哪个收益率: Masked alpha && contours