I am a novice coder, having been self-taught through codeacademy. I am wondering what is the easiest way to import png files to python (2.7.14) with the goal of using these files in a deep-learning program.
So far I have tried these two codes:
import scipy
from scipy import misc
import glob
for image_path in glob.glob("/E:/_SAMM_Projects/gemini_hikai_DM_hack_complete/export/contact_frames/boat/*.png"):
image = misc.imread(image_path)
print image.shape
print image.dtype
import scipy
from scipy import misc
import glob
import numpy
png = []
for image_path in glob.glob("/E:/_SAMM_Projects/gemini_hikai_DM_hack_complete/export/contact_frames/boat/*.png"):
png.append(misc.imread(image_path))
im = np.asarray(png)
print "importing done...", im.shape
based off templates I have found online, both do not seem to work
In the context of deep learning, I understand that you would like to read an image into a numpy array so you can use deep learning models (such as ConvNet) on it.
I suggest using OpenCV for your purpose.
import cv2
image = cv2.imread("yourimg.png")
Related
i using SLIVER07 dataset for liver segmentation task but i am stuck in reading that images.
import SimpleITK as sitk
import numpy as np
import matplotlib.pyplot as plt
# reading .mhd file from slive07 dataset
itkimage = sitk.ReadImage('liver-orig001.mhd')
ct_scan = sitk.GetArrayFromImage(itkimage)
plt.imshow(ct_scan[1])
You are trying to pass the entire 3D image volume to imshow. You could instead try:
plt.imshow(ct_scan[40,:,:])
Which will show the 40th slice.
Of interest might be the platipy library, available here, or just $ pip install platipy. The built-in image visualiser (based on matplotlib) is perfect for 3D image visualisation in python, and has lots of cool features.
A little demo:
from platipy.imaging import ImageVisualiser
img = sitk.ReadImage("image_filename.mhd")
vis = ImageVisualiser(img)
fig = vis.show()
I am using code to read a .tiff file in order to calculate a fractal dimension. My code looks like this:
import matplotlib.pyplot as plt
raster = plt.imread('xyz.tif')
for i in range(x1, x2):
for j in range(y1, y2):
pixel = raster[i][j]
This works, but I have to read a lot of pixels so I would like this to be fast, and ideally minimize electricity usage given current events. Is there a better library than matplotlib for this purpose? For example, could using a library specialized for matrix operations such as pandas help? Additionally, would another language such as C have better performance than python?
Edit: #cgohlke in the comments and others have found that cv2 is slower than tifffile for large and/or compressed images. It is best you test the different options on realistic data for your application.
I have found cv2 to be the fastest library for this. Using 5000 128x128 uint16 tif images gives the following result:
import time
import matplotlib.pyplot as plt
t0 = time.time()
for file in files:
raster = plt.imread(file)
print(f'{time.time()-t0:.2f} s')
1.52 s
import time
from PIL import Image
t0 = time.time()
for file in files:
im = np.array(Image.open(file))
print(f'{time.time()-t0:.2f} s')
1.42 s
import time
import tifffile
t0 = time.time()
for file in files:
im = tifffile.imread(file)
print(f'{time.time()-t0:.2f} s')
1.25 s
import time
import cv2
t0 = time.time()
for file in files:
im = cv2.imread(file, cv2.IMREAD_UNCHANGED)
print(f'{time.time()-t0:.2f} s')
0.20 s
cv2 is a computer vision library written in c++, which as the other commenter mentioned is much faster than pure python. Note the cv2.IMREAD_UNCHANGED flag, otherwise cv2 will convert monochrome images to 8-bit rgb.
I am not sure which library is the fastest but I have very good experience with Pillow:
from PIL import Image
raster = Image.open('xyz.tif')
then you could convert it to a numpy array:
import numpy
pixels = numpy.array(raster)
I would need to see the rest of the code to be able to recommend any other libraries. As for the language C++ or C would have better performance as they are low level languages. So depends on how complex your operations are and how much data you need to process, C++ scripts were shown to be 10-200x faster(increasing with the complexity of calculations). Hope this helps if you have any further questions just ask.
I want to store my image directory in memory, then load the images into a numpy array.
The normative way to load images that are not in memory is as follows:
import PIL.Image
import numpy as np
image = PIL.Image.open("./image_dir/my_image_1.jpg")
image = np.array(image)
However, I am not sure how to do this when the images are in memory. So far, I have been able to setup the following starter code:
import fs
import fs.memoryfs
import fs.osfs
image_dir = "./image_dir"
mem_fs = fs.memoryfs.MemoryFS()
drv_fs = fs.osfs.OSFS(image_path)
fs.copy.copy_fs(drv_fs, mem_fs)
print(mem_fs.listdir('.'))
Returns:
['my_image_1.jpg', 'my_image_2.jpg']
How do I load images that are in memory into numpy?
I am also open to alternatives to the fs package.
As per the documentation, Pillow's Image.open accepts a file object instead of a file name, so as long as your in-memory file package provides Python file objects (which it most likely does), you can just use them. If it doesn't, you could even just wrap them in a class that provides the required methods. Assuming you are using PyFilesystem, according to its documentation you should be fine.
So, you want something like:
import numpy as np
import PIL.Image
import fs.memoryfs
import fs.osfs
import fs.copy
mem_fs = fs.memoryfs.MemoryFS()
drv_fs = fs.osfs.OSFS("./image_dir")
fs.copy.copy_file(drv_fs, './my_image_1.jpg', mem_fs, 'test.jpg')
with mem_fs.openbin('test.jpg') as f:
image = PIL.Image.open(f)
image = np.array(image)
(note I just used copy_file because I tested with a single file, you can use copy_fs if you need to copy the entire tree - it's the same principle)
I need to read a folder full of multi-page tiffs generated by the Suite2p neurobiology package.
From the Suite2p source code the multi-tiffs are created as follows:
import numpy as np
from tifffile import TiffWriter
# fake example images
img_5_tiles = np.random.randint(0,65535,(5,10,20), dtype='uint16')
img_4_tiles = img_5_tiles[1:,...]
# save fake images
with TiffWriter(r'D:\5tiles.tiff') as tif:
for frame in img_5_tiles:
tif.save(frame)
with TiffWriter(r'D:\4tiles.tiff') as tif:
for frame in img_4_tiles:
tif.save(frame)
When I try to read them into dask, skimage.io default tifffile plugin fails to get the correct shape:
from dask.array.image import imread
from skimage import io
def read_with_tifffile(path):
return io.imread(path, plugin='tifffile')
# should produce (5,10,20) instead of (1,10,20)
imread(r'D:\5tiles.tiff', imread=read_with_tifffile).shape
I can overcome this by using the non-default skimage.io.imread plugin 'pil'
def read_with_pil(path):
return io.imread(path, plugin='pil', mode='L')
# gives (1,5,10,20) which is acceptable
imread(r'D:\5tiles.tiff', imread=read_with_pil).shape
Unfortunately, if the number of tiles equals to 4, skimage starts to handle the shape differently:
# gives (1,10,20,4) instead of (1,4,10,20)
imread(r'D:\4tiles.tiff', imread=read_with_pil).shape
From reading skimage docs, it's probably trying to interpret my image as RGBA and then fails.
Is there a solution to force 'uint16' multipage read for all image shapes?
Any advice is appreciated!
Based on cgohlke's comment:
from dask.array.image import imread
import numpy as np
from skimage import io
import tifffile
# fake data
img_with_4_tiles = np.random.randint(0,65535,(4,10,20), dtype='uint16')
with tifffile.TiffWriter(r'D:\4tiles.tiff') as tif:
for frame in img_with_4_tiles:
tif.save(frame)
# my original bad solution
def read_with_pil(path):
return io.imread(path, plugin='pil', mode='L')
print(imread(r'D:\4tiles.tiff', imread=read_with_pil).shape)
# a good solution from the horse's mouth (https://pypi.org/user/cgohlke/)
def read_with_tifffile(path):
return tifffile.imread(path, is_shaped=False)
print(imread(r'D:\4tiles.tiff', imread=read_with_tifffile).shape)
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?
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
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.
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
Using a (very) commonly used package is prefered:
import matplotlib.pyplot as plt
im = plt.imread('image.png')
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.
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()).
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
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]
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()