【问题标题】:Optimization reading images from disk python从磁盘python读取图像的优化
【发布时间】:2017-06-29 05:24:37
【问题描述】:

我想知道什么更快更好:

class AvgRGB(object):

    def __init__(self, path):
        self.path = path

        self.imgs = []
        self.avg = MyRGBImg()       

    def gather_pictures(self):
        # for now gathe all the files, next check for picture extensions
        p = self.path
        self.names = [f for f in listdir(p) if isfile(join(p, f))]

        for imgname in self.names:
            path, name, ext = get_pathname(imgname)
            if ext in ['.png', '.jpg']:
                imagepath = join(self.path, imgname)
                img = MyRGBImg(imagepath )
                self.imgs.append(img)

    def average(self):
        dataset = self.imgs

        s = MyRGBImg(np.zeros(dataset[0].data.shape))
        for i, picture in enumerate(dataset):
            im = picture.data
            s += im 

        s = s / float(len(dataset))
        self.avg = MyRGBImg(s)

class AvgRGB_savememory(object):

    def __init__(self, path):
        self.path = path
        self.imgs_names = []

    def get_image(self, index):
        # read the image corresponding to the path
        pathtopic = join(self.path, self.imgs_names[index])
        myimg = MyRGBImg()
        myimg.read_from_file(pathtopic)
        return myimg

    def gather_pictures_names(self):
        p = self.path
        filenames = [f for f in listdir(p) if isfile(join(p, f))]
        for filename in filenames:
            path, name, ext = get_pathname(filename)
            if ext in ['.png', '.jpg']:       
                self.imgs_names.append(filename)

    def average(self, aligned = True, debug = False):
        sizedataset = len(self.imgs_names)
        picture = self.get_image(0)       

        s = MyRGBImg(np.zeros(picture.data.shape)) 
        for i in range(sizedataset):
            #load the picture
            picture = self.get_image(i)
            im = picture.data
            #perform operations
            s += im 

        s = s / float(sizedataset)
        self.avg = MyRGBImg(s)

这段代码从一个文件夹中获取图像并将它们平均化。

这两个片段之间的区别是:第一个将图像加载到数组中,而第二个从内存中加载图片。

现在你必须想象这不是我做的唯一操作,当我尝试分析来自 500 张图片 (1080x1080x3) 的数据时,程序会出现内存错误。

我的问题是哪个更好?还是更快?

理论上第一个应该更快,因为将所有图像加载到内存中,但是当数组的大小大于 RAM 时会发生什么?他们被写在磁盘上?如果这不是比仅仅阅读单个图像慢吗? 此外,考虑到我的所有程序都是连续的,从缓冲区流式传输图片会更有效吗?

【问题讨论】:

  • 为什么不直接分析你的代码?
  • 我在想一个理论上的答案...我知道第二种方法在逻辑上更快,因为它不会阻塞内存,如果我使用 chrome 浏览 stackoverflow 是...宝贵的资源
  • 理论以数据为基础。自己试验一下,然后确定为什么你会看到你在做什么。
  • 嗯...这令人不安。我的意思是我希望我不是第一个遇到这种问题的人。就像有很多选项可以测试(以二进制加载保存数据,以 png 格式加载保存数据(要写入的数据更少,计算更多)等等)但我确信有一种聪明的方法来估计这些过程.或指示条件 -> 如果总图像大小 > x 使用保存内存选项,否则使用内存中的负载
  • 我发布了你所说的

标签: python image memory optimization


【解决方案1】:

我没有您的示例数据,但我会使用一些虚拟函数和 arg。您可以通过调用找出给定函数调用的实际成本,如下所示:

your_function = lambda x: enumerate(range(x, x**x))
your_arg1 = 8
import cProfile
import pstats
prof = cProfile.Profile()
group = prof.runcall(your_function, your_arg1)
p = pstats.Stats(prof)
p.sort_stats('time').print_stats(100)

这将打印出来,例如:

   3 function calls in 0.600 seconds

   Ordered by: internal time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.600    0.600    0.600    0.600 {range}
        1    0.000    0.000    0.600    0.600 python.py:1(<lambda>)
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}

【讨论】:

  • 我想要一种更理论的方法。我的意思是我知道第二种方法更快,并且没有给出Memory error,但与我所学到的关于 RAM 和 ROM 的所有知识都背道而驰
【解决方案2】:

按照建议,我做了一些自制的分析

我使用了这个自己实现的计时功能
https://pastebin.com/Myph3ndJ

这里有两个测试函数AvgFolderAvgFolderMem,第一个加载内存中的所有图像,而第二个在需要时从磁盘加载图像。下面是
https://github.com/Pella86/DenoiseAverage/blob/master/src/AvgFolder_class.py

的实现

这些是总结的结果: https://pastebin.com/pcHZFVLV

5 张图片,128x128(灰度)

--------LOAD IN MEM 5---------
Total elapsed time: 00:00:05
305 us/px
--------MEMSAVE 5---------
Total elapsed time: 00:00:06
366 us/px

20 张图片,128x128(灰度)

--------LOAD IN MEM 20---------
Total elapsed time: 00:00:20
1220 us/px
--------MEMSAVE 20 ---------
Total elapsed time: 00:00:20
1220 us/px

100 张图片,128x128(灰度)

--------LOAD IN MEM 100---------
Total elapsed time: 00:01:37
5920 us/px
--------MEMSAVE 100---------
Total elapsed time: 00:01:46
6469 us/px

20 张图片,512x512(灰度)

--------LOAD IN MEM---------
Total elapsed time: 00:27:26
100'463 us/px
--------MEMSAVE---------
Total elapsed time: 00:27:40
101'310 us/px

因此与教科书的概念相反,使用 numpy 从磁盘内存上下加载文件可能非常有效。 我不知道是因为图像出现分页问题还是因为我的 RAM 充满了垃圾。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-08-13
    • 2015-07-19
    • 1970-01-01
    • 2016-04-26
    • 1970-01-01
    • 1970-01-01
    • 2020-04-14
    相关资源
    最近更新 更多