Display Images from Disk, either list of files or large binary file

116 views
Skip to first unread message

Dennis Norton

unread,
Oct 29, 2018, 12:50:41 AM10/29/18
to pyqtgraph
I'm wondering if there is a convenient way to use the ImageView class to display images either from a list of files in a directory or from a large binary file consisting of multiple frames.

Could we create a generator which yields the numpy arrays to display?

Thanks.

Patrick

unread,
Oct 30, 2018, 12:47:05 AM10/30/18
to pyqtgraph
Hi,

You can load images into numpy arrays (usable by ImageItem, ImageView etc) using the scipy.ndimage.imread function. I think it relies on having the Python Image Library (PIL) installed. A more modern version of that library is Pillow, which you could also use to load image data.

Limitations are though that the ImageView expects each image to have the same dimensions.

Simple modification of ImageView example to demonstrate (specify your image files on command line).

#!/usr/bin/env python3


import numpy as np
from pyqtgraph.Qt import QtCore, QtGui
import pyqtgraph as pg
from argparse import ArgumentParser
from scipy.ndimage import imread

argparser
= ArgumentParser(description='Load images and display using pyqtgraph ImageView widget.')
argparser
.add_argument('input_images', help='Input filename(s) of images', nargs='+')
args
= argparser.parse_args()

imagelist
= []
for filename in args.input_images:
   
print("Loading {}...".format(filename))
    image
= imread(filename)
    imagelist
.append(image)
   
print('Image shape: {}{}'.format(imagelist[len(imagelist)-1].shape, '' if imagelist[len(imagelist)-1].shape == imagelist[0].shape else ' *'))
data
=np.stack([ i for i in imagelist if i.shape==imagelist[0].shape ], 0)
if len(args.input_images) != data.shape[0]:
   
print('Warning: Shape of all input files must match. Those marked with * are skipped.')

# Interpret image data as row-major instead of col-major
pg
.setConfigOptions(imageAxisOrder='row-major')

app
= QtGui.QApplication([])

## Create window with ImageView widget
win
= QtGui.QMainWindow()
win
.resize(800,800)
imv
= pg.ImageView()
win
.setCentralWidget(imv)
win
.show()
win
.setWindowTitle('pyqtgraph example: ImageView')

## Display the data
imv
.setImage(data)

## Set a custom color map
colors
= [
   
(0, 0, 0),
   
(45, 5, 61),
   
(84, 42, 55),
   
(150, 87, 60),
   
(208, 171, 141),
   
(255, 255, 255)
]
cmap
= pg.ColorMap(pos=np.linspace(0.0, 1.0, 6), color=colors)
imv
.setColorMap(cmap)

## Start Qt event loop unless running in interactive mode.
if __name__ == '__main__':
   
import sys
   
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
       
QtGui.QApplication.instance().exec_()

Dennis Norton

unread,
Oct 30, 2018, 8:29:55 PM10/30/18
to pyqt...@googlegroups.com
Thanks, Patrick.

I should have been more explicit about what I was asking.  The method you outlined I was aware of.

What I'm asking has to do if you have such a large number of files or a single file that is so large it can't be (or is impractical to be) read into memory.

The idea I tried, and works thus far is to use a numpy memmap object.

So imagine a file "VeryLargeImageFile.img", which consists of the binary data of type unsigned integer (uint16).  Let's say this was captured with a camera of format frame shape (512,640), and there are 10,000 frames stored in the file.

fp = np.memmap('VeryLargeImageFile.img', dtype='unt16', mode='r',
                        offset=0, shape=(10000,512,640))
        
The variable can be passed to ImageView item by imv.setImage(fp).

However, for 32-bit operating systems, fp would still be limited to 2Gb.

So my real question is if there is a method to pass a generator which reads a frame at a time to the ImageView or, if I had a large list of binary files, could I create a generator which will cycle through reading each file and return a numpy array of the data read for each file.

Is what I'm asking making more sense, now?  If not, let me know and I'll try to clarify by uploading my current code.

Thanks again.

-Dennis

--
You received this message because you are subscribed to a topic in the Google Groups "pyqtgraph" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/pyqtgraph/1PuRof6NA5w/unsubscribe.
To unsubscribe from this group and all its topics, send an email to pyqtgraph+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/pyqtgraph/d1681786-8d9c-4a97-a3b5-78f32223e481%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


--
-Dennis


Patrick

unread,
Oct 31, 2018, 8:32:17 PM10/31/18
to pyqtgraph
Hi Dennis,

Yes, that makes sense now... and unfortunately I can't see an easy way to plumb that into the ImageView widget. An idea though, if you look at the code for ImageView (http://www.pyqtgraph.org/documentation/_modules/pyqtgraph/imageview/ImageView.html#ImageView.setImage) the image provided does not strictly need to be an numpy array (just needs certain attributes), so perhaps you could make a shim class which extends/mimics a numpy ndarray, catching calls to these attributes and mapping to the appropriate disk image file.
Of course, maybe someone has already made something like this... http://docs.dask.org/en/latest/array.html looks interesting, though I've never used it.

Good luck!
Patrick

Dennis Norton

unread,
Oct 31, 2018, 10:19:07 PM10/31/18
to pyqt...@googlegroups.com
Thanks again for your response.

I did think about creating a custom class which would have the attributes ImageView is looking for, or just create a custom ImageView-esque class which would handle a generator.

I'll look into the array link you sent.

Best regards.


For more options, visit https://groups.google.com/d/optout.


--
-Dennis


Aaron Adamson

unread,
Nov 1, 2018, 9:10:14 AM11/1/18
to pyqtgraph
Another option - you can possibly embed your data in an hdf5 file, and then read / downsample the hdf5 file on demand based on your range settings. You can look at the "HDF5 big data" example in pyqtgraph.examples to see it done with a line plot. I am working on a similar problem, and will post an example if I get a good solution.

Sebastian Höfer

unread,
Nov 8, 2018, 6:22:17 AM11/8/18
to pyqtgraph
The most convenient way I used in the past where memory mapped files. Numpy supports memmapped arrays that (in most cases) behave just like regular ndarrays.
https://docs.scipy.org/doc/numpy-1.15.1/reference/generated/numpy.memmap.html

We used it to store raw video data with hundreds/thousands of frames and display them in an ImageView. Of course you're at the whims of your Operating system and numpy to handle the on-the-fly loading efficiently, but it's a quick and easy way to handle big amounts of data without additional libraries and self-made solutions.

Regards,
Sebastian
Reply all
Reply to author
Forward
0 new messages