Importing PNG files into Numpy?

PythonImageNumpyPng

Python Problem Overview


I have about 200 grayscale PNG images stored within a directory like this.

1.png
2.png
3.png
...
...
200.png

I want to import all the PNG images as NumPy arrays. How can I do this?

Python Solutions


Solution 1 - Python

According to the doc, scipy.misc.imread is deprecated starting SciPy 1.0.0, and will be removed in 1.2.0. Consider using imageio.imread instead.

Example:

import imageio

im = imageio.imread('my_image.png')
print(im.shape)

You can also use imageio to load from fancy sources:

im = imageio.imread('http://upload.wikimedia.org/wikipedia/commons/d/de/Wikipedia_Logo_1.0.png')

Edit:

To load all of the *.png files in a specific folder, you could use the glob package:

import imageio
import glob

for im_path in glob.glob("path/to/folder/*.png"):
     im = imageio.imread(im_path)
     print(im.shape)
     # do whatever with the image here

Solution 2 - Python

Using just scipy, glob and having PIL installed (pip install pillow) you can use scipy's imread method:

from scipy import misc
import glob

for image_path in glob.glob("/home/adam/*.png"):
    image = misc.imread(image_path)
    print image.shape
    print image.dtype

UPDATE

According to the doc, scipy.misc.imread is deprecated starting SciPy 1.0.0, and will be removed in 1.2.0. Consider using imageio.imread instead. See the answer by Charles.

Solution 3 - Python

This can also be done with the Image class of the PIL library:

from PIL import Image
import numpy as np
 
im_frame = Image.open(path_to_file + 'file.png')
np_frame = np.array(im_frame.getdata())

Note: The .getdata() might not be needed - np.array(im_frame) should also work

Solution 4 - Python

Using a (very) commonly used package is prefered:

import matplotlib.pyplot as plt
im = plt.imread('image.png')

Solution 5 - Python

If you are loading images, you are likely going to be working with one or both of matplotlib and opencv to manipulate and view the images.

For this reason, I tend to use their image readers and append those to lists, from which I make a NumPy array.

import os
import matplotlib.pyplot as plt
import cv2
import numpy as np

# Get the file paths
im_files = os.listdir('path/to/files/')

# imagine we only want to load PNG files (or JPEG or whatever...)
EXTENSION = '.png'

# Load using matplotlib
images_plt = [plt.imread(f) for f in im_files if f.endswith(EXTENSION)]
# convert your lists into a numpy array of size (N, H, W, C)
images = np.array(images_plt)

# Load using opencv
images_cv = [cv2.imread(f) for f in im_files if f.endswith(EXTENSION)]
# convert your lists into a numpy array of size (N, C, H, W)
images = np.array(images_cv)

The only difference to be aware of is the following:

  • opencv loads channels first
  • matplotlib loads channels last.

So a single image that is 256*256 in size would produce matrices of size (3, 256, 256) with opencv and (256, 256, 3) using matplotlib.

Solution 6 - Python

I changed a bit and it worked like this, dumped into one single array, provided all the images are of same dimensions.

png = []
for image_path in glob.glob("./train/*.png"):
    png.append(misc.imread(image_path))    
    
im = np.asarray(png)

print 'Importing done...', im.shape

Solution 7 - Python

To read in one image:

import PIL.Image
im = PIL.Image.open('path/to/your/image')
im = np.array(im)

Iterate to read in multiple images.

This answer is similar to this but simpler (no need for .getdata()).

Solution 8 - Python

I like the build-in pathlib libary because of quick options like directory= Path.cwd() Together with opencv it's quite easy to read pngs to numpy arrays. In this example you can even check the prefix of the image.

from pathlib import Path
import cv2
prefix = "p00"
suffix = ".png"
directory= Path.cwd()
file_names= [subp.name for subp in directory.rglob('*') if  (prefix in subp.name) & (suffix == subp.suffix)]
file_names.sort()
print(file_names)

all_frames= []
for file_name in file_names:
    file_path = str(directory / file_name)
    frame=cv2.imread(file_path)
    all_frames.append(frame)
print(type(all_frames[0]))
print(all_frames[0] [1][1])

Output:

['p000.png', 'p001.png', 'p002.png', 'p003.png', 'p004.png', 'p005.png', 'p006.png', 'p007.png', 'p008.png', 'p009.png']
<class 'numpy.ndarray'>
[255 255 255]

Solution 9 - Python

If you prefer the standard library:

#IMPORTANT: This Code only works with Python>=3.6
Directory="."#Your directory
import os
import tkinter
import numpy
tk=tkinter.Tk()
tk.overrideredirect(1)
tk.geometry("0x0")
Items=[]
for i in os.listdir(Directory):
    fn=Directory+os.sep+i
    imgArray=[]
    image=tkinter.PhotoImage(file=fn)
    for w in range(image.width()):
        entry=[]
        for h in range(image.height()):
            entry.append(image.get(w,h))
        imgArray.append(entry)
    imgArray=numpy.array(imgArray)
    Items.append(imgArray)
tk.destroy()

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionpbuView Question on Stackoverflow
Solution 1 - PythonCharlesView Answer on Stackoverflow
Solution 2 - PythonspoorccView Answer on Stackoverflow
Solution 3 - PythonmrkView Answer on Stackoverflow
Solution 4 - PythonNirView Answer on Stackoverflow
Solution 5 - Pythonn1k31t4View Answer on Stackoverflow
Solution 6 - PythonpbuView Answer on Stackoverflow
Solution 7 - PythonzabopView Answer on Stackoverflow
Solution 8 - PythonKolibrilView Answer on Stackoverflow
Solution 9 - PythonHelpfulHelperView Answer on Stackoverflow