如何在Matplotlib中绘制模糊点
正如问题所说,我想找一种方法用Matplotlib画模糊的点。 我不想先画一堆点,然后再对整个图像应用滤镜来模糊。相反,我想画一组点,每个点都有一个对应的模糊程度。
提前谢谢你。
2 个回答
8
当你做不到的时候,就假装能做到。
import matplotlib.pyplot as plt
import numpy as np
# some random data
x = np.random.random(100)
y = np.random.random(100)
z = np.random.random(100)
# z reflects the amount of defocus at each dot
# if z=0, the point is small (1 pt)
# if z=1, the point is large (50 pt)
# each dot is composed of different layers
fig = plt.figure()
ax = fig.add_subplot(111)
for i in np.arange(.1,1.01,.1):
ax.scatter(x, y, s=(50*i*(z*.9+.1))**2, color=(0,0,0,.5/i/10))
这样做会得到:
这并不是完美的,但类似的东西可能能满足你的需求。需要考虑的几点:
- 现在的点大小是绝对单位,不会随其他东西缩放(如果要缩放,需要更多的数学计算)
- 如果你想让每个点的墨水量相等,就得为更大的块减少透明度值
- 你想让模糊的直径反映数值(像这里这样)还是模糊的面积?
- 真正的“模糊”通常是高斯模糊,但这里不是;可以做到,但那样的话大小和透明度的缩放会变得复杂一些
- 当模糊的点重叠时,你希望看到什么效果?
- 在处理透明度值和颜色值时,记得显示器的伽马函数
所以,这只是一个丑陋的假象。有时候看起来还不错,有时候就不行。
10
这里有另一种解决方法。你可以在每个位置显示一张图片,而不是使用标记,这可以通过 BboxImage
来实现。这样你就可以对图片进行模糊处理或者以任何你想要的方式进行调整。这个教程里有更多关于 BboxImages 的内容。
import matplotlib.pyplot as plt
from scipy import ndimage
from matplotlib.image import BboxImage
from matplotlib.transforms import Bbox, TransformedBbox
import numpy as np
# Create and save an image with just a marker in it
fig1 = plt.figure()
ax1 = fig1.add_subplot(111)
ax1.plot(0.5,0.5,'*',ms=200)
ax1.set_ylim(0,1)
ax1.set_xlim(0,1)
plt.axis('off')
fig1.savefig('marker.png')
# Read in the same marker image
marker = plt.imread('marker.png')
# New figure and data
fig2 = plt.figure()
ax2 = fig2.add_subplot(111)
x = 8*np.random.rand(10) + 1
y = 8*np.random.rand(10) + 1
sigma = np.arange(10,60,5)
# Blur the marker and image plot the blurred image at each data point.
for xi, yi, sigmai in zip(x,y,sigma):
markerBlur = ndimage.gaussian_filter(marker,sigmai) # Blur the marker image
# Create an BboxImage for the blurred marker and add it to the plot.
bb = Bbox.from_bounds(xi,yi,1,1)
bb2 = TransformedBbox(bb,ax2.transData)
bbox_image = BboxImage(bb2,
norm = None,
origin=None,
clip_on=False)
bbox_image.set_data(markerBlur)
ax2.add_artist(bbox_image)
ax2.set_xlim(0,10)
ax2.set_ylim(0,10)
plt.show()