文章目录
- 1. 常用图片数据类型
- 2. 图片的显示
- 2.1 `plt.imshow()`
- 2.2 使用 turtle 来绘制图片
- 3.图片`ndarray`数据的常用切片操作
- 使用 cv2 来读取图片
- 打印数据
- R G B 通道的获取
- BGR 转成 RGB
- cv2 不支持中文路径的解决方法
- 4 `PIL.Image` 转成 `QImage` 或 `QPixmap`
1. 常用图片数据类型
-
使用
cv2.imread
返回的是一个
numpy.ndarray
类型, 同时 cv2.Mat 也是ndarray
的包装类 ,数据默认是 BGR 形式的img = cv2.imread('./image/test.png') # 100 x 78,32bpp print(type(img)) # <class 'numpy.ndarray'> print(img.shape) # (78, 100, 3) print(img) # cv2 的 image 是 BGR 格式 [[[ 90 108 68] ... BGR
-
PIL.Image
Image.open
返回了一个Image类, 具体数据可以 通过tobytes()
方法返回, 数据默认是RGBA形式img = Image.open("./image/test.png") print(img) # <PIL.PngImagePlugin.PngImageFile image mode=RGBA size=100x78 at 0x261D5255A90> print(img.width) print(img.height) print(img.mode)
同时 Image 类 兼容了
ndarray
, 也就是说 Image的数据可以直接转换成ndarray
类型img_data = np.array(img) # 这里面也是用 tobytes 来获取原始数据的 print(img_data) # [[[ 68 108 90 255] .... RGBA print(img_data.shape) # (78, 100, 4)
-
QImage
QImage
中存储的数据 从 bits() 获取, 为了方便, 统一转成 RGBA8888q_img = QImage() q_img.load("./image/test.png") w, h = q_img.width(), q_img.height() q_img.convertTo(QImage.Format.Format_RGBA8888) print(q_img.sizeInBytes()) dataPtr = q_img.bits() dataPtr.setsize(q_img.sizeInBytes()) img = Image.frombytes(mode='RGBA', data=dataPtr, size=(w, h)) # 转换成 PIL.Image 类型 img_array = np.array(dataPtr).reshape((h, w, 4)) # 转换成 ndarray 类型
2. 图片的显示
图片显示有很多方法, cv2.imshow, plt.imshow, QLabel.setPixmap
也能show, tkinter 的Label 也可以, 但最方便感觉还是使用plt
2.1 plt.imshow()
def imshow(
X: ArrayLike | PIL.Image.Image,
cmap: str | Colormap | None = None,
norm: str | Normalize | None = None,
....
) -> AxesImage:
# plt 可是直接显示 PIL.Image 以及 ndarray
使用方法也很简单
import numpy as np
from PIL import Image
from matplotlib import pyplot as plt
img = Image.open("./image/test.png")
print(img) # <PIL.PngImagePlugin.PngImageFile image mode=RGBA size=100x78 at 0x261D5255A90>
plt.imshow(img)
plt.show()
2.2 使用 turtle 来绘制图片
turtle 可以用来绘制图片
原理其实很简单, 获取像素数据,画笔设置像素颜色, 再直接落笔就🆗
import turtle as t
import cv2
print(t.colormode())
t.colormode(255)
img1 = cv2.imread('./image/test.png')[:, :, ::-1] # BGR 形式 转成 RGB 形式
height = img1.shape[0]
width = img1.shape[1]
t.setup(width=width * 2, height=height * 2)
print(t.pos())
t.pu()
t.goto(-width / 2, height / 2)
t.pd()
t.tracer(2000)
for k1, i in enumerate(img1):
for j in i:
t.pencolor((j[0], j[1], j[2]))
t.fd(1)
t.pu()
t.goto(-width / 2, height / 2 - k1 - 1)
t.pd()
t.done()
3.图片ndarray
数据的常用切片操作
为了讲解这一部分的知识,特地缩小了一张图片(test.png 100*28) 来讲解
使用 cv2 来读取图片
img = cv2.imread('./image/test.png') # 100 x 78,32bpp
打印数据
一张图片解码后的像素数据大概是这个样子的, 以BGR为例, 就是一个[h][w][3]
形状 3 维数据
二维的像素数组, 每个像素又是一个3列的列表分别表示BGR的颜色组成
print(img)
[
[ [ 90 108 68] [ 88 107 66] [ 80 98 57] ...]
[ [ 24 40 12] [ 24 40 12] [ 23 40 12] ...]
...
]
R G B 通道的获取
直接使用 ndarray
的切片 ,分别获取 R G B 的颜色分量
二维的像素数组, 每个像素只有一个颜色分量
# print(img[..., 0])
# print(img[:, :, 0]) # 第 1 个通道 [[ 90 88 80 ... 24 24 23] ...
# print(img[:, :, 1]) # 第 2 个通道 [[108 107 98 ... 40 40 40] ...
# print(img[:, :, 2]) # 第 3 个通道 [[ 68 66 57 ... 12 12 12]
BGR 转成 RGB
img_RGB = img[..., ::-1] # 还是切片
cv2 不支持中文路径的解决方法
cv 库 不支持图片文件名包含中文, 用 np.fromfile
读取数据,并重新解码数据来解决
img = cv2.imdecode(np.fromfile('./image/测试.png', dtype=np.uint8),
cv2.IMREAD_COLOR)
4 PIL.Image
转成 QImage
或 QPixmap
PIL.Image
有两个函数 可以分别转成 QImage
或 QPixmap
toqimage() -> ImageQt
toqpixmap()-> QPixmap