Qimage Grayscale Format Indexed8

qimage2ndarray is a small python package for quickly convertingbetween QImages and numpy.ndarrays (in both directions). These arevery common tasks when programming e.g. scientific visualizations inPython using PyQt4 as the GUI library.

That assumes I be want to do the math for every Format. Of Qt::red Qt::green Qt::blue or Qt::gray QImage out(image.width, image.height. For indexed8 QVector values; values.reserve(256); if.

Similar code was found in Qwt and floating around on mailing lists,but qimage2ndarray has the following unique feature set:

  • Supports conversion of scalar and RGB data, with arbitrary dtypesand memory layout, with and without alpha channels, into QImages(e.g. for display or saving using Qt).

  • qimage2ndarray makes it possible to create ndarrays that areviews into a given QImage’s memory.

    This allows for very efficient data handling and makes it possibleto modify Qt image data in-place (e.g. for brightness/gamma or alphamask modifications).

  • qimage2ndarray is stable and unit-tested:

    • proper reference counting even with views (ndarray.base points tothe underlying QImage)

    • handles non-standard widths and respects QImage’s 32-bit rowalignment

    • tested with Python 2 and Python 3, and various Qt wrappers

  • Masked arrays are also supported and are converted into QImageswith transparent pixels.

  • Supports recarrays (and comes with an appropriate dtype) forconvenient access to RGB(A) channels (see recarray_view()).

  • Supports value scaling / normalization to 0.255 for convenientdisplay of arbitrary NumPy arrays.

  • Recent additions are convenient image loading / saving methods.

qimage2ndarray works with both Python 2.x and Python 3.x on all majorplatforms, and with different Python wrappers of Qt (PyQt4 and PyQt5,PySide, PySide2 and PythonQt). The package is open source,BSD-licensed, and the repository can be browsed online or clonedusing Git:

Changelog¶

Version 1.8.3:
  • fix normalization potentially modifying input array

Version 1.8.2:
  • normalize boolean arrays to 0/255 by default

Version 1.8.1:
  • support normalization of boolean arrays

Version 1.8:
  • improve exception when calling imread on non-existing file

  • improved pure-python implementation working with PythonQt as well

Version 1.7:
  • add support for PySide2

  • changed default driver from PyQt4 to PyQt5

Version 1.6:
  • finally, also support PySide on Python 3 (closing last known issue)

Version 1.5.1:
  • small installation and documentation fixes

Version 1.5:
  • PyQt5 support

Version 1.4:
  • pure python version of qimage2ndarray

  • PySide support (Python 2 only yet)

  • added imsave()

Version 1.3.1:
  • restored compatibility with NumPy 1.6 (lost in 1.2)

Version 1.3:
  • added imread()

  • added implicit loading in view functions

Version 1.2:
  • support Python 3.x (in addition to Python 2.x, same codebase)

  • adapted to NumPy 1.7 API

  • move documentation away from uni-hamburg.de, too

Version 1.1:
  • gracefully handle empty normalization range

  • improved compilation support (on Windows and OS X)

  • small optimizations

  • support alternative Qt bindings (PythonQt, used by MeVisLab)

  • update URLs/email to move away from uni-hamburg.de

Version 1.0:
  • Let array2qimage support 2 channels (gray + alpha)

  • Fixed installation on OS X (where Qt libs come as “Frameworks”)

Version 0.2:
  • Fixed endianness issues (tested on PowerPC arch)

  • Simplified installation on Windows (e.g. with Qt DLLs bundled with PyQt)

Version 0.1:
  • Initial Relase

Usage¶

There are two opposite directions of conversion, discussed in the nextsubsections:

  1. Converting QImages into numpy.ndarrays.

  2. Converting ndarrays into QImages.

The first task is supported by a family of functions that createviews into the corresponding QImage memory, while the second taskwill always copy the image data (usually converting it into theappropriate type or value range).

Note

The reason for this is that ndarrays are much more flexible thanQImages, and while it is possible – even using pure python – tocreate QImages that are views into an ndarray’s memory, this willonly work if the latter fulfills certain strict requirementsw.r.t. dtype, strides / memory layout etc. Thus, you’d needfunctions that set up a properly convertible ndarray, which makesthis less convenient. Moreover, it is then a logical next step tolet QImage set up and manage the memory and instead create ndarrayviews.

Converting QImages into numpy.ndarrays¶

QImages can be viewed as recarrays usingrecarray_view(), as uint8-valued array using rgb_view(),alpha_view(), or just byte_view(), or as raw 2D arrayusing raw_view().

recarray_view(qimage)

Returns recarray view of a given 32-bit color QImage’smemory.

The result is a 2D array with a complex record dtype, offering thenamed fields ‘r’,’g’,’b’, and ‘a’ and corresponding long names.Thus, each color components can be accessed either via stringindexing or via attribute lookup (through numpy.recarray):

For your convenience, qimage may also be a filename, seeLoading and Saving Images in the documentation.

Parameters

qimage (QImage with 32-bit pixel type) – image whose memory shall be accessed via NumPy

Return type

numpy.ndarray with shape (height, width) and dtype bgra_dtype

bgra_dtype = dtype([(('blue', 'b'), 'u1'), (('green', 'g'), 'u1'), (('red', 'r'), 'u1'), (('alpha', 'a'), 'u1')])

Complex dtype offering the named fields ‘r’,’g’,’b’, and ‘a’ andcorresponding long names, conforming to QImage’s 32-bit memory layout.

rgb_view(qimage)

Returns RGB view of a given 32-bit color QImage’s memory.Similarly to byte_view(), the result is a 3D numpy.uint8 array,but reduced to the rgb dimensions (without alpha), and reordered(using negative strides in the last dimension) to have the usual[R,G,B] order. The image must have 32 bit pixel size, i.e. beRGB32, ARGB32, or ARGB32_Premultiplied. (Note that in the lattercase, the values are of course premultiplied with alpha.)

The order of channels in the last axis depends on the byteorder,which defaults to ‘big’, i.e. RGB order. You may set the argumentbyteorder to ‘little’ to get BGR, or use None which meanssys.byteorder here, i.e. return native order for the machine thecode is running on.

For your convenience, qimage may also be a filename, seeLoading and Saving Images in the documentation.

Parameters
  • qimage (QImage with 32-bit pixel type) – image whose memory shall be accessed via NumPy

  • byteorder – specify order of channels in last axis

Return type

numpy.ndarray with shape (height, width, 3) and dtype uint8

alpha_view(qimage)

Returns alpha view of a given 32-bit color QImage’s memory.The result is a 2D numpy.uint8 array, equivalent tobyte_view(qimage)[…,3]. The image must have 32 bit pixel size,i.e. be RGB32, ARGB32, or ARGB32_Premultiplied. Note that it isnot enforced that the given qimage has a format that actuallyuses the alpha channel – for Format_RGB32, the alpha channelusually contains 255 everywhere.

For your convenience, qimage may also be a filename, seeLoading and Saving Images in the documentation.

Parameters

qimage (QImage with 32-bit pixel type) – image whose memory shall be accessed via NumPy

Return type

numpy.ndarray with shape (height, width) and dtype uint8

byte_view(qimage)

Returns raw 3D view of the given QImage’s memory. This willalways be a 3-dimensional numpy.ndarray with dtype numpy.uint8.

Note that for 32-bit images, the last dimension will be in the[B,G,R,A] order (if little endian) due to QImage’s memory layout(the alpha channel will be present for Format_RGB32 images, too).

For 8-bit (indexed) images, the array will still be 3-dimensional,i.e. shape will be (height, width, 1).

The order of channels in the last axis depends on the byteorder,which defaults to ‘little’, i.e. BGRA order. You may set theargument byteorder to ‘big’ to get ARGB, or use None which meanssys.byteorder here, i.e. return native order for the machine thecode is running on.

For your convenience, qimage may also be a filename, seeLoading and Saving Images in the documentation.

Parameters
  • qimage (QImage) – image whose memory shall be accessed via NumPy

  • byteorder – specify order of channels in last axis

Return type

numpy.ndarray with shape (height, width, 1 or 4) and dtype uint8

raw_view(qimage)

Returns raw 2D view of the given QImage’s memory. The resultwill be a 2-dimensional numpy.ndarray with an appropriately sizedintegral dtype. (This function is not intented to be useddirectly, but used internally by the other – more convenient –view creation functions.)

Parameters

qimage (QImage) – image whose memory shall be accessed via NumPy

Return type

numpy.ndarray with shape (height, width)

Converting ndarrays into QImages¶

array2qimage(array[, normalize])

Convert a 2D or 3D numpy array into a 32-bit QImage. Thefirst dimension represents the vertical image axis; the optionalthird dimension is supposed to contain 1-4 channels:

#channels

interpretation

1

scalar/gray

2

scalar/gray + alpha

3

RGB

4

RGB + alpha

Scalar data will be converted into corresponding gray RGB triples;if you want to convert to an (indexed) 8-bit image instead, usegray2qimage (which cannot support an alpha channel though).

The parameter normalize can be used to normalize an image’svalue range to 0.255:

normalize = (nmin, nmax):

scale & clip image values from nmin.nmax to 0.255

normalize = nmax:

lets nmin default to zero, i.e. scale & clip the range 0.nmaxto 0.255

normalize = True:

scale image values to 0.255 (same as passing (gray.min(),gray.max()), except for boolean arrays, where False/Trueare mapped to 0/255)

If array contains masked values, the corresponding pixels willbe transparent in the result. Thus, the result will be ofQImage.Format_ARGB32 if the input already contains an alphachannel (i.e. has shape (H,W,4)) or if there are masked pixels,and QImage.Format_RGB32 otherwise.

Parameters
  • array (2D or 3D numpy.ndarray or numpy.ma.array) – image data which should be converted (copied) into a QImage

  • normalize (bool, scalar, or pair) – normalization parameter (see above, default: no value changing)

Return type

QImage with RGB32 or ARGB32 format

gray2qimage(gray[, normalize])

Convert the 2D numpy array gray into a 8-bit, indexed QImagewith a gray colormap. The first dimension represents the verticalimage axis.

The parameter normalize can be used to normalize an image’svalue range to 0.255:

normalize = (nmin, nmax):

scale & clip image values from nmin.nmax to 0.255

normalize = nmax:

lets nmin default to zero, i.e. scale & clip the range 0.nmaxto 0.255

normalize = True:

scale image values to 0.255 (same as passing (gray.min(),gray.max()), except for boolean arrays, where False/Trueare mapped to 0/255)

If the source array gray contains masked values, the result willhave only 255 shades of gray, and one color map entry will be usedto make the corresponding pixels transparent.

A full alpha channel cannot be supported with indexed images;instead, use array2qimage to convert into a 32-bit QImage.

Parameters
  • gray – image data which should be converted (copied) into a QImage

  • normalize (bool, scalar, or pair) – normalization parameter (see above, default: no value changing)

Return type

QImage with RGB32 or ARGB32 format

Loading and Saving Images¶

There are two ways to read images from disk directly into ndarrays:

  1. The imread() function mimicks existing API in otherlibraries, returning an ndarray whose dimensionality and shapedepends on whether the image is a color or grayscale image.

  2. Also, the view functions (all five of them) can be passed afilename instead of a qimage. This can be more useful thanimread(), e.g. in case you want to get a recarray(recarray_view()), just the alpha channel(alpha_view()), or the original ARGB image data(byte_view()).

imread(filename)

Convenience function that uses the QImage constructor to read animage from the given file and return an rgb_view of the result.This is intentionally similar to scipy.ndimage.imread (which usesPIL), scipy.misc.imread, or matplotlib.pyplot.imread (using PILfor non-PNGs).

For grayscale images, return 2D array (even if it comes from a 32-bitrepresentation; this is a consequence of the QImage API).

For images with an alpha channel, the resulting number of channelswill be 2 (grayscale+alpha) or 4 (RGB+alpha). Alternatively, one maypass masked = True in order to get masked arrays back.Note that only fully transparent pixels are masked(and that masked arrays only support binary masks). The value ofmasked is ignored when the loaded image has no alpha channel(i.e., one would not get a masked array in that case).

This function has been added in version 1.3.

Finally, there is also a tiny wrapper around array2qimage() andQImage.save() for saving images to disk:

imsave(filename, array[, normalize])

Convenience function that uses QImage.save to save an image to thegiven file. This is intentionally similar to scipy.misc.imsave.However, it supports different optional arguments:

Parameters
  • normalize – see array2qimage() (which is used internally)

  • format – image filetype (e.g. ‘PNG’), (default: check filename’s suffix)

  • quality – see QImage.save (0 = small . 100 = uncompressed, -1 = default compression)

Returns

boolean success, see QImage.save

This function has been added in version 1.4.

About QtOpenCV

  • QtOpenCV provides some helper functions to converting cv::Mat from/to QImage.

  • QtOpenCV provides a opencv.pri file which can be used to integrate OpenCV2 or newer to qmake-based project.

cv::Mat <> QImage

  • Download and copy the cvmatandqimage.cppcvmatandqimage.h and opencv.pri to your project's source tree.

  • Then take advantage of the following API to converting data between Cv::Mat and QImage.

  • In addition, two other functions are provided which works more efficient when operating on CV_8UC1, CV_8UC3(R G B)CV_8UC4(R G B A), CV_8UC4(B G R A) or CV_8UC4(A R G B).

OpenCV2 Integration

If your want to use OpenCV in your qmake based project, you can download and put the source files to any directory you wanted,then add following code to your .pro file.

or you can simply add following line to your .pro file:

As you can see, nothing else needed to do for non-windows users.

Notes for Windows User

To make opencv.pri works for your, you need to create an opencv.prf file, then move the .prf file to %QTDIR%/mkspecs/features/.

Method 1: Create and copy the opencv.prf by hand

You can use a textedit to create the .prf file. The contents of .prf file more or less looks like this:

Then you can copy it to %QTDIR%/mkspecs/features/.

Method 2: Take use of the helper script

If you have installed python, the helper script opencv_prf_generator.py can be used to generate and install the opencv.prf file.

Some thing you need to know

Channels order of OpenCV's image which used by highgui module is B G R and B G R A

The manual of OpenCV says that,

  • cv::imwrite()

Only 8-bit (or 16-bit unsigned(CV_16U) in case of PNG,JPEG2000,and TIFF) single-channel or 3-channel(with 'BGR' channel order) images can be saved using this function.

It is possible to store PNG images with an alpha channel using this function. To do this, create 8-bit (or 16-bit) 4-chanel image BGRA, where the alpha channel goes last.

  • cv::imread()

In the case of color images, the decoded images will have the channels stored in B G R order .

Note: If you don't care opencv_highgui module, you can always use the same channels order as QImage, which will be slightly fast.

Data bytes order of QImage

  • In Little Endian System
  • Ins Big Endian System

How to swap channels?

  • In OpenCV
  • In Qt

Swap r and b channel of QImage

If the depth of the image is 32, the following function can be used too.

EziView Software Application for Meter Configuration EziView allows customers to check meter installations locally or remotely. It provides the communications link to the EDMI family of meters and is specifically used to configure and retrieve data from them. This software through a schedular, allows automatic data reading at a present time. Edmi multidrive software.

Common Image Data Range of OpenCV