【问题标题】:How to compute image mean for a set of image files?如何计算一组图像文件的图像平均值?
【发布时间】:2017-01-14 20:44:34
【问题描述】:

是否有人对如何计算一组图像(文件夹中的 .jpg 文件)的图像均值并为 ImageDeserializer 生成正确格式的 XML 文件有高级解释?

我已经看到 CNTK_201A_CIFAR-10_DataLoader 中的代码,它执行此操作。但是,那里的输入格式不同,因此不清楚如何将图像文件作为输入来处理。

【问题讨论】:

    标签: cntk


    【解决方案1】:

    您可以按照computes the mean input for CIFAR 的代码示例进行操作。基本上它会遍历所有训练图像并计算平均值。然后它以 OpenCV 可以理解的格式将其写入文件中。第一部分很容易,因为 numpy 和 PIL,第二部分很容易,因为 minidom。

    【讨论】:

    • 你能再详细一点吗?正如我所说,我查看了提供的链接中引用的代码。然而,平均计算有点复杂到 saveImage 函数中。 CIFAR 案例中的源格式似乎是一个文本文件,这与使用 PIL 读取 .jpg 文件所获得的不同。我认为,如果平均值是根据完成的文件图像计算的,或者如果明确了平均值计算的格式是什么,我认为教程会更简洁。
    • 在 CNTK_201A_CIFAR-10_DataLoader 中的 saveImage 函数内部看起来是计算均值,然后有一些代码步骤不是很明显。看起来一些填充完成了。这会不会影响平均值计算的正确性,因为看起来平均值是在不同的图像上计算的?然后有几个没有 cmets 的嵌套 for 循环。如果对功能逻辑进行更多解释会有所帮助。
    【解决方案2】:

    以下是基于 Nikos 提供的链接的完整解决方案,用于计算存储在 ZIP 文件(如果您使用 ZIP 图像阅读器)或图像文件列表中的所有图像的平均值。

    关于您的问题:在 DataLoader 教程中,填充仅影响将图像保存到文件的代码路径,而不影响计算平均值。

    import zipfile
    import io
    import numpy as np
    from PIL import Image
    from scipy.misc import imread, imresize, fromimage
    import xml.etree.cElementTree as et
    import xml.dom.minidom
    # saveMean function taken from 
    # https://github.com/Microsoft/CNTK/blob/v2.0.beta7.0/Examples/Image/DataSets/CIFAR-10/cifar_utils.py#L84
    def saveMean(fname, data, imgSize):
        root = et.Element('opencv_storage')
        et.SubElement(root, 'Channel').text = '3'
        et.SubElement(root, 'Row').text = str(imgSize)
        et.SubElement(root, 'Col').text = str(imgSize)
        meanImg = et.SubElement(root, 'MeanImg', type_id='opencv-matrix')
        et.SubElement(meanImg, 'rows').text = '1'
        et.SubElement(meanImg, 'cols').text = str(imgSize * imgSize * 3)
        et.SubElement(meanImg, 'dt').text = 'f'
        et.SubElement(meanImg, 'data').text = ' '.join(['%e' % n for n in np.reshape(data, (imgSize * imgSize * 3))])
        tree = et.ElementTree(root)
        tree.write(fname)
        x = xml.dom.minidom.parse(fname)
        with open(fname, 'w') as f:
            f.write(x.toprettyxml(indent = '  '))
    def loadAndResize(f, networkSize):
        im = Image.open(io.BytesIO(f))
        n = fromimage(im).astype(np.float)
        return imresize(n, (networkSize, networkSize))
    

    然后在从 ZIP 文件或原始文件中以字节形式读取图像的函数中使用这些构建块:

    def meanFromZip(zipFile, networkSize):
        imgSum = np.zeros((networkSize, networkSize, 3), np.float)
        with zipfile.ZipFile(zipFile) as z:
            allFiles = z.namelist()
            for f in allFiles:
                imgSum = imgSum + loadAndResize(z.read(f), networkSize)
        return imgSum / len(allFiles)
    def meanFromFiles(files, networkSize):
        imgSum = np.zeros((networkSize, networkSize, 3), np.float)
        for f in files:
            with open(f, 'rb') as b:
                imgSum = imgSum + loadAndResize(b.read(), networkSize)
        return imgSum / len(files)
    

    调用如下:

    zipFile = "myImages.zip"
    networkSize = 224
    mean = meanFromZip(zipFile, networkSize)
    saveMean("mean.xml", mean, networkSize)
    files = ["c:/temp/Column0_Line16.jpg", "C:/temp/Column0_Line47.jpg"]
    mean2 = meanFromFiles(files, networkSize)
    

    【讨论】:

    • “关于您的问题:在 DataLoader 教程中,填充仅影响将图像保存到文件的代码路径,而不影响计算平均值。”:是的,但不应该根据基础计算平均值什么保存到文件中?这是输入到培训的文件,我原以为平均文件应该反映创建的实际文件的内容,而不是根据输入计算。
    • 我已尝试使用您的代码生成平均 XML 文件,但我无法使其与 CIFAR 教程中提供的 XML 文件相同。提供的 XML 文件是根据 32x32x3 像素输入图像计算得出的。生成的 .png 文件为 40x40x3 像素,因此不可能在这些文件上生成平均值并使其与在 32x32x3 图像上计算的平均值相同。我认为这里的教程可能存在缺陷。
    猜你喜欢
    • 1970-01-01
    • 2015-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-01
    • 1970-01-01
    • 2022-11-30
    • 2017-04-03
    相关资源
    最近更新 更多