How to overlay two images with opacity

I have a simple problem, I want to overlay two rgb images (np.arrays with three channels and same size) over each other, with opacity setting for the top so I can see both.

fig_visual_check = go.Figure()
fig_visual_check = fig_visual_check.add_trace(go.Image(z=images_merged_visual[0], opacity=0.5))
fig_visual_check = fig_visual_check.add_trace(go.Image(z=images_merged_visual[1], opacity=1))

fig_visual_check

However, the result is just a black image.
If I switch the order of opacities, I get only the bottom image (half dimmed), but the top image is not shown.
Do you have an idea how to do it?
Thanks!

Hi @Madrigallo maybe something with your images? I tried this:

import plotly.graph_objects as go
import PIL.Image as Image

images = []
for i, color in zip(range(2), ['red', 'blue']):
    # create some png files
    fig = go.Figure(go.Scatter(x=np.arange(10), y=np.random.randint(2,10,10), mode='markers+lines', marker_color=color))
    fig.write_image(f'fig_{i}.png')
    
    # open files with PIL
    images.append(Image.open(f'fig_{i}.png').convert("RGBA"))

# create base figure
fig = go.Figure(data=go.Image(z=images[0]), layout={'height': 800, 'width': 800})

# add trace
fig.add_trace(go.Image(z=images[1], opacity=0.1))
fig.show()


mrep PIL

I’m trying to overlay two images with transparency. Following code produces error

import plotly.graph_objects as go
import plotly.express as px
import numpy as np

# Sample RGB images
asdf = np.full((50,50,3), 1, dtype=float)
jklu = np.full((50,50,3), 1, dtype=float)
jklu[10:20,:,2:] = jklu[10:20,:,2:] * 200
asdf[:,10:20,:1] = asdf[:,10:20,:1] * 100
px.imshow(jklu)
px.imshow(asdf)

# Create a figure
fig = go.Figure()

# Add the first image
fig.add_trace(go.Image(z=image1))

# Show the plot
fig.show()

javascript error: e.slice is not a function
Is that a bug?

…has never been defined in this code snippet.

Alright, sorry for the confusion. I realised I had some stray objects defined from before.
Just could you clarify for me what datatype should be passed to z argument in go.Image? It’s numpy array, with 1 or more channels, right?

HI there, happy you sorted it out.

Concerning the z argument: either an Image object (as in my example) or a numpy array with 3 or 4 channels. For gray scale images (1 channel) you can use the go.Heatmap() as go.Image() won’t work.

1 Like

Oooh so! That might be the reason why I was not seeing one of my images, since it was grayscale. So I’ll try combining go.Image and go.Heatmap. Thanks!

Edit: One more question, is there a good resource page where I could’ve read this information, that go.Image is for rgb and go.Heatmap should be used for grayscale instead? I feel there must be and I just missed it. I’m aware of all the API plotly documentation, but I think I didn’t find it there. Thanks!

Unfortunately I don’t know. I just found out responding to your question (adding/removing channels) I knew that go.Heatmap() only works with 2D arrays, so I figured that there might be a restriction to go.Image()too concerning the array shape.

import plotly.graph_objects as go
import numpy as np

image = go.Figure(data=go.Image(z=np.random.randint(0, 255, size=(20, 20, 3))), layout={'height': 800, 'width': 800})
image.show()

heatmap = go.Figure(data=go.Heatmap(z=np.random.randint(0, 255, size=(20, 20))), layout={'height': 800, 'width': 800})
heatmap.show()

@Madrigallo @AIMPED If someone is interested, in Image processing there is an operation called alpha-blending, i.e. two images of different alpha are overlayed. One is the background image, and another the foreground.
As example let us take the following two images:

bgimage

fgimage

 
import skimage.io as sio
import plotly.express as px
imgbg= sio.imread("bgimage.png")
figbg=px.imshow(imgbg, width=500, height=500)
figbg.update_layout(xaxis_visible=False, yaxis_visible=False)
figbg.show()

imgfg= sio.imread("fgimage.png")
figfg=px.imshow(imgfg, width=500, height=500)
figfg.update_layout(xaxis_visible=False, yaxis_visible=False)
alphabg= 0.3  # the parameter for the background image
alphafg = 0.9  # parameter for the foreground image 

#convex combination of the arrays representing the two images
blendarray = (alphabg * imgbg + alphafg*(1-alphabg)* imgfg)/(alphabg+alphafg*(1-alphabg))

blendimg=px.imshow(blendarray)
blendimg.update_layout(xaxis_visible=False, yaxis_visible=False)

And this is the blended image:

A similar  alpha-blending can be performed on the z-arrays representing two heatmaps.

Matplotlib has implemented alpha-blending, in imshow.
3 Likes

Hey @empet, thanks for the insight, really interesting!

1 Like

Thanks a ton, @empet !