如何使用 Tensorflow 创建包含所有图像的一小部分的数据集

问题描述 投票:0回答:1

我在一个文件夹中有 99,000 张图片,但我的数据集只需要 10000 张。我试过先随机选择图像,然后创建数据集,但它似乎不起作用。为此,我需要使用 Tensorlfow。

这个问题困扰我一个多星期了。如果有人有另一种方法来创建一个数据集,只包含与我完全不同的图像总数的一小部分,那对我来说没问题。

谢谢!

现在我正在尝试使以下代码工作:

import tensorflow as tf
import numpy as np
import os

# Define the directory where your images are located
data_dir = '/home/clau/Escritorio/cropped/'

# Load the list of image filenames
filenames = tf.constant(os.listdir(data_dir))
num_images = len(filenames)

# Shuffle the filenames
filenames = tf.random.shuffle(filenames)

# Select the first 12000 filenames
filenames = filenames[:10000]


# Define a function to load and preprocess each image
def load_and_preprocess_image(filename):
    # Convert the filename tensor to a string
    filename = filename.numpy().decode('utf-8')

    # Load the image file
    file_path = os.path.join(data_dir, filename)
    img = tf.io.read_file(file_path)

    # Decode the image and convert to floating-point tensor
    img = tf.image.decode_jpeg(img, channels=3)
    img = tf.image.convert_image_dtype(img, tf.float32)

    # Resize the image to 256x256
    img = tf.image.resize(img, [256, 256])

    # Normalize the pixel values to the range [0,1]
    img = img / 255.0

    return img

# Create an empty dataset
dataset = tf.data.Dataset.from_tensor_slices(tf.constant([], dtype=tf.string))

for imgfile in filenames:
    processed_img = load_and_preprocess_image(imgfile)
    
    # Add the image
    dataset = dataset.concatenate(tf.data.Dataset.from_tensor_slices(processed_img))


它给了我以下错误:

TypeError:不兼容的数据集元素: TensorSpec(shape=(), dtype=tf.string, name=None) 与 TensorSpec(shape=(256, 3), dtype=tf.float32, name=None)

tensorflow image-processing dataset artificial-intelligence tensorflow-datasets
1个回答
0
投票

您可以使用所需的特定数量的图像创建 Tensorflow 记录,并在训练模型之前解析它们。

这里是创建 TF 记录文件并将其解析为您的模型的示例代码。我假设图像文件名是您的标签,它们是整数,因为从您的代码中不清楚您使用的是什么标签。

import tensorflow as tf
import numpy as np
import random
import os

def image_feature(value):
    """
    Returns a bytes_list from a string / byte.
    """

    return tf.train.Feature(
        bytes_list=tf.train.BytesList(value=[tf.io.encode_jpeg(value).numpy()])
    )


def bytes_feature(value):
    """Returns a bytes_list from a string / byte."""
    return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))


def float_feature(value):
    """Returns a float_list from a float / double."""
    return tf.train.Feature(float_list=tf.train.FloatList(value=[value]))


def int64_feature(value):
    """Returns an int64_list from a bool / enum / int / uint."""
    return tf.train.Feature(int64_list=tf.train.Int64List(value=[value]))

def create_example(image:np.ndarray, label:int):
    feature = {
        "label" : int64_feature(label),
        "image" : image_feature(image),        
    }
    return tf.train.Example(features=tf.train.Features(feature=feature))

path_to_your_images = "/path/to/your/images"

#Here we sample 10000 random images from your image folder
images_path_list = random.sample(os.listdir(path_to_your_images), 10000)

with tf.io.TFRecordWriter("train.tfrec") as writer:
    for file_path in images_path_list:
        img = tf.io.read_file(os.path.join(path_to_your_images, file_path))
        label = int(file_path.strip(".jpg"))
        """ 
        Here we decode the image bytes first and encode it again using encode_jpeg(). 
        This encoding reduces the memory occupied by the TF records file. 
        You can also directly write the raw image bytes to TF records but that would make 
        the file size of TF records to be huge as it saves the actual bytes of the image
        """
        example = create_example(tf.image.decode_jpeg(img, channels=3), label) 
        writer.write(example.SerializeToString())

以上代码将创建包含 10000 张图像的 TF 记录文件。现在你可以使用下面的代码来解析图像和标签并创建你的数据集句柄来训练你的模型

def _parse_dataset(example_proto):
    _feature_description = {
        "image" : tf.io.FixedLenFeature([], tf.string),        
        "label" : tf.io.FixedLenFeature([], tf.int64)
    }
    
    example = tf.io.parse_single_example(example_proto, _feature_description)

    image = tf.io.decode_jpeg(example["image"])    
    
    image = tf.cast(image, tf.float32) / 255.0
    label = example["label"]

def create_dataset(tfrecord_paths, batch_size):
    raw_dataset = tf.data.TFRecordDataset(tfrecord_paths)
    dataset = raw_dataset.map(_parse_dataset)
   
    dataset = dataset.batch(batch_size)
    return dataset


train_dataset = create_dataset("/path/to/train.tfrec",8)

现在您可以直接在

model.fit(train_dataset)
中使用train_dataset 来训练您的模型。要从数据集中访问一个示例,您可以执行
train_dataset.take(1)
。这将为您提供两个值,一个是您的形状图像
(batch_size, height, width, channels)
,另一个是您的
label

注意:您不仅限于您的图像和标签,您还可以通过feature_description字典将其他信息写入TF记录文件。例如,如果你想为每个示例添加图像文件名,图像的宽度和高度,那么你可以修改你的特征描述如下

feature = {
        "file_name" : bytes_feature(filename.encode("utf8")),
        "width" : int64_feature(width),
        "height" : int64_feature(height)
        "label" : int64_feature(label),
        "image" : image_feature(image),        
    }

您需要确保在解析数据集时使用相同的特征描述。

希望对您有所帮助。干杯!!!

© www.soinside.com 2019 - 2024. All rights reserved.