如何在Python中加载图像,但保持压缩?

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

我有一系列图像,都可以在JP2和PNG上使用,我需要在python程序中加载这个图像以按顺序显示它们。现在我只需要显示序列的一部分,例如:

  • 一次从Frame12到Frame24,
  • 第二次从第2帧到第7帧,
  • 等等 加载所有图像会占用太多内存,并且每次新序列执行任务时都会加载。 有一个函数/方法在程序中加载图像,但保持压缩?我可以将这些图像保存在内存中以备即用,但内存占用率低吗?
  • python python-3.x image
    2个回答
    0
    投票

    您可以将可爱的小型JPEG / PNG / JP2图像作为一堆字节读入内存,并将其保存在与磁盘相同的压缩大小,然后在需要时从内存中解压缩。

    首先,让我们看一下内存中RGB888的1280x1024图像所需的内存 - 它高达3.9MB:

    # Decompressed image in memory takes 3.9MB memory
    im = np.zeros([1280,1024,3], dtype=np.uint8)
    
    # print(im.nbytes) => 3932160
    

    现在让我们看一下相同大小的JPEG:

    enter image description here

    这是在磁盘上,与ls -l

    -rw-r--r--@  1 mark  staff      47276  2 Apr 17:13 image.jpg
    

    在这里它仍然在内存中压缩,也是在47kB或仅1.2%的大小:

    # Same image as JPEG takes 47kB of memory
    with open('image.jpg','rb') as f: 
       jpg = f.read() 
    
    # print(len(jpg)) => 47276
    

    现在,当您需要图像时,将其从内存而不是从磁盘解压缩

    # Read with 'imageio'
    from io import BytesIO 
    import imageio
    numpyArray = imageio.imread(BytesIO(jpg))
    # print(numpyArray.shape) =>(1024, 1280, 3)
    
    # Or, alternatively, and probably faster, read with OpenCV
    import cv2
    numpyArray = cv2.imdecode(np.frombuffer(jpg,dtype=np.uint8), -1)  
    # print(numpyArray.shape) =>(1024, 1280, 3)
    

    另一个完全不同的选项,可以更快地解码里程,但只会将内存占用减少3倍,这是为了让图像更加便捷。您可以将颜色数量减少到少于256种独特颜色,并存储256种颜色的调色板。然后在每个像素位置存储一个字节,它是调色板的索引,而不是3个字节的RGB。这将使您的内存使用量从3.9MB /图像减少到1.3MB /图像。它不需要任何解码。但可能会导致颜色保真度和/或条带的轻微损失 - 这可能是也可能不是问题,具体取决于相机/图像的质量。

    看起来像这样(未经测试):

    from PIL import Image
    import numpy as np
    
    im = Image.open('image.jpg')
    
    # Make into Numpy array - size is 3.9MB
    a = np.array(im)
    
    # Now make a 256 colour palletised version
    p = im.convert('P',palette=Image.ADAPTIVE)
    
    # Make into Numpy array - size is now only 1.3MB
    a = np.array(p)
    

    0
    投票

    PIL是Python Imaging Library,它为python解释器提供了图像编辑功能。

    Windows:根据您的python版本下载相应的Pillow包。确保根据您拥有的python版本下载。

    要导入Image模块,我们的代码应该从以下行开始:

        from PIL import Image
    
        Open a particular image from a path
        #img  = Image.open(path)      
        # On successful execution of this statement, 
        # an object of Image type is returned and stored in img variable) 
    
        try:  
            img  = Image.open(path)  
        except IOError: 
        pass
    
    # Use the above statement within try block, as it can  
    # raise an IOError if file cannot be found,  
    # or image cannot be opened.
    

    检索图像的大小:创建的Image类的实例具有许多属性,其中一个有用的属性是size。

    from PIL import Image 
    
    filename = "image.png"
    with Image.open(filename) as image: 
        width, height = image.size 
    #Image.size gives a 2-tuple and the width, height can be obtained 
    

    其他一些属性包括:Image.width,Image.height,Image.format,Image.info等。

    保存图像中的更改:要保存对图像文件所做的任何更改,我们需要提供路径和图像格式。

    img.save(path, format)     
    # format is optional, if no format is specified,  
    #it is determined from the filename extension
    
     from PIL import Image  
    
    def main(): 
        try: 
         #Relative Path 
        img = Image.open("picture.jpg") 
        width, height = img.size 
    
        img = img.resize((width/2, height/2)) 
    
        #Saved in the same relative location 
        img.save("resized_picture.jpg")  
    except IOError: 
        pass
    
    if __name__ == "__main__": 
        main() 
    
    © www.soinside.com 2019 - 2024. All rights reserved.