opencv, Image 模块在单通道与三通道互相转换上的疑问与解答

opencv, Image 模块在单通道与三通道互相转换上的疑问与解答

一、前言

最近项目处理图片比较多,有时忘记改默认值,使得API将灰度图读成了三通道图,事后虽然改了过来,但很好奇二者后期转化的结果与原始读入的区别。本着动手多折腾的想法,抽个时间好好试验了一下,结果如下。

二、试验

1.opencv 模块

凡事先上代码,再谈结果,代码如下:

src_1 = cv2.imread(r"F:\demo\MS_DMS\add\0_\2.jpg", 0) # 正确读入单通道的方式
src_3 = cv2.imread(r"F:\demo\MS_DMS\add\0_\2.jpg") # 以三通道的方式读入
print(src_1)
gray = cv2.cvtColor(src_3, cv2.COLOR_BGR2GRAY) # 再将后者由三通道转换为单通道
list_ = ((gray == src_1).astype("int8")).tolist() # 转为列表,方便计算比对结果中 0(False) 的个数
print(list_.count(0))

结果为

src_1 = 
[[148 149 150 ... 154 154 154]
 [148 149 150 ... 154 154 154]
 [148 150 151 ... 154 154 154]
 ...
 [154 146 132 ... 213 195 154]
 [144 135 130 ... 172 207 169]
 [134 123 118 ... 210 180 199]]
 
list_.count(0) = 0 # 说明两个数组相等

由上可以看出,原始读入灰度图 与 先按三通道图读入,后面再转换为单通道图的方式相比,二者结果是相等的。再看看,单通道变为三通道是怎么变化的。

src_1 =  [[148 149 150 ... 154 154 154]
 [148 149 150 ... 154 154 154]
 [148 150 151 ... 154 154 154]
 ...
 [154 146 132 ... 213 195 154]
 [144 135 130 ... 172 207 169]
 [134 123 118 ... 210 180 199]]

src_3 =  [[[148 148 148]
  [149 149 149]
  [150 150 150]
  ...
  [154 154 154]
  [154 154 154]
  [154 154 154]]

 [[148 148 148]
  [149 149 149]
  [150 150 150]
  ...
  [154 154 154]
  [154 154 154]
  [154 154 154]]

 [[148 148 148]
  [150 150 150]
  [151 151 151]
  ...
  [154 154 154]
  [154 154 154]
  [154 154 154]]

 ...

 [[154 154 154]
  [146 146 146]
  [132 132 132]
  ...
  [213 213 213]
  [195 195 195]
  [154 154 154]]

 [[144 144 144]
  [135 135 135]
  [130 130 130]
  ...
  [172 172 172]
  [207 207 207]
  [169 169 169]]

 [[134 134 134]
  [123 123 123]
  [118 118 118]
  ...
  [210 210 210]
  [180 180 180]
  [199 199 199]]]

src_3[0:1, 0:1, :] = [[[148 148 148]]] # 打印了三通道图的第一个像素点的数值看了一下

比较长,大致看下就行,程序就是将单通道的数据单纯的复制了一下,使得其他2个通道的数据与另一个一样,这个从我特意打印的第一个像素点的数值可以看出来。像我们在pytorch中,数组形状是 (C, H, W),那样是个什么样子呢?

# 特意将数组形状转换了一下,数值表现如下:
src_3_ =  [[[148 148 148 ... 152 152 152]
  [152 152 149 ... 151 152 152]
  [152 152 152 ... 154 154 154]
  ...
  [157 157 157 ... 157 157 157]
  [150 150 150 ... 172 172 191]
  [191 191 208 ... 151 158 158]]

 [[158 161 161 ... 155 155 155]
  [150 150 150 ... 203 203 213]
  [213 213 173 ... 144 158 158]
  ...
  [ 96  96  68 ... 134 151 151]
  [151 129 129 ... 163 163 163]
  [142 142 142 ...  84  84  74]]

 [[ 74  74  94 ... 122 115 115]
  [115  95  95 ... 164 164 164]
  [140 140 140 ... 110 110 116]
  ...
  [134 134 134 ... 163 163 163]
  [163 163 163 ... 165 166 166]
  [166 166 166 ... 199 199 199]]]
  
src_3_.shape =  (3, 74, 76)

2.Image 模块

ptyorch里这个模块用的比较多,所以也试验了一下。

src = Image.open(r"F:\demo\MS_DMS\add\0_\2.jpg")
print(np.array(src))

结果为:

[[[148 148 148]
  [149 149 149]
  [150 150 150]
  ...
  [154 154 154]
  [154 154 154]
  [154 154 154]]

 [[148 148 148]
  [149 149 149]
  [150 150 150]
  ...
  [154 154 154]
  [154 154 154]
  [154 154 154]]

 [[148 148 148]
  [150 150 150]
  [151 151 151]
  ...
  [154 154 154]
  [154 154 154]
  [154 154 154]]

 ...

 [[154 154 154]
  [146 146 146]
  [132 132 132]
  ...
  [213 213 213]
  [195 195 195]
  [154 154 154]]

 [[144 144 144]
  [135 135 135]
  [130 130 130]
  ...
  [172 172 172]
  [207 207 207]
  [169 169 169]]

 [[134 134 134]
  [123 123 123]
  [118 118 118]
  ...
  [210 210 210]
  [180 180 180]
  [199 199 199]]]

Image的 open函数并没有按灰度图读取的设置(看了该函数的文档也没有什么发现),只有后期再将其转换为单通道图,所以pytorch读取单通道图时一般还要再转换一下。回到结果上面,这与opencv的结果是一致的,不信可以做个对比。

src2 = cv2.imread(r"F:\demo\MS_DMS\add\0_\2.jpg")
src = Image.open(r"F:\demo\MS_DMS\add\0_\2.jpg")
print(((src2 == np.array(src).astype("int8")).tolist()).count(0))

结果为 0 ,说明以不同API读取的两个数组结果是一样的。

此外,Image将单通道转为三通道也是直接将一个通道上的数据再复制两份,所以三个通道数据一样。
下面试试单通道结果。

src2 = cv2.imread(r"F:\demo\MS_DMS\add\0_\2.jpg", 0) # opencv按单通道读取图片
src = Image.open(r"F:\demo\MS_DMS\add\0_\2.jpg").convert("L") # Image将三通道转为单通道
print("src = ",np.array(src))
print(((src2 == np.array(src).astype("int8")).tolist()).count(0)) # 比对二者是否一样

结果为:

src =  [[148 149 150 ... 154 154 154]
 [148 149 150 ... 154 154 154]
 [148 150 151 ... 154 154 154]
 ...
 [154 146 132 ... 213 195 154]
 [144 135 130 ... 172 207 169]
 [134 123 118 ... 210 180 199]]
 
((src2 == np.array(src).astype("int8")).tolist()).count(0) =  0    # 为 0 表示上面两个数组是相等的

三、总结

经过这次试验,终于一解我心中疑惑,总结一下:
① opencv 按 单通道读取图片的结果 与 先按三通道读取图片再转为单通道的结果,二者一致的;
② Image 只能按三通道读取图片,其读取的三通道的结果与 opencv 的方式一致。转换为 单通道后,其结果也与 opencv 一致。
可能后面还有其他疑惑,再慢慢试验吧。舒服~~

opencv, Image 模块在单通道与三通道互相转换上的疑问与解答opencv, Image 模块在单通道与三通道互相转换上的疑问与解答 tang-shopping 发布了11 篇原创文章 · 获赞 1 · 访问量 1058 私信 关注
上一篇:洛谷——P2393 yyy loves Maths II


下一篇:AcWing 154. 滑动窗口(模板)