图像像素上的 matplotlib 标记/掩码
matplotlib markers / mask on image pixels
所以我有一个图像,我有一个该图像的像素蒙版,其中蒙版与图像大小相同,包含值 0 和 1,如果是 0,我不想修改图像,如果它是 1,我想在图像的那个像素上添加透明颜色。
基本上我想突出显示图像的某些部分,但仍能看到下面的内容。
现在我到处搜索,但没有找到一个简单的方法来做到这一点。我使用 np.where 和掩码来获取 1 的像素位置以用于绘图函数。我首先尝试了具有小标记大小且没有边缘颜色(small scatter plot markers in matplotlib are always black)的散点图,但标记的大小不是一个图像像素,它们似乎是绝对大小,因此取决于图形的大小透明度受到影响,重叠的标记会产生奇怪的图案。
只是常规的 pyplot plot 函数创建了我想要的精确外观(其中着色平滑且不随图形大小变化)但它也为掩码中不相交的段之间的水平连接着色(我猜是因为它是画线) ,所以我无法使用它。
最有效的是补丁,我在这个问题中遇到过:(How to set a fixed/static size of circle marker on a scatter plot?)。我发现宽度和高度为 1 的矩形块给了我想要的效果,我可以在图像的某些像素上放置透明颜色。然而,事实证明这会为某些图像生成大量(数万个)矩形,因此速度非常慢。即使每次使用 PatchCollection 而不是调用 addPatch 时它仍然很慢。
现在我可能只连接相邻的矩形以减少需要绘制的东西的数量,但我只是想知道是否有更简单的方法来做到这一点?
谢谢。
您可以使用 蒙版数组 或通过在 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 那样完全 pixel-by-pixel 控制 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
),但只在图形的一半和另一半的窄交替对角线带中(由于遮罩)。这是使用掩码数组的更复杂的图像:
补充一下 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 值/透明度
我还需要在我的区域有一个清晰的轮廓。因此,您可以轻松地在顶部添加等高线图:例如,创建一个虚拟 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()
产生:
所以我有一个图像,我有一个该图像的像素蒙版,其中蒙版与图像大小相同,包含值 0 和 1,如果是 0,我不想修改图像,如果它是 1,我想在图像的那个像素上添加透明颜色。
基本上我想突出显示图像的某些部分,但仍能看到下面的内容。
现在我到处搜索,但没有找到一个简单的方法来做到这一点。我使用 np.where 和掩码来获取 1 的像素位置以用于绘图函数。我首先尝试了具有小标记大小且没有边缘颜色(small scatter plot markers in matplotlib are always black)的散点图,但标记的大小不是一个图像像素,它们似乎是绝对大小,因此取决于图形的大小透明度受到影响,重叠的标记会产生奇怪的图案。
只是常规的 pyplot plot 函数创建了我想要的精确外观(其中着色平滑且不随图形大小变化)但它也为掩码中不相交的段之间的水平连接着色(我猜是因为它是画线) ,所以我无法使用它。
最有效的是补丁,我在这个问题中遇到过:(How to set a fixed/static size of circle marker on a scatter plot?)。我发现宽度和高度为 1 的矩形块给了我想要的效果,我可以在图像的某些像素上放置透明颜色。然而,事实证明这会为某些图像生成大量(数万个)矩形,因此速度非常慢。即使每次使用 PatchCollection 而不是调用 addPatch 时它仍然很慢。
现在我可能只连接相邻的矩形以减少需要绘制的东西的数量,但我只是想知道是否有更简单的方法来做到这一点?
谢谢。
您可以使用 蒙版数组 或通过在 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 那样完全 pixel-by-pixel 控制 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
),但只在图形的一半和另一半的窄交替对角线带中(由于遮罩)。这是使用掩码数组的更复杂的图像:
补充一下 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 值/透明度
我还需要在我的区域有一个清晰的轮廓。因此,您可以轻松地在顶部添加等高线图:例如,创建一个虚拟 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()
产生: