Gnuplot中如何实现发光(霓虹)效果

8

我希望在gnuplot中实现这种效果:

霓虹灯效果

如何实现这种效果?如果不能实现,有哪些软件可以用来实现它?


1
首先,用什么软件制作了那张图片? - Matthew
@Matthew 不太确定,这个图形不是我做的,但我在最新的Excel里见过类似的图形:Excel 发光效果 - RedPointyJackson
3个回答

6

在gnuplot中,对于每个像素使用2D内核是可行的。这样,比单个像素更密集的积累会变得更亮。检查show palette rgbformulae和帮助文档中相关章节以更改颜色。

  set term wxt size 300,300 background rgb 0
  set view map
  set samp 140                                       
  set dgrid3d 180,180, gauss kdensity2d 0.2,0.2   
  set palette rgbform 4,4,3   
  splot "+" us 1:(sin($1/3)**2*20):(1)  with pm3d notitle

我惊叹于你的纯Gnuplot实现,你太厉害了。 - RedPointyJackson
我想功劳归于过去和现在的开发人员。 - Karl

4
< p >< em >免责声明:您可以按照此答案中的说明使用gnuplot完成此操作,但您应该考虑使用其他工具来绘制此特定类型的图。

至少有一种方法可以做到这一点,即通过数据预处理。思路是通过使用高斯核来模拟光晕效果以涂抹数据点。考虑以下数据,包含在名为data的文件中:

1   2
1   2.1
1.1 2.2
2   3
3   4

我特意将前三个点放在一起,以便观察相邻点的强光增强。这些数据看起来像这样:

enter image description here

现在,我们将使用2D高斯核来涂抹数据点。我编写了以下Python代码来帮助完成此过程。该代码在每个点周围有4个标准偏差(sxsy)的截止值。如果您希望发光为圆形,则应选择标准偏差,使得sx / sy比率与gnuplot中x/y轴长度的比率相同。否则,点看起来像椭圆。这是代码:
import numpy as np
import sys

filename = str(sys.argv[1])
sx = float(sys.argv[2])
sy = float(sys.argv[3])

def f(x,y,x0,y0,sx,sy):
    return np.exp(-(x-x0)**2/2./sx**2 -(y-y0)**2/2./sy**2)

datafile = open(filename, 'r')

data = []
for datapoint in datafile:
    a, b = datapoint.split()
    data.append([float(a),float(b)])

xmin = data[0][0]
xmax = data[0][0]
ymin = data[0][1]
ymax = data[0][1]
for i in range(1, len(data)):
    if(data[i][0] < xmin):
        xmin = data[i][0]
    if(data[i][0] > xmax):
        xmax = data[i][0]
    if(data[i][1] < ymin):
        ymin = data[i][1]
    if(data[i][1] > ymax):
        ymax = data[i][1]

xmin -= 4.*sx
xmax += 4.*sx
ymin -= 4.*sy
ymax += 4.*sy

dx = (xmax - xmin) / 250.
dy = (ymax - ymin) / 250.

for i in np.arange(xmin,xmax+dx, dx):
    for j in np.arange(ymin,ymax+dy, dy):
        s = 0.
        for k in range(0, len(data)):
            d2 = (i - data[k][0])**2 + (j - data[k][1])**2
            if( d2 < (4.*sx)**2 + (4.*sy)**2):
                s += f(i,j,data[k][0],data[k][1],sx,sy)
        print i, j, s

它的使用方法如下:

python script.py data sx sy

这里的 script.py 是代码所在文件的名称,data 是数据文件的名称,sxsy 是标准偏差。

现在,回到gnuplot,我们定义一个类似发光图案的调色板。对于孤立点,总和高斯分布会在该点的位置处产生1;对于重叠点,它会产生大于1的值。在定义调色板时必须考虑这一点。以下仅为示例:

set cbrange [0:3]
unset colorbox
set palette defined (0 "black", 0.5 "blue", 0.75 "cyan", 1 "white", 3 "white")
plot "< python script.py data 0.05 0.05" w image

enter image description here

你可以看到,这些点实际上是椭圆形,因为不同方向上的标准差比例与轴长度比例不同。这个问题可以很容易地解决:
plot "< python script.py data 0.05 0.06" w image

enter image description here


1

将背景设置为黑色,然后使用逐渐减小的点大小以不同颜色多次绘制数据集。

  set term wxt backgr rgb "black"
  plot sin(x) w p pt 7 ps 2 lc rgb 0x00003f not, \
       sin(x) w p pt 7 ps 1.5 lc rgb 0x00007f not, \
       sin(x) w p pt 7 ps 1 lc rgb 0x0000af not,  \
       sin(x) w p pt 7 ps .5 lc rgb 0x0000ff

或者,可以使用splot with pm3dset dgrid3d gauss kdensity2dset view map的某种组合,再加上适当的调色板,详见我的其他答案。


这种方法的问题在于相邻点的光亮不会“合并”。我考虑过发布一种可行但实现起来非常笨拙的方法:对XY平面中所有点(每个高斯函数以其对应的点为中心)执行2D高斯函数卷积,然后将所有高斯函数求和。现在使用颜色调色板绘制3D彩色地图,模仿发光效果。我用几个点测试了一下,它确实有效:对于任意数量的点,需要依赖外部(例如Python)程序,因此我没有发布它。 - Miguel
@Miguel 如果它能工作,你应该发布它。也许唯一的方法是借助外部程序来完成这个任务。我尝试使用与此答案相同的方法,但我将 alpha 设置得比不透明低,以便我的点会合并。然而,我对它并不完全满意。它看起来没有提供的图像那么平滑。我希望 OP 能回答我的问题,关于第一次使用了什么,因为观察它是如何完成的,可能会提供如何在 gnuplot 中完成它的见解。 - Matthew
@Matthew 我已经发布了我的解决方案和一个用于预处理的Python脚本,但我对它不满意:它太复杂了,而应该是非常简单的事情。 - Miguel
你对gnuplot的要求有些低了。;-) 请查看我的其他答案。 - Karl
@Karl 是的,那更符合我的想法。我通常使用1D高斯核,但不知道是否实现了2D选项。了解对于许多点来说gnuplot过程是否变得非常缓慢会很有趣。我知道Python在做这种事情时是次优的,我通常会用Fortran编写这种东西,但Fortran代码可能会让大多数在SO上检查此处的用户望而却步。 - Miguel
我猜速度与1/n成比例,而且很快就注意到它很慢。Gnuplot可能会为每个点和每个像素重新计算内核,因为数据点的位置没有被光栅化。 - Karl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接