字数:2616,阅读量:662

几种常用图像数据类型

环境:

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 来渲染界面。

发表评论