哪种图像格式更适合机器学习 .png .jpg 或其他?

机器算法验证 Python 机器学习 图像处理 神经网络 计算机视觉
2022-03-13 18:57:26

我正在尝试用图像训练神经网络。由于我是从视频源中提取图像,因此我可以将它们转换为 .png 或 .jpg。机器学习和深度学习首选哪种格式。我的神经网络模型包含卷积层、最大池化层和图像大小调整。

3个回答

这是一个真实的案例:4K 视频流的精确分割管道(这里有一些示例)。我确实依赖于传统的计算机视觉以及神经网络,因此需要准备高质量的训练集。此外,找到一些特定对象的训练集是不可能的:

在此处输入图像描述

见行动

长话短说,创建训练集和进行额外的后处理需要大约 1TB 的数据。我使用 ffmpeg 并将提取的帧存储为 JPG。没有理由使用 PNG,原因如下:

  • 视频流已经被压缩
  • 压缩流中的任何单个帧都将包含一些伪影
  • 对有损压缩数据使用无损压缩可能看起来有点奇怪
  • 没有理由消耗更多空间来存储相同的数据
  • 此外,没有理由消耗额外的带宽

让我们做一个快速测试(真的很快)。相同的 4K 流,相同的设置,将帧提取为 PNG 和 JPG。如果您发现任何差异 - 对您有好处 :) 任何现实生活中的问题都可能与压缩视频流有关,因为带宽至关重要。

PNG 在此处输入图像描述

JPG 在此处输入图像描述

最后

如果您需要更多详细信息 - 使用 4K(如果您需要更有价值的详细信息,请使用 8K)。我所拥有的几乎所有示例都是基于 4K 输入的。当您尝试处理真实场景和快速移动的物体时,FPS 才是真正重要的。

在此处输入图像描述

见行动

不用说,相机和光线条件是获得适当细节水平的最关键的先决条件。

JPG 更适用于逼真的图像,PNG 更适用于具有清晰线条和纯色的绘图。对于视频提要的帧,我肯定会使用 JPG。

更新:由于视频通常以类似于 JPG 的方式压缩,因此质量不太可能比现有的质量下降得更多。数据集大小也不是不重要的。

正如其他人在评论中指出的那样,PNG无损格式比JPEG. 话虽如此,作为您管道的输入,答案将是“两者都不是”。几乎总是你必须预处理你的图像,例如裁剪它们,减去平均值等。在典型的情况下,我会运行我的管道大约 100 次,然后我才会对结果感到满意。每次都对图像进行预处理只会浪费资源,尤其是因为读取图像需要时间。

更好的主意是使用HDF5,格式非常适合处理数字数据和切片。通常你会:

  1. 加载图像。
  2. 对其进行预处理。
  3. 保存到 HDF5。您将创建两个数据集:一个用于图像数据,第二个用于标签(如果存在)。
  4. 冲洗并重复。

如果HDF5对您来说是新的并且可能看起来有些抽象,那么您将在下面找到一个可用于使用这种格式将图像存储到磁盘的类示例。

import h5py
import os

class HDF5Writer(object):
    def __init__(self, dims, output_path, data_key="images", buf_size=1000):
        self.db = h5py.File(output_path, "w")
        self.data = self.db.create_dataset(data_key, dims, dtype="float")
        self.labels = self.db.create_dataset("labels", (dims[0],), dtype="int")

        self.bufSize = buf_size
        self.buffer = {"data": [], "labels": []}
        self.idx = 0

    def add(self, rows, labels):
        self.buffer["data"].extend(rows)
        self.buffer["labels"].extend(labels)

        if len(self.buffer["data"]) >= self.bufSize:
            self.flush()

    def flush(self):
        i = self.idx + len(self.buffer["data"])
        self.data[self.idx:i] = self.buffer["data"]
        self.labels[self.idx:i] = self.buffer["labels"]
        self.idx = i
        self.buffer = {"data": [], "labels": []}

    def store_class_labels(self, classLabels):
        dt = h5py.special_dtype(vlen=str)
        labelSet = self.db.create_dataset("label_names", (len(classLabels),), dtype=dt)
        labelSet[:] = classLabels

    def close(self):
        if len(self.buffer["data"]) > 0:
            self.flush()
        self.db.close()

我建议阅读有关h5py的教程,额外的学习曲线是值得的。缓冲区只是告诉您应该将多少图像数据写入驱动器。

如何使用它(在伪代码中):

data_dim = (num_of_images, x_dim, y_dim, num_of_colours)
writer = HDF5Writer(data_dim, output_path)

for image_path in paths:
    image = read_image(image_path)
    image = preprocess(image) 
    writer.add([image], [label])

writer.close()

HDF5 的严重缺点是,如果在没有任何压缩的情况下使用,它将使您的数据集大小增加 50 倍。在一定程度上,使用它似乎不可行,但很可能无论如何您都必须使用专门的计算基础设施(这样存储空间就不会成为问题)。