Talumux
Talumux

Reputation: 68

How to stack multiple images on top of each other using python or matlab?

How can I stack multiple images and save the new output image using python (or matlab)? I need to set the alpha of each image and do i little translation, e.g.:

enter image description here

Upvotes: 2

Views: 6391

Answers (2)

Oliver W.
Oliver W.

Reputation: 13459

You could make such a stack of translated (shifted) images with Python, using the numpy and matplotlib module. Pillow (another Python module) by itself could probably do it as well, but I would have to look up how to ensure values of overlapping pixels get added, rather than overwritten.

So, here's a numpy + matplotlib solution, that starts off with a test image:

import numpy as np
import matplotlib.pyplot as plt

img1 = plt.imread('img.png')

For those following along, a very simply test image is shown at the end of this post, which will also serve to show the different options available for stacking (overwriting or additive which is weighted opacity with equal weights).

layers = 5  # How many images should be stacked.
x_offset, y_offset = 40, 20  # Number of pixels to offset each image.

new_shape = ((layers - 1)*y_offset + img1.shape[0],
             (layers - 1)*x_offset + img1.shape[1],
             4)  # the last number, i.e. 4, refers to the 4 different channels, being RGB + alpha

stacked = np.zeros(new_shape, dtype=np.float)


for layer in range(layers):
    stacked[layer*y_offset:layer*y_offset + img1.shape[0],
            layer*x_offset:layer*x_offset + img1.shape[1], 
            ...] += img1*1./layers
plt.imsave('stacked.png', stacked, vmin=0, vmax=1)

It's very simple really: you precalculate the size of the output image, initialize it to have full transparency and then you "drop" the base image in that file, each time offset by a certain offset vector. The interesting part comes when parts overlap. You then have some choices:

  • overwrite what was there before. In this case, change the += operator to simply =. Also, don't scale by the number of layers.
  • add in a weighted fashion. You should rescale all the intensity values in each channel by a certain weight (equal importance was taken in the example above) and then add those values. It is possible, depending a.o. on the weights, that you saturate pixels. You have the option then to clip the array (thereby resulting in loss of information) or simply rescale everything by the newly obtained maximum value. The example above uses clipping by specifying vmin and vmax in the call to imsave.

The test image shown here contains 4 transparent squares, but those are not easily distinguished from the 2 white ones in the top left row. They were added to illustrate the transparency addition and effect of rescaling (white becomes gray).

enter image description here

After running the above code, you end up with something like this (change your offsets though) ("add") enter image description here or like this ("overwrite") enter image description here

There are a few more ways you can think of that reflect what you want to do when pixels overlap. The 2 situations here are probably the most common ones though. In any case, the approach laid out here should give you a good start.

Upvotes: 1

bla
bla

Reputation: 26069

here's an example based on my comment:

mask=zeros(50,50,5); 
for n=1:size(mask,3)
    mask(randi(20):randi(20)+20,randi(20):randi(20)+20,n )=1;
    mask(:,:,n)=  bwperim( mask(:,:,n),8);
end

A=permute(mask,[3 2 1]); 
% plottning
h=slice(A,[],1:5,[]);
set(h,'EdgeColor','none','FaceColor','interp');
alpha(0.3);
colormap(flipud(flag))

enter image description here

Upvotes: 4

Related Questions