简体   繁体   English

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

[英]How can i load a image in Python, but keep it compressed?

I have a series of images, all available both on JP2 and PNG, and I need to load this image on a python program to show them in a sequence.我有一系列图像,都可以在 JP2 和 PNG 上使用,我需要在 python 程序上加载这个图像以按顺序显示它们。 Now I need only show a part of the sequence, for example:现在我只需要显示序列的一部分,例如:

  • one time from Frame12 to Frame24,一次从 Frame12 到 Frame24,
  • second time from Frame2 to Frame7,第二次从 Frame2 到 Frame7,
  • etc.等等。

    load all images take me too much memory and load every time a new sequence is a long task to do.加载所有图像占用我太多内存,每次加载新序列是一项很长的任务。
    there is a function/method to load the image in a program, but keep compressed?有一个函数/方法可以在程序中加载图像,但要保持压缩? Can I save these images on memory to be ready-to-use, but with low memory occupation?我可以将这些图像保存在内存中以备使用,但内存占用低吗?

  • You can read the lovely, small JPEG/PNG/JP2 images into memory as a bunch of bytes and hold them there compressed with the same size as they have on disk and then uncompress them from memory when you need them.您可以将可爱的小型 JPEG/PNG/JP2 图像作为一堆字节读取到内存中,并将它们以与磁盘上相同的大小进行压缩,然后在需要时从内存中解压缩它们。

    First, let's look at the memory required by a 1280x1024 image of RGB888 in memory - its a whopping 3.9MB:首先,让我们看看内存中 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
    

    Now let's look at a JPEG the same size:现在让我们看看同样大小的 JPEG:

    在此处输入图片说明

    Here it is on disk, with ls -l :这是在磁盘上,使用ls -l

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

    And here it is still compressed in memory, also at 47kB or just 1.2% of the size:在这里它仍然在内存中被压缩,也是 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
    

    Now when you want an image, decompress it from memory rather than from disk现在当你想要一个图像时,从内存而不是从磁盘解压它

    # 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)
    

    Another, totally different option that will decode miles faster, but will only reduce the memory footprint by a factor of 3 is to palettise the images.另一个完全不同的选项可以更快地解码数英里,但只会将内存占用减少 3 倍,是对图像进行调色。 You reduce the number of colours down to less than 256 unique colours, and store a palette with 256 colours.您将颜色数量减少到少于 256 种独特颜色,并存储具有 256 种颜色的调色板。 At each pixel location, you then store a single byte which is the index into the palette, rather than 3 bytes of RGB.然后在每个像素位置存储一个字节,它是调色板的索引,而不是 3 个字节的 RGB。 This will reduce your memory usage from 3.9MB/image to 1.3MB/image.这会将您的内存使用量从 3.9MB/图像减少到 1.3MB/图像。 It will not require any decoding.它不需要任何解码。 but may result in slight loss of colour fidelity and/or banding - which may or may not be an issue depending on the quality of your camera/images.但可能会导致色彩保真度和/或条纹的轻微损失 - 这可能是也可能不是问题,具体取决于您的相机/图像的质量。

    That looks something like this (untested):看起来像这样(未经测试):

    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)
    

    PIL is the Python Imaging Library which provides the python interpreter with image editing capabilities. PIL 是 Python 图像库,它为 Python 解释器提供图像编辑功能。

    Windows: Download the appropriate Pillow package according to your python version. Windows:根据您的 python 版本下载适当的 Pillow 包。 Make sure to download according to the python version you have.确保根据您拥有的python版本下载。

    To import the Image module, our code should begin with the following line:要导入 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.
    

    Retrieve size of image: The instances of Image class that are created have many attributes, one of its useful attribute is size.检索图像大小:创建的 Image 类的实例有很多属性,其中一个有用的属性是大小。

    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 
    

    Some other attributes are: Image.width, Image.height, Image.format, Image.info etc.其他一些属性是:Image.width、Image.height、Image.format、Image.info 等。

    Save changes in image: To save any changes that you have made to the image file, we need to give path as well as image format.保存图像中的更改:要保存您对图像文件所做的任何更改,我们需要提供路径和图像格式。

    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() 
    

    声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

     
    粤ICP备18138465号  © 2020-2024 STACKOOM.COM