推荐可以看看这个:
1.IDE里的
1.1 显示模式(plt.ion()和plt.ioff())
很有用的一点:
无论使用的是什么交互模式,都可以使用pyplot.show(block=True)
来让图变成responsive的
来自chatGPT的回答:
“Responsive” 通常翻译为 “响应式的” 或者 “自适应的”。在计算机编程中, “响应式” 或 “自适应” 通常指程序可以根据不同设备屏幕大小或用户界面的变化自动进行调整,并且能够通过对用户输入和交互方式做出合理的回应。例如,网页设计中经常用到响应式布局,以使得页面在不同尺寸的屏幕上都能够展示得很好。
可以借用plt.ion()
和plt.ioff()
来绘制一些动态效果,这两句英语很好的说明了这个显示模式:
If you wish to disable automatic redrawing of the plot:
plt.ioff()
If you wish to re-enable automatic redrawing of the plot:
plt.ion()
- 一般很难看到动态效果是因为处理速度太快,在不同的(
plt.figure()
之间加一些plt.pause(0.5)
这样的中断语句,就可以比较显著的看到变化了 - 另外,这个东西使用比较少,目前可以想到的场景,先显示一条线,处理之后又显示一条线,分时显示在同一个图上。
参考:
- matplotlib.org-Interactive figures,这里也有关于IDE里交互式窗口的介绍
- matplotlib.pyplot.ion
- Python中使用plt.ion()和plt.ioff()画动态图
- 绘制五角星
1.2 backend说明
如果涉及到多种操作系统,比如macOS和Windows,可能要关注一下这个参数。
# 查看自己当前matplotlib的默认backend
import matplotlib as mpl
rc = mpl.rcParams
print(rc['backend'])
> MacOSX
# 如果想临时更换(代码只能改运行时),可以
import matplotlib
matplotlib.use("MacOSX")
关于mpl.rcParams
,详见3.4 matplotlib利用rcParams配置样式参数
matplotlib已经支持的内建的backend有以下,详见The builtin backends
2. jupyter里的(主要是和iwidgets组件结合交互式)
TBD,需要进一步整理
之前总结过,可以看:
- jupyter交互式查看图像
- anaconda、pip及jupyter常见使用中 3.7和3.8部分
3 通用的
3.0 根据颜色名称获取对应rgb值(0~255)
from matplotlib import colors
# print(colors.to_rgb("tab:blue"))
for colorName in ["tab:blue", "tab:red","tab:green","white","black","white"]:
color_rgb = [int(c*255) for c in colors.to_rgb(colorName)]
print(color_rgb)
>[31, 119, 180]
[214, 39, 40]
[44, 160, 44]
[255, 255, 255]
[0, 0, 0]
[255, 255, 255]
参考:
- stackoverflow:Convert matplotlib color value to RGB
- https://matplotlib.org/2.0.2/api/colors_api.html
- https://matplotlib.org/stable/tutorials/colors/colors.html
- stackoverflow:Python from color name to RGB
3.1 cmap
其实基本用不到自定义cmap的功能,最多就是plt.show(XXX,'gray')
,可能会想换个色谱。。目前没有找到很好的可以用程序就找到相应色谱的办法,还是看下面的参考链接吧:Choosing Colormaps in Matplotlib或者Colormap reference
3.1.1 cmap绘制CMYK四个通道
我遇到了一个比较简单的需求,cmap显示CMYK配色,现有自带的cmap无法满足我的需求,因此自定义了一下,如下:
channels = ('c', 'm', 'y', 'k')
# 不那么好的cmap显示,使用默认近似的cmap达不到想要的效果
plt.figure("wrong CMYK")
for i, channel, colormap in zip(range(4), channels, ('Greens', 'RdPu', 'YlOrBr', 'gray')):
plt.subplot(2, 2, i+1)
plt.title(channel+" channel")
plt.imshow(np.asarray(CMYK[:,:,i]), cmap=colormap)
# 正确的CMYK显示
plt.figure("right CMYK")
cyan_cmap = ListedColormap(["black", "cyan"])
magenta_cmap = ListedColormap(["black", "magenta"])
yellow_cmap=ListedColormap(["black", "yellow"])
plt.subplot(2, 2, 1)
plt.title("cyan")
plt.imshow(np.asarray(CMYK[:,:,0]), cmap=cyan_cmap)
plt.subplot(2, 2, 2)
plt.title("magenta")
plt.imshow(np.asarray(CMYK[:,:,1]), cmap=magenta_cmap)
plt.subplot(2, 2, 3)
plt.title("yellow")
plt.imshow(np.asarray(CMYK[:,:,2]), cmap=yellow_cmap)
plt.subplot(2, 2, 4)
plt.title("black")
plt.imshow(np.asarray(CMYK[:,:,3]), cmap="gray")
原图是这样:
呈现效果如下:
IDE的这个显示框可以进行ZOOM,
主要参考:
- ✅matplotlib-Creating listed colormaps
- ✅matplotlibList of named colors
- Creating a colormap from a list of colors
3.1.2 cmap绘制mask
主要是使用matplotlib.colors.ListedColormap
这个函数
import matplotlib
# 设置了一个西瓜的cmap
watermalon_cmap = matplotlib.colors.ListedColormap(["tab:blue", "tab:red","tab:green","white","black","white"],N=6)
# mask中值为0的地方是`tab:blue`背景色
# mask中值为1的地方是`tab:red`红色,....
plt.subplot(1,2,1)
plt.imshow(img[:,:,::-1])
plt.subplot(1,2,2)
# 只显示单通道,同时值的范围不是0-255,没有normalize,只有0和5
plt.imshow(mask[:,:,0],cmap=watermalon_cmap)
"""函数说明
matplotlib.colors.ListedColormap(colors,N)
-colors:list, array
颜色列表,字符表示的颜色,或者是RGB/RGBA三元组/四元组表示的颜色
"""
参考:
- ✅https://matplotlib.org/stable/tutorials/colors/colorbar_only.html
- https://matplotlib.org/stable/api/_as_gen/matplotlib.colors.ListedColormap.html#matplotlib.colors.ListedColormap
- https://matplotlib.org/stable/tutorials/colors/colormap-manipulation.html#creating-listed-colormaps
- https://matplotlib.org/stable/gallery/color/named_colors.html
3.2 subplot()相关
例如:
# Initialize the grid
grid = plt.GridSpec(2, 3, wspace=0.4, hspace=0.3)
# make subplots
plt.subplot(grid[0, 0])
plt.subplot(grid[0, 1:])
plt.subplot(grid[1, :2])
plt.subplot(grid[1, 2]);
我实际使用的例子:
olors=("b","g","r") #opencv的默认三通道顺序
plt.figure("histograms")
grid = plt.GridSpec(2, 3, wspace=0.4, hspace=0.3)
plt.subplot(grid[0, 0:])
plt.title("src Image")
plt.imshow(srcImg[:, :, [2, 1, 0]])
for i,color in enumerate(colors):
hist = cv2.calcHist([srcImg],[i],None,[256],[0,255])
plt.subplot(grid[1, i])
plt.title(color+" channel")
plt.plot(hist,color)
plt.xlim([0,256])
plt.show(block=True)
参考:
- https://www.machinelearningplus.com/plots/subplots-python-matplotlib/
- 使用 GridSpec 自定义子图位置
- Using Gridspec to make multi-column/row subplot layouts
3.3 绘制动态图(Animation类)
参考:
- 3.6. softmax回归的从零开始实现中
class Animator:
- stackoverflow:How to animate a scatter plot
- matplotlib-Animated scatter saved as GIF
3.4 matplotlib利用rcParams配置样式参数
参考:Customizing Matplotlib with style sheets and rcParams
在程序中利用rcParams进行样式修改,只能是运行时生效。如果想永久生效的话,需要去修改matplotlibrc
文件
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
from cycler import cycler
mpl.rcParams['lines.linewidth'] = 2
mpl.rcParams['lines.linestyle'] = '--'
data = np.random.randn(50)
plt.plot(data)
关于mpl.rcParams
支持的参数,可以
import matplotlib
doc(matplotlib.RcParams)
- 程序里直接打印配置项和对应当前的默认值:
import matplotlib as mpl
rc = mpl.rcParams
for key,value in rc.items():
print(key,value)
# 会有很多项
> .....
axes.prop_cycle cycler('color', ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd', '#8c564b', '#e377c2', '#7f7f7f', '#bcbd22', '#17becf'])
axes.spines.bottom True
axes.spines.left True
axes.spines.right True
axes.spines.top True
....
- 直接去看
matplotlibrc
文件,或者可以看看网页上默认的matplotlibrc,如果想查看本地的,可以使用以下代码获取改文件在系统里的位置
import matplotlib
matplotlib.matplotlib_fname()
> /Users/yourname/Documents/software/miniconda3/miniconda3/envs/py37/lib/python3.7/site-packages/matplotlib/mpl-data/matplotlibrc
3.5 显示中文
之前写过一篇,在这里,macos或windows中 matplotlib中文显示(matplotlib字体常见使用)
3.6 plt.plot()参数详解
想画花里胡哨的图的话,这个函数的参数要懂一些。重点就是3个:线型,marker的标记形状和颜色,最多再来一个size,其他属性不太常见,有需要自己看。
下面是随机搭配生成的线,注明了使用的marker、线型和颜色,注意:markder不全都是字符串,有数字格式,标注为num_
主要参考:
- matplotlib.pyplot.plot,其实重点是matplotlib.lines.Line2D这个类里的属性。
- 属性marker:
- set_marker,从描述中知道,这个也支持自己上传自定义的marker路径
- matplotlib.markers,markers的完整图示,数的没错的话,是39种marker(包括none在内)
- 属性linestyle:
- set_linestyle,基础线型配上线基本单位之间的offset等,可以构建不同的线型,但是一般都会直接选择默认的。
- Linestyles,默认的4种(包含none就是5种)+一些调整了线基本单位之间offset的自定义线型,一共19种线型示例。
- 属性colors:
- matplotlib.colors
- CSS Colors,可视化的颜色和对应名称
- 属性text: matplotlib.pyplot.text
- 属性legend:matplotlib.pyplot.legend
如果想要让线和marker颜色不一样,可以使用color
来指定线的颜色,使用mfc='red', mec='k'
来指定marker的markerfacecolor
(marker的前景色,也可以使用mfc
简写代替)和markeredgecolor
(marker的边颜色,也可以使用mec
简写代替),例如:
plt.plot([0, 50, 180, 256], [0, 30, 120, 256], "D-b", mfc='red', mec='k')
显示如下:
主要参考:
- matplotlib.org-matplotlib.pyplot.plot,在这个页面搜索
color
就可以看到了 - stackoverflow.com-Make Line plot markers of different color
3.7 移除坐标轴0左侧的空白
参考:How can I get rid of the white space in matplotlib?
只需要使用:
plt.margins(x=0)
# 或者
ax.margins(x=0)
就可以了,如下图,完全去除边界带来的问题就是原点处的点的marker,显示不全,但是会更符合常规认知的坐标系
3.8 matplotlib.collections.PatchCollection使用
写在另一个文章里了:matplotlib——2. 形状和路径(Shape and Collection)底纹(hatch)
这个东西有一点点冷门,但是看起来很酷,同时在绘制形状比较复杂的mask的时候很常用!
3.9 绘制原点居中的坐标系(笛卡尔坐标系)
import matplotlib.pyplot as plt
import matplotlib as mpl
import numpy as np
x = np.linspace(-np.pi, np.pi, 100)
y = 2*np.sin(x)
fig,ax=plt.subplots()
ax.spines[['left', 'bottom']].set_position('center')
ax.spines[['top', 'right']].set_visible(False)
ax.plot(x,y)
但是如果x或者y本身取值不对称,则这个坐标轴显示也不会对称,有点鸡肋。
import matplotlib.pyplot as plt
import matplotlib as mpl
import numpy as np
x = np.linspace(0, 2*np.pi, 100)
y = 2 * np.sin(x)
fig,ax=plt.subplots()
ax.spines[['left', 'bottom']].set_position('center')
ax.spines[['top', 'right']].set_visible(False)
ax.plot(x,y)
参考:
- https://matplotlib.org/stable/gallery/spines/spine_placement_demo.html
- https://matplotlib.org/2.0.2/examples/pylab_examples/spine_placement_demo.html
- https://stackoverflow.com/questions/4694478/center-origin-in-matplotlib
4. 与opencv连用
可能遭遇的问题
1. IDE不显示图像窗口
现象描述
代码类似下面这样:
zipImg = cv2.imread(zipImgPath)
plt.ion()
plt.figure()
plt.imshow(zipImg[:, :, [2, 1, 0]])
但是运行后没有出现图像窗口。
可能的原因及解决方案,参考:Matplotlib plots not showing up in Mac OSX?
- backend问题,后端可以理解为渲染图像的引擎,对于macos电脑来说,可能是因为backend设置不对造成的,这部分介绍,详见上面1.1.2 backend说明
- 窗口其实显示了,只是一闪而过了,可以在
plt.imshow()
代码的后面添加plt.pause(20)
或者time.sleep(20)
来暂停程序执行一段时间,这样就可以看见窗口了。