【问题标题】:matplotlib markers / mask on image pixels图像像素上的 matplotlib 标记/掩码
【发布时间】:2018-05-10 00:06:32
【问题描述】:

所以我有一个图像,并且我有该图像的像素掩码,其中掩码与图像大小相同,并且包含值 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 时它仍然很慢。

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

谢谢。

【问题讨论】:

    标签: python matplotlib


    【解决方案1】:

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

    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 值进行逐像素控制。

    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),但只在图中的一半和另一半的窄交替对角带中(由于面具)。这是一个使用掩码数组的更复杂的图像:

    【讨论】:

    • 对不起,我对如何使用它有点困惑。因此,如果我有一个 800x800 背景图像,并且我有一个包含 3 个 20x20 正方形的 1 且其他所有内容为 0 的蒙版,我将如何使用它将这 3 个正方形绘制为图像上的半透明红色框?
    【解决方案2】:

    只是补充一下 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 值/透明度

    【讨论】:

      【解决方案3】:

      我的区域还需要清晰的轮廓。因此,您可以轻松地在顶部添加等高线图:例如,创建一个虚拟 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()
      

      产生:

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-04-17
        • 2020-01-14
        • 1970-01-01
        • 2017-02-06
        • 1970-01-01
        • 1970-01-01
        • 2022-01-25
        • 2016-03-19
        相关资源
        最近更新 更多