本文介绍了使用 matplotlib/pyplot 绘制混合线条颜色的曲线的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想以一种颜色开始曲线,然后逐渐融入另一种颜色直到结束.我的 MCVE 中的以下函数可以工作,但肯定有更好的方法我还没有发现?!

I want to start the curve with one color and progressively blend into another color until the end. The following function in my MCVE works, but surely, there has to be a better way I haven't found out about, yet?!

import numpy as np
import matplotlib.pyplot as plt

def colorlist(color1, color2, num):
    """Generate list of num colors blending from color1 to color2"""
    result = [np.array(color1), np.array(color2)]
    while len(result) < num:
        temp = [result[0]]
        for i in range(len(result)-1):
            temp.append(np.sqrt((result[i]**2+result[i+1]**2)/2))
            temp.append(result[i+1])
        result = temp
    indices = np.linspace(0, len(result)-1, num).round().astype(int)
    return [result[i] for i in indices]

x = np.linspace(0, 2*np.pi, 100)
y = np.sin(x)
colors = colorlist((1, 0, 0), (0, 0, 1), len(x))

for i in range(len(x)-1):
    xi = x[i:i+1+1]
    yi = y[i:i+1+1]
    ci = colors[i]
    plt.plot(xi, yi, color=ci, linestyle='solid', linewidth='10')

plt.show()

推荐答案

不确定更好的方法"指的是什么.代码更少、绘制速度更快的解决方案是将 LineCollection 与颜色图一起使用.

Not sure what "better way" refers to. A solution with less code, which would draw faster is the use of a LineCollection together with a colormap.

颜色图可以由两种颜色定义,中间的任何颜色都会自动插值.

A colormap can be defined by two colors and any colors in between are automatically interpolated.

cmap = matplotlib.colors.LinearSegmentedColormap.from_list("", [(1, 0, 0), (0, 0, 1)])

LineCollection 可用于一次绘制多条线.作为一个 ScalarMappable,它可以使用颜色图根据某个数组对每条线进行不同的着色 - 在这种情况下,人们可能只为此目的使用 x 值.

A LineCollection can be used to plot a lot of lines at once. Being a ScalarMappable it can use a colormap to colorize each line differently according to some array - in this case one may just use the x values for that purpose.

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection
from matplotlib.colors import LinearSegmentedColormap

x = np.linspace(0, 2*np.pi, 100)
y = np.sin(x)

cmap = LinearSegmentedColormap.from_list("", [(1, 0, 0), (0, 0, 1)])

points = np.array([x, y]).T.reshape(-1,1,2)
segments = np.concatenate([points[:-1],points[1:]], axis=1)

lc = LineCollection(segments, cmap=cmap, linewidth=10)
lc.set_array(x)
plt.gca().add_collection(lc)
plt.gca().autoscale()
plt.show()

如图所示,此解决方案的缺点是各个线路没有很好地连接.

The drawback of this solution as can be see in the picture is that the individual lines are not well connected.

所以为了规避这一点,我们可以绘制那些重叠的点,使用

So to circumvent this, one may plot those points overlapping, using

segments = np.concatenate([points[:-2],points[1:-1], points[2:]], axis=1)

在上面的颜色是线性插值在两个给定的颜色之间.因此,该图看起来与使用一些自定义插值的问题不同.


In the above the color is linearly interpolated between the two given colors. The plot therefore looks different than the one from the question using some custom interpolation.

要获得与问题中相同的颜色,您可以使用相同的函数为 LineCollection 创建颜色图中使用的颜色.如果目的是简化此函数,您可以直接将这些值计算为通道中色差的平方根.

To obtain the same colors as in the question, you may use the same function to create the colors used in the colormap for the LineCollection. If the aim is to simplify this function you may directly calculate the values as the square root of the color difference in the channels.

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection
from matplotlib.colors import LinearSegmentedColormap

x = np.linspace(0, 2*np.pi, 100)
y = np.sin(x)

def colorlist2(c1, c2, num):
    l = np.linspace(0,1,num)
    a = np.abs(np.array(c1)-np.array(c2))
    m = np.min([c1,c2], axis=0)
    s  = np.sign(np.array(c2)-np.array(c1)).astype(int)
    s[s==0] =1
    r = np.sqrt(np.c_[(l*a[0]+m[0])[::s[0]],(l*a[1]+m[1])[::s[1]],(l*a[2]+m[2])[::s[2]]])
    return r

cmap = LinearSegmentedColormap.from_list("", colorlist2((1, 0, 0), (0, 0, 1),100))

points = np.array([x, y]).T.reshape(-1,1,2)
segments = np.concatenate([points[:-2],points[1:-1], points[2:]], axis=1)

lc = LineCollection(segments, cmap=cmap, linewidth=10)
lc.set_array(x)
plt.gca().add_collection(lc)
plt.gca().autoscale()
plt.show()

这篇关于使用 matplotlib/pyplot 绘制混合线条颜色的曲线的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 20:59
查看更多