【openCV中的BGR和RGB】img[:,:,::

您所在的位置:网站首页 相册img是什么意思 【openCV中的BGR和RGB】img[:,:,::

【openCV中的BGR和RGB】img[:,:,::

2024-05-30 13:49| 来源: 网络整理| 查看: 265

以下放在开头,备忘:

img = Image.open(ImgPath) 打开的图片是PIL类型,默认RGB。 将PIL类型转化为numpy类型:im = numpy.array(img) 才能看到shape属性,是(height, width, channel)数组,channel的通道数据是RGB。cv2.imread(path, 读取方式): path: 图片的路径; 读取方式: cv2.IMREAD_COLOR:读入一副彩色图片;cv2.IMREAD_GRAYSCALE:以灰度模式读入图片;cv2.IMREAD_UNCHANGED:读入一幅图片,并包括其alpha通道。 默认为cv2.IMREAD_COLOR。 返回值是(height,width,channel)数组,channel的顺序是BGR顺序两者之间的相互转换 PIL Image转化为OpenCV格式: img = Image.open() img = cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR) OpenCV转化为PIL Image格式: img = cv2.imread() img2 = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))plt.imshow()和cv2.imshow() 这个显示是和读取对着的,也就是说要想可视化出来正常的RGB格式,给plt.imshow()的应该是rgb格式的图片,给cv2.imshow()的应该是bgr格式的图片。多说一些plt.imshow(),因为我平时几乎不用cv2.imshow()。在plt.imshow()中,接受的图片类型可以是np.ndarray,tensor, PIL Image这些任意的类型。

在SSD和YOLO的源码中,使用opencv读取图片,其处理图片时都有以下图片通道转换的代码,做以下记录:

以https://github.com/ultralytics/yolov3中的一部分为例:

img0 = cv2.imread(path) # BGR # Padded resize img = letterbox(img0, self.img_size, stride=self.stride)[0] # Convert img = img[:, :, ::-1].transpose(2, 0, 1) # BGR to RGB, to 3x416x416 img = np.ascontiguousarray(img)

其中的Padded resize不用管,是YOLO对输入图片按Padded方式进行Resize。 我们要分析的是img = img[:, :, ::-1].transpose(2, 0, 1)这句代码 先放结论:

img[:,:,::-1] 这句的作用,是说:图像张量有三个维度,分别表示宽度、长度和颜色通道。既然image[:,:,::-1]的作用是对颜色通道把RGB转换成BGR。

怎么转换的呢?

1. img[:,:,::-1]作用

对于列表img进行img[:,:,::-1]的作用是列表数组左右翻转,例如:

import numpy as np a = np.arange(27).reshape(3,3,3) print(a) ''' [[[ 0 1 2] [ 3 4 5] [ 6 7 8]] [[ 9 10 11] [12 13 14] [15 16 17]] [[18 19 20] [21 22 23] [24 25 26]]] ''' b = a[:,:,::-1] print(b) ''' [[[ 2 1 0] [ 5 4 3] [ 8 7 6]] [[11 10 9] [14 13 12] [17 16 15]] [[20 19 18] [23 22 21] [26 25 24]]] '''

可以明确看出,[:,:,::-1]的作用就是对数组进行左右翻转。那为什么对于图像而言却能实现RGB通道转换为BGR通道呢?先看一些读取图片的方法是怎么读取吧

一般有opencv(cv2)和matplotlib(plt)的读取方式:(cv2把图片读取后是把图片读成BGR形式的,plt则是读成RGB形式)

证明如下:

以一张图片为样例:

正常显示就是以RGB为格式显示的。当我们用plt读取时:

from matplotlib import pyplot as plt import cv2 img_name = r'C:\Users\Administrator\Desktop\airball\val\35.jpg' img = plt.imread(img_name) print(img)

打印出来的是:

取第一个值,(129,80,73),在网上以查,颜色是深棕色的,确实跟图片的左上角是一致的:

证明plt读取图片的方式确实是以RGB的格式读取。

接着:

当执行 [:,:,::-1]后,数组会左右翻折:

from matplotlib import pyplot as plt import cv2 img_name = r'C:\Users\Administrator\Desktop\airball\val\35.jpg' img = plt.imread(img_name) print(img) print('-----------------------') img = img[:, :, ::-1] print(img)

可以看到(129 80 73)变成(73 80 129)。

通过网上查询(73 80 129)是什么颜色的,发现是蓝色的。

所以,如果拆测没错的话,这是后显示出来的图片应该左上角就是蓝色的,我们试试:

from matplotlib import pyplot as plt import cv2 img_name = r'C:\Users\Administrator\Desktop\airball\val\35.jpg' img = plt.imread(img_name) print(img) print('-----------------------') img = img[:, :, ::-1] plt.imshow(img) plt.show()

果然左上角就是蓝色的。因此,这应该是BRG格式的图片了。所以得证,[:,:,::-1]的作用就是把RGB(或BRG)转换成BGR(或者RGB)。

=============================

插一句题外话,用opencv(即cv2)读取图片,是以BGR的形式来读取的。我们用cv2的imshow()函数显示图片发现跟我们打开图片的样子一样,是因为cv2的imshow()又把BGR转回RGB再显示。但cv2确实是以BGR形式读取图片的,而plt则是以RGB形式。

2. img[:, :, (2, 1, 0)]

代码中有时也会有img[:, :, (2, 1, 0)]这种操作,这个的意义也是通道的转换。其实都是因为opencv中imread读取出来的图片是BGR格式,也就是说下列三组代码是完全等价的,操作的结果都是将imread读取的BGR格式的图片转换为RGB格式

#第一组 image = cv2.imread(path) image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # 转化为RGB #第二组 image = cv2.imread(path) image = image[:, :, (2, 1, 0)] #第三组 image = cv2.imread(path) image = image[:,:,::-1]

回到最初的问题,img = img[:, :, ::-1].transpose(2, 0, 1)这句代码,transpose(2,0,1)有什么用,一句话总结:

这时的image是H,W,C的顺序,因此需要转化为C, H, W,维度变换正好2,0,1 变换维度的目的仅仅是为了方便计算。

常见如下代码

image = torch.from_numpy(image).permute(2, 0, 1) 3. PIL读取

PIL读取很正常,没什么操作,通常也不进行转换

image = Image.open(os.path.join(self.image_path, image_name)) # 读取到的是RGB, C, H, W

参考:

图像领域img[:,:,::-1]的理解

pytorch:读取图像的两种方法



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3