使用matplotlib / pyplot混合线条颜色绘制曲线

问题描述 投票:1回答:1

我想用一种颜色开始曲线并逐渐融入另一种颜色直到结束。我的MCVE中的以下功能有效,但当然,必须有一个更好的方法,我还没有发现,但是?!

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()

1

python image matplotlib plot colors
1个回答
2
投票

不确定“更好的方式”是指什么。具有较少代码的解决方案可以更快地绘制,即使用LineCollection和色彩映射。

色图可以由两种颜色定义,其间的任何颜色都是自动插值的。

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

LineCollection可用于一次绘制许多行。作为ScalarMappable,它可以使用色彩图根据某些数组不同地着色每一行 - 在这种情况下,可以仅使用x值来实现该目的。

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()

enter image description here

从图中可以看出,该解决方案的缺点是各个线路连接不良。

因此,为了避免这种情况,可以使用以下方法绘制重叠点

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

enter image description here


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.

enter image description here

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

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()

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.