skimage编程笔记——整型和实型、RGB和Lab图像数组作为颜色空间转换函数的参数的注意事项

对于图像自动上色项目来说,将RGB图像转化为Lab图像的方法是必须掌握的。博主在实践过程中,在rgb2lab()lab2rgb()等函数上吃了很大亏,特此总结了一些注意事项。

本文涉及颜色空间转换函数和图像数据矩阵类型两方面的内容。

int型和float型的RGB图像数组作为颜色空间转换函数参数的区别


《Tensorflow:实战Google深度学习框架(第2版)》中有一句话:
大多数图像处理API支持整数和实数类型的输入。如果输入是整数类型,这些API会在内部将输入转化为实数后处理,再将输出转化为整数。如果有多个处理步骤,在整数和实数之间的反复转化将导致精度损失,因此推荐在图像处理前将其转化为实数类型。


编程中常见的一种警告:

/Library/Python/2.7/site-packages/skimage/util/dtype.py:141: UserWarning: Possible precision loss when converting from float64 to uint8
  .format(dtypeobj_in, dtypeobj_out))
/Library/Python/2.7/site-packages/skimage/util/dtype.py:141: UserWarning: Possible precision loss when converting from float64 to uint16
  .format(dtypeobj_in, dtypeobj_out))

Possible precision loss when converting from float to uint的意思是这意味着可能发生的精度损失。

总之,我们在使用图像处理API前,最好将图像数据转化为float型。

既然这样,我们就必须知道整型和实型图像数组的区别:


整型RGB图像数组元素值范围是0~255,实型RGB图像数组元素值范围是0~1;

Lab图像数组元素范围是:L的范围是0~100(代表亮度),a和b的范围均为-128~127(代表颜色),不管Lab图像数组是整型还是实型,范围都是这个。

另外再补充一点,skimage的颜色空间转换函数(比如rgb2lab()lab2rgb())的参数可以是整型或者实型,返回值都是实型。


注意到以上所讲的整型和实型的RGB图像数组范围不一致,这是我们需要注意的地方。下面进行整型和实型的RGB图像数组的使用对比:

现在我手头上有int型RGB图像数组rgb_image,要将图像转化为Lab格式只需下面一句:

lab_image = rgb2lab(rgb_image)

返回的lab_image数组是float型的。

和上述情况形成对比的是:为了照顾精度,要先将rgb_image转化为float型,再使用rgb2lab()将整型RGB图像数组转化为实型后,由于要符合实型RGB图像数组的数据范围,所以要除以255.0f

……	# "……"代表将rgb_image数组元素转化为float型的操作,由于仅做了数据类型转化,
	# 所以数据范围依旧是0~255
	
rgb_image = rgb_image / 255.0f		# 作用就是使图像数组数据范围符合实型RGB图像数组的要求。
									# 如果不加这一句,则得到的lab_image图像数组范围超出正常,
									# 且程序不会报错
lab_image = rgb2lab(rgb_image)

上述操作返回的lab_image也是float型数组,注意上述代码的/255.0f尤为重要,不然得到的lab_image数组元素数值范围会特别大。

既然整型和实型的RGB数组使用有区别,那么整型和实型的Lab图像数组有没有区别呢?

当然没有:
若我手头上有Lab图像数组,由于整型和实型的Lab图像数组范围一致,所以使用lab2rgb()时不需要改变数组元素值的范围:

rgb_image = lab2rgb(lab_image)	# 无论lab_image是整型还是实型,这一句都足够了

利用Tensorflow+skimage实现颜色空间转换

根据之前所讲,当我们给rgb2lab()传入一个实型数组时,需要检查这个数组的范围是否在0~1之间,如果你将整型RGB数组转化为实型RGB数组的操作仅仅是改变了数组元素的类型,而没有改变数值范围,则程序不会报错,但得到的Lab图像数组范围会很大。

tensorflow有个函数可以将整型RGB图像转化为实型RGB图像,转化的过程不仅改变数组元素的类型,还会自动将数值范围限制在0~1.

下面给出博主实践用的代码(注意每个代码片的缩进是同步的),结合代码理解:

import tensorflow as tf
from skimage.color import rgb2lab, lab2rgb

image_raw_data = tf.gfile.FastGFile("rgb_picture/2.jpg", 'r').read() # 读取一个RGB图像
with tf.Session() as sess:
    img_data = tf.image.decode_jpeg(image_raw_data)	# 此时img_data是整型图像数组的tensor
    print img_data.eval()

输出的是整型RGB图像数矩阵,范围在0~255:

[[[  1  94 215]
  [  0  93 214]
  [  0  93 214]
  ...
  [  0 105 223]
  [  0 105 223]
  [  0 105 223]]

 [[  1  94 215]
  [  0  93 214]
  [  0  93 214]
  ...

利用tensorflow的函数将图像转换为float型图像

    img_data = tf.image.convert_image_dtype(img_data, dtype=tf.float32)
    print img_data.eval()   # 输出的图片数据矩阵,数据范围都在0~1间。
    			# 加eval()是因为img_data是tensor,获取其值需要用eval()或者sess.run(),下同。

输出float型RGB图像数据矩阵,且数值范围自动限制在0~1间:

[[[0.00392157 0.36862746 0.8431373 ]
  [0.         0.3647059  0.83921576]
  [0.         0.3647059  0.83921576]
  ...
  [0.         0.41176474 0.8745099 ]
  [0.         0.41176474 0.8745099 ]
  [0.         0.41176474 0.8745099 ]]
 ...

然后将图像转化为Lab格式():

	img_data = rgb2lab(img_data.eval())
	print img_data      # 返回的lab图片数据矩阵是float型,但数据范围不在-1~1间

输出Lab图像数组如下,可以看到这个Lab图像数组虽为实型,但不像实型的RGB图像数组,它的数值范围和整型Lab图像数组是一致的:

[[[ 42.63580875  24.91225502 -68.08540347]
  [ 42.27894392  25.14236119 -68.09560274]
  [ 42.27894392  25.14236119 -68.09560274]
  ...
  [ 46.21493852  20.89131147 -66.81553317]
  [ 46.21493852  20.89131147 -66.81553317]
  [ 46.21493852  20.89131147 -66.81553317]]
  ...

然后将这个Lab作为别的图像颜色空间转换函数的参数,不需要修改它的数值范围,不像不符合要求的RGB图像矩阵要手动除以255以确保符合实型图像数据-1~1的范围要求。

    img_data = lab2rgb(img_data)	# 如果你多此一举地将作为Lab图像数组的img_data
    								# 的数值范围限制在-1~1间,程序会报错
    print img_data      # 返回的rgb图片数据矩阵是float型,数据范围在-1~1间

瞧瞧这返回的RGB图像矩阵,毫无疑问,范围又被限制回-1~1间:

[[[3.92156872e-03 3.68627461e-01 8.43137327e-01]
  [0.00000000e+00 3.64705893e-01 8.39215782e-01]
  [0.00000000e+00 3.64705893e-01 8.39215782e-01]
  ...
  [0.00000000e+00 4.11764747e-01 8.74509950e-01]
  [0.00000000e+00 4.11764747e-01 8.74509950e-01]
  [0.00000000e+00 4.11764747e-01 8.74509950e-01]]
  ...

小结:

(1)颜色空间转换函数的返回值均为float型,如果返回的是RGB图像矩阵,则其范围符合-1~1的范围要求
(2)颜色空间转换函数的参数可以是整型图像矩阵也可以是实型,如果参数是RGB图像数组,则传入实型数组时,要确保将数据范围限制在-1~1之间(方式是除以255),更确切讲其实是0~1间,因为RGB值不可能为负;如果传入的是Lab图像数组,不管数组元素是整型还是实型,都无需关心其范围,反倒是将数据限制在-1~1间会出错。

你可能感兴趣的:(机器学习编程足迹)