Set alpha value to PyQtgraph ImageItem pixel by pixel

Viewed 29

I'm using PyQtgraph to display an image. In particular I'm displaying a bidimensional numpy array (where each point [i,j] is not color data, but just a single value) inside an ImageView, applying a color map to it.

Now I want to add an overlay to it, using as image data another bidimensional numpy array of the same type and size, again mapped to a color map.

I'd like to use different levels of transparency for the overlay, i.e. a different alpha value for each element [i, j] of the second numpy array, computed based on some function (which is not important for the sake of the question), so that the second image will be more or less visibile in different areas.

How could I achieve this? Thanks in advance.

1 Answers

You can use the opacity option (check the doc) in setImage method for setting the same alpha for every pixel (float number between 0.0 and 1.0).

For a pixel-per-pixel transparency definition, I've not found a valid way to append an alpha channel to a grayscale image. The easiest work around I found is to transform the image into a mock RGB and subsequently add the alpha channel:

my_fake_rgb_image = np.array([my_grayscale_image]*3 + [alpha_channel]).T

NOTE: The alpha channel value must be designed in the same range as the pixels. If your image is 8-bit (uint 0-255), the alpha channel must be a matrix for the same size as the image and with integer values between 0 and 255

NOTE2: [x]*3 + [y] is a shorthand for [x, x, x, y]

However, each ImageItem (the actual pyqtgraph item into ImageView that handles and displays the image) can handle one image at a time. What you need, is to implement an extra ImageItems into the same ViewBox, such as:

# Tailored on your comment
main_image_item = my_image_view.getImageItem()
main_image_item.setImage(my_np_image1)

view_box = my_image_view.getView()
second_image_item = pyqtgraph.ImageItem(my_np_image2, opacity=my_alpha2)
view_box.addImte(second_image_item)

NOTE 3: Pay extra-care when using the ImageView tools like the histogram, ROI etc., while handling two ImageItems instead of one.

A full working example follows, that generates two images made by orthogonal lines. The second image implement a random alpha value pixel-by-pixel:

import PySide2
from PySide2.QtWidgets import QApplication
import pyqtgraph as pg
from pyqtgraph import ViewBox, ImageItem, ImageView
import numpy as np


def generate_images():
    from PIL import Image, ImageDraw
    im1 = Image.new('L', (128, 128))
    im2 = Image.new('L', (128, 128))

    draw1 = ImageDraw.Draw(im1)
    draw1.line([0, 0, 128, 128], fill='white', width=10)

    draw2 = ImageDraw.Draw(im2)
    draw2.line([0, 128, 128, 0], fill='red', width=10)

    return np.array(im1), np.array(im2)


app = QApplication()
cm = pg.colormap.get('CET-D1')
iw = ImageView()
iw.setColorMap(cm)

main_image_item = iw.getImageItem()

image1, image2 = generate_images()

main_image_item.setImage(image1)

rand_alpha = np.random.random_sample((128, 128)) * 255

fake_rgb_image2 = np.array([image2]*3 + [rand_alpha]).T

overlayed_image_item = pg.ImageItem(fake_rgb_image2)
iw.addItem(overlayed_image_item)

iw.show()

app.exec_()

The result:

enter image description here

Edit1:

Modified the answer based on your comment

Related