本文介绍了使用Python / Matplotlib基于色彩映射绘制(极性)色轮的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在Python中创建一个色轮,最好使用Matplotlib。以下工程可以:

  import numpy as np 
import matplotlib as mpl
import matplotlib.pyplot as plt

xval = np.arange(0,2 * pi,0.01)
yval = np.ones_like(xval)

colormap = plt.get_cmap hsv')
norm = mpl.colors.Normalize(0.0,2 * np.pi)

ax = plt.subplot(1,1,1,polar = True)
ax.scatter(xval,yval,c = xval,s = 300,cmap = colormap,norm = norm,linewidths = 0)
ax.set_yticks([])


但是,这个尝试有两个严重的缺陷。



首先,将结果图保存为向量(



如果你想要一个戒指而不是一个轮子,在 plt.show() plt.savefig

  display_axes.set_rlim([ -  1,1])$ ​​b $ b  

这会提供








根据在评论中 - if您将图形保存为按照OP的SVG,这里是使用结果图形的提示:生成的SVG图像的小元素是触摸和不重叠的。这导致一些渲染器中的淡灰色线(Inkscape,Adobe Reader,可能不打印)。对此的简单解决方案是对每个单独的梯度元素应用小(例如120%)缩放,使用例如Inkscape或Illustrator。请注意,您必须单独将变换应用到每个元素(上述软件提供自动执行此功能的功能),而不是应用到整个绘图,否则不会生效。


I am trying to create a color wheel in Python, preferably using Matplotlib. The following works OK:

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt

xval = np.arange(0, 2*pi, 0.01)
yval = np.ones_like(xval)

colormap = plt.get_cmap('hsv')
norm = mpl.colors.Normalize(0.0, 2*np.pi)

ax = plt.subplot(1, 1, 1, polar=True)
ax.scatter(xval, yval, c=xval, s=300, cmap=colormap, norm=norm, linewidths=0)
ax.set_yticks([])

However, this attempt has two serious drawbacks.

First, when saving the resulting figure as a vector (figure_1.svg), the color wheel consists (as expected) of 621 different shapes, corresponding to the different (x,y) values being plotted. Although the result looks like a circle, it isn't really. I would greatly prefer to use an actual circle, defined by a few path points and Bezier curves between them, as in e.g. matplotlib.patches.Circle. This seems to me the 'proper' way of doing it, and the result would look nicer (no banding, better gradient, better anti-aliasing).

Second (relatedly), the final plotted markers (the last few before 2*pi) overlap the first few. It's very hard to see in the pixel rendering, but if you zoom in on the vector-based rendering you can clearly see the last disc overlap the first few.

I tried using different markers (. or |), but none of them go around the second issue.

Bottom line: can I draw a circle in Python/Matplotlib which is defined in the proper vector/Bezier curve way, and which has an edge color defined according to a colormap (or, failing that, an arbitrary color gradient)?

解决方案

One way I have found is to produce a colormap and then project it onto a polar axis. Here is a working example - it includes a nasty hack, though (clearly commented). I'm sure there's a way to either adjust limits or (harder) write your own Transform to get around it, but I haven't quite managed that yet. I thought the bounds on the call to Normalize would do that, but apparently not.

import matplotlib.pyplot as plt
import numpy as np
from matplotlib import cm
import matplotlib as mpl

fig = plt.figure()

display_axes = fig.add_axes([0.1,0.1,0.8,0.8], projection='polar')
display_axes._direction = 2*np.pi ## This is a nasty hack - using the hidden field to 
                                  ## multiply the values such that 1 become 2*pi
                                  ## this field is supposed to take values 1 or -1 only!!

norm = mpl.colors.Normalize(0.0, 2*np.pi)

# Plot the colorbar onto the polar axis
# note - use orientation horizontal so that the gradient goes around
# the wheel rather than centre out
quant_steps = 2056
cb = mpl.colorbar.ColorbarBase(display_axes, cmap=cm.get_cmap('hsv',quant_steps),
                                   norm=norm,
                                   orientation='horizontal')

# aesthetics - get rid of border and axis labels                                   
cb.outline.set_visible(False)                                 
display_axes.set_axis_off()
plt.show() # Replace with plt.savefig if you want to save a file

This produces

If you want a ring rather than a wheel, use this before plt.show() or plt.savefig

display_axes.set_rlim([-1,1])

This gives


As per @EelkeSpaak in comments - if you save the graphic as an SVG as per the OP, here is a tip for working with the resulting graphic: The little elements of the resulting SVG image are touching and non-overlapping. This leads to faint grey lines in some renderers (Inkscape, Adobe Reader, probably not in print). A simple solution to this is to apply a small (e.g. 120%) scaling to each of the individual gradient elements, using e.g. Inkscape or Illustrator. Note you'll have to apply the transform to each element separately (the mentioned software provides functionality to do this automatically), rather than to the whole drawing, otherwise it has no effect.

这篇关于使用Python / Matplotlib基于色彩映射绘制(极性)色轮的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-16 08:56