环境:
Ubuntu 20.04 x86_64
Python 3.9.10
OpenCV 4.5.5
python3 -m pip install opencv-python
PIL
sudo apt install python3-pil python3-pil.imagetk
tkinter
TensorFlow 2.7.0
Matplotlib
NumPy
分析
OpenCV 中图像的数据类型为 NumPy 数组,通道顺序为 BGR(只有 cv 是 BGR,其它全部都是 RGB)

PIL 是 Python 的图像库,tkinter 是 Python 的 GUI 库,其中 PIL 又有依赖于 tkinter。
而 PIL 的图像数据类型则是它自家的实现,大致是 PIL.Image 类下的。

如果要将 OpenCV 的图像类型转为 PIL 的,大致分为两部,第一步是修改通道顺序从 BGR 改为 RGB,第二步是进行数据转换。

tkinter 作为 GUI 库是用于构建用户界面的,而前面提到 tkinter 和 PIL 都是 Python 自家的,那么顺理成章的两者之间是存在交集的。
比如我要实现一个图片预览程序,那么读取图片数据这部分自然是用 PIL 来做(另外,根据上面我分析的,cv 可以转为 PIL 的数据类型,那么读取图片这部分也可以用 cv),然后由 tkinter 来显示图片界面。
下面是一个示例,演示效果的左图为 OpenCV 读取图片,右边为 PIL 读取图片。
""" 图片预览功能实现 Copyright (C) 2022 IYATT-yx iyatt@iyatt.com 每个人都可以复制和分发本许可证文档的逐字副本,但不允许更改。 这个程序是自由软件:你可以在自由软件基金会发布的GNU Affro通用公共许可证的条款下重新分发它和/或修改它, 或者许可证的第3版,或者(在你的选择)任何其他版本。 本程序的发布目的是希望它有用,但不提供任何担保;甚至没有对适销性或特定用途适用性的默示保证。 有关更多详细信息,请参阅GNU Affero通用公共许可证。 您应该已经收到GNU Affero通用公共许可证的副本以及本程序。如果没有,请参阅<https://www.gnu.org/licenses/>. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>. """ import cv2 from PIL import ImageTk, Image import tkinter as tk # 图片路径 img_path = 'demo.jpg' class Application(tk.Frame): def __init__(self, master): super().__init__(master) self._master = master def draw_interface(self): # 特别注意!!! tkinter 要显示的图片数据应该为全局 # 不这样做会发生什么,可以注释下一行就知道了 global pil_img1, pil_img2 global img_path try: # OpenCV 读取图片 cv_bgr_img = cv2.imread(img_path, cv2.IMREAD_COLOR) if cv_bgr_img is None: raise FileNotFoundError cv_rgb_img = cv2.cvtColor(cv_bgr_img, cv2.COLOR_BGR2RGB) pil_img1 = ImageTk.PhotoImage(Image.fromarray(cv_rgb_img)) # PIL 读取图片 pil_img2 = ImageTk.PhotoImage(Image.open(img_path)) except FileNotFoundError: print('{} 图片不存在或者无法读取!'.format(img_path)) exit() tk.Label(self._master,image=pil_img1).grid(column=0, row=0) tk.Label(self._master, image=pil_img2).grid(column=1, row=0) if __name__ == '__main__': root = tk.Tk() root.title('图片预览器') app = Application(root) app.draw_interface() root.mainloop()

OpenCV -> PIL 可以了,那么反过来,PIL 的图片数据如何转为 OpenCV (BGR 顺序的 NumPy)呢?下面就是一个程序示例,由 PIL 读取图片,用 OpenCV 来显示。

Matplotlib 的图片数据类型和 OpenCV 一样,都是 NumPy 数组,只是MatplotLib 的图片通道是 RGB,就只有 OpenCV 最拽,独特的 BGR 反序。因为相似,也就不过多谈论了。

Tensorflow 读取图片后的数据类型也是它自家的,但是可以通过一定方式转为 NumPy 数组(通道顺序为 RGB),见下图示例,最终使用 Matplotlib 来渲染界面。
