matplotlibt图像转OpenCV图像
1. 概述
有时候,我们需要使用Matplotlib库强大的绘图函数来在numpy.ndarray格式的图像上进行一些可视化,比如关键点绘制,投影点绘制。绘制完后,还需要把matplotlib的figure对象转换为numpy.ndarray 格式的对象,方便和原图进行比较。有时候为了可视化的美观,需要验证保证转换后的图像与原始图像大小一致。这里记录一下操作的流程,以及一些常遇到的问题。
2. 原理
核心原理是利用matplotlib.pyplot的imshow
函数来显示np.ndarray格式的图像,然后进行可视化绘制,再通过matplotlib.pyplot.figure.canvas的tostring_rgb
函数来将图像转换为string,在用numpy的fromstring
函数将string转换为np.ndarray,即为我们所求。
示例代码如下:
1 | import cv2 |
3. 几个关键点
上述代码是简单的原理,但要达到保存的vis_img
对象与img
对象完全等大小,还需要设置figure对象的size,具体实现是通过set_size_inches
函数,传入原始图像的宽和高除以dpi的值:
1 | fig = plt.figure() |
注意是宽在前面,高在后面。
还有一个很关键的点是需要去除matplotlib设置的padding白边,否则在相同尺寸的情况下,包含白边显得里面的内容变小了:
1 | plt.gca().set_position((0, 0, 1, 1)) |
为了不显示横纵坐标轴,需要添加plt.axis('off')
语句。
为了能在无GUI的环境(比如SSH连到的Linux 服务器)这个脚本也能正常工作,需要采用Agg
这个backend:
1 | import matplotlib |
插句题外话,Agg
这个backend原来是来自于Anti-Grain Geometry 2D渲染库,2002年开始开发,距今已有20年历史了,Respect。
此外由于matploltlib的imshow
需要RGB格式的图像,而OpenCV图像格式为BGR,需要做转换。
4. 完整代码
结合上一部分的几个关键点,最终的代码如下:
1 | import cv2 |
需要注意的是,直接执行这段代码虽然可以得到你想要的结果,但本身是没有意义的,最核心的matplotlib调用需要你自己填写。