Tensorflow:如果是灰度图像,将其转换为RGB

4
我有一组rgb和灰度图像的数据集。在迭代整个数据集时,我想要检测图像是否是灰度图像,以便将其转换为rgb格式。我想使用tf.shape(image)来检测图像的维度。对于rgb图像,我得到类似于[1, 100, 100, 3]的结果。对于灰度图像,该函数返回例如[1, 100, 100]。我想使用len(tf.shape(image))来检测它的长度,如果长度为4,则表示rgb图像,长度为3则表示灰度图像。但这并不起作用。
以下是我的代码,但并未实现想要的效果:
def process_image(image):
    # Convert numpy array to tensor
    image = tf.convert_to_tensor(image, dtype=tf.uint8)
    # Take care of grayscale images
    dims = len(tf.shape(image))
    if dims == 3:
        image = np.expand_dims(image, axis=3)
        image = tf.image.grayscale_to_rgb(image)
    return image

有没有另一种方法将灰度图像转换为RGB?
2个回答

4

我有一个非常类似的问题,我想一次性加载RGB和灰度图像。Tensorflow支持在读入图像时设置通道数。因此,如果图像具有不同数量的通道,这可能是您要寻找的解决方案:

# to get greyscale:
tf.io.decode_image(raw_img, expand_animations = False, dtype=tf.float32, channels=1)

# to get rgb:
tf.io.decode_image(raw_img, expand_animations = False, dtype=tf.float32, channels=3)

-> 您甚至可以在同一张图像上执行这两个操作,并且可以在 tf.data.Dataset 映射内完成!

现在,您需要设置 channels 变量以匹配所需的形状,以便所有已加载的图像都具有该形状。然后,您可以无需条件地重塑。

这还允许您直接将灰度图像加载到Tensorflow中的RGB。以下是一个示例:

    >> a = Image.open(r"Path/to/rgb_img.JPG")
    >> np.array(a).shape
    (666, 1050, 3)
    >> a = a.convert('L')
    >> np.array(a).shape
    (666, 1050)
    >> b = np.array(a)
    >> im = Image.fromarray(b) 
    >> im.save(r"Path/to/now_it_is_greyscale.jpg")
    >> raw_img = tf.io.read_file(r"Path/to/now_it_is_greyscale.jpg")
    >> img = tf.io.decode_image(raw_img, dtype=tf.float32, channels=3)
    >> img.shape
    TensorShape([666, 1050, 3])
    >> img = tf.io.decode_image(raw_img, dtype=tf.float32, channels=1)
    >> img.shape
    TensorShape([666, 1050, 1])

如果您遇到 ValueError: 'images' contains no shape. 错误,请使用 expand_animations = False!请参见:https://dev59.com/LFcP5IYBdhLWcg3wDWRq#59944421


1
这是否意味着我可以使用 tf.io.decode_image(raw_img, expand_animations=False, dtype=tf.float32, channels=3) 直接将灰度图像加载到 RGB 图像中? - Gilfoyle
是的,它有效 :) 我会更新我的答案。 - LC117

4
你可以使用以下这个函数来完成此操作:
import tensorflow as tf

def process_image(image):
    image = tf.convert_to_tensor(image, dtype=tf.uint8)
    image_rgb =  tf.cond(tf.rank(image) < 4,
                         lambda: tf.image.grayscale_to_rgb(tf.expand_dims(image, -1)),
                         lambda: tf.identity(image))
    # Add shape information
    s = image.shape
    image_rgb.set_shape(s)
    if s.ndims is not None and s.ndims < 4:
        image_rgb.set_shape(s.concatenate(3))
    return image_rgb

在这种情况下,我需要使用 tf.identity() 函数吗? - Gilfoyle
1
@Samuel 我倾向于这样做,以使得我正在创建一个新的节点在图形中,这是条件操作的结果(取决于)。然而,我认为这并不是真正必要的(如果“image”是一个变量,并且更新被应用于它,那么可能会有所不同,但在大多数情况下我认为不需要)。 - jdehesa
我刚刚发现,如果我想调整process_image()返回的图像的大小,并使用您的代码,则会出现错误。当我在使用process_image(image)后使用image = tf.image.resize_images(image, size=[64,64])时,它会显示ValueError: 'images' contains no shape。为什么会这样? - Gilfoyle
1
@Samuel 对的,tf.cond 不会保留形状信息(不确定是从来没有还是在这种情况下)。我已经修改了函数,在可能的情况下恢复它。 - jdehesa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接