2

I have 2 images: a foreground and a background. The foreground is a matrix of numbers ranging from -50 to 300. I display it via imagesc. (I.e. this is no RGB image). The background is a RGB image.

I want to first apply a transparency mask on the foreground to alter it's appearance. This is easy enough by using

altered_foreground = imagesc(foreground, 'AlphaData', Alphamask)

Now, I want to superimpose the altered_foreground on top of the background. The problem is that since I've already used the Alphamask on the foreground, I can't superimpose it via:

imagesc(background)
hold on
bimage = imagesc(altered_foreground)
set(bimage, 'AlphaData', altered_foreground)

(doesn't work compared to if I just want to superimpose an unaltered foreground on background where I would use:

imagesc(background)
hold on
bimage = imagesc(foreground)
set(bimage, 'AlphaData', foreground)

Any ideas?

EDIT

Here is an example of data:

Foreground:


(source: gawkerassets.com)

Download the image; Type the following code to process it:

Foreground = im2double(imread('500x_54.jpg'));
Foreground = Foreground + 50*randn(101,1);

My altered foreground can be something simple like making the first 100 columns of the image to be fully transparent (in reality, it's a bit more complicated, I threshold the values and stuff like that)

Background:

Likewise, download the image and type:

Background = imread('2-effect1-500x225.jpg');
Glorfindel
  • 21,988
  • 13
  • 81
  • 109
Briandmg
  • 57
  • 1
  • 7
  • Take a look at this. http://stackoverflow.com/q/25011048/3839249 Still looking into your problem. – Yvon Aug 15 '14 at 04:27
  • Ah that guy is lucky enough to have his foreground hold values in a fixed range of numbers. My foreground values are variable, not necessarily fixed from -50 to 300. It's typically around there, but can go crazy from -100 to 1000 as well :/ – Briandmg Aug 15 '14 at 04:31
  • So you're suggesting normalize my foreground into RGB values, then overlaying it via the method shown in the link? – Briandmg Aug 15 '14 at 04:36
  • 1
    Done. It's a simple example but it should do. – Briandmg Aug 15 '14 at 05:01

2 Answers2

6

EDIT: Sorry for misunderstanding your question yesterday, so here is your full-colored version :P


The basic idea is almost the same as MATLAB: Combine Two Grayscale Images With Different Alpha, but in your case some more maneuvers are needed to get the right stuff.

First, recreate your well-described situation with the provided samples

% load foreground image, and scale to [-50, 300]
Foreground = imread('500x_54.jpg');
figure(1)
imshow(Foreground)
Foreground = im2double(Foreground)*350-50;

% load background image
Background = im2double(imread('2-effect1-500x225.jpg'));
figure(2)
imshow(Background)

Then make an alpha channel from scratch. Note that I'm not using imagesc but writing a plain double array. This is indeed an alpha channel! Doesn't need so much mysteries.

% build alpha layer for Foreground
alpha = bsxfun(@times, ones(size(Foreground,1), size(Foreground,2)), .6);
alpha(:,[1:53,149:203,290:352,447:end])=0;
alpha([1:58,170:end],:)=0;
figure(3)
imshow(alpha)

Before blending, I want to scale the foregrond "back" into [0,1]. Since the background image is freshly loaded from a regular picture, it doesn't need normalizing; only the foreground ranging from -50 to 300 does.

The problem is sometimes you have crazy data like -100 or 1000. I don't know how you want to interpret them. If you take [-50. 300] as the regular, typical, should-be range, then how do you map -100 or 1000 into the color level?

There are 2 options / methods to handle this condition: 1) Use [-100, 1000] as a new scale. So -100 will be pure black and 1000 pure color; 2) Keep using [-50, 300] as the scale range, so all stuff out of this range will be mapped (coerced) to the nearest border.

Here I choose the first one, with an adaptive mechanism that limits the range at least [-50, 300]. So if your data go like [-10,200], you still get the scale [-50, 300]. I think this makes more sense.

% find a scale dynamically with some limit
Foreground_min = min( min(Foreground(:)), -50 );
Foreground_max = max( max(Foreground(:)), 300 );

The blending procedure is almost the same as that post. But you are using RGB images, so you'll need to add the numbers for all of the 3 color layers; bsxfun is used to replace the slower + and .* operations.

% overlay the image by blending
Background_blending = bsxfun(@times, Background, bsxfun(@minus,1,alpha));
% Background_blending = Background.*repmat((1-alpha), 1, 1, 3);
Foreground_blending = bsxfun( @times, bsxfun( @rdivide, ...
    bsxfun(@minus, Foreground, Foreground_min), ... 
    Foreground_max-Foreground_min ), alpha );
% Foreground_blending = (Foreground-Foreground_min) / ...
%     (Foreground_max-Foreground_min).*repmat(alpha, 1, 1, 3);
% out = bsxfun(@plus, Background_blending, Foreground_blending);
out = Background_blending + Foreground_blending;
figure(4)
imshow(out)

The commented lines except the first one are "regular" assigning commands without using bsxfun, but do the same job, and are easier to understand :)

Result

result

Community
  • 1
  • 1
Yvon
  • 2,903
  • 1
  • 14
  • 36
  • This is good. But if I want to retain the colour? Replacing imshow(...) with imagesc(...) doesn't seem to work – Briandmg Aug 15 '14 at 06:29
  • @Briandmg `imagesc` does not satisfy your need, since it is a _color mapping_ tool that maps single-value color index into indexed color. That's _false color_. – Yvon Aug 15 '14 at 06:37
  • Do you mean "color" blending mode in this page? http://www.northlite.net/ps/blend.htm Then that's a little different story. – Yvon Aug 15 '14 at 07:12
  • 1
    Oh sorry. I guess I was a bit ambiguous in the question. When I said the foreground was "no RGB image", I meant more of that the values weren't in uint8 form (all double values). I used imagesc's false color imaging to force the values for imaging. In this case, by "retain the colour", I mean more of applying the dissolve effect you gave in the northlite linky to the foreground. So the 3 Mario characters should be dissolved (with their colours still in place), but you can still see the background behind them. – Briandmg Aug 15 '14 at 07:47
  • Yes, both the foreground and background is still a coloured image. Sorry for the misunderstanding :( – Briandmg Aug 15 '14 at 08:12
  • @Briandmg I was also responsible for our miscommunication. I've updated my answer. Please take a look. – Yvon Aug 15 '14 at 15:43
  • Thank you! You have been most helpful :) – Briandmg Aug 18 '14 at 00:53
3

Coming late to the show, but still think to have some useful information for others finding this thread, like I found the thread myself searching for some solution. Well I finally ended up to simply use the build in function imlincomb() for blending RGB images, which I fortunately have access to by using the Image Processing Toolbox. Anyway, I also voted for the answer of Yvon, because not everybody has the IPT and will learn a lot from that answer.

OUT = imlincomb(scalaralphavalue, FOREGROUNDIMAGE, (1-scalaralphavalue), BACKGROUNDIMAGE)

This gives the same result as using something based on this basic code:

OUT = FOREGROUND .* ALPHA  + BACKGROUND .* (1-ALPHA)

If not working with indexed RGB files, but with intensity values, then you might want to consider some proper scaling of the intensity values, for instance into the range from 0 to 1 by doing this:

ARRAY= (ARRAY - min(ARRAY(:))) / (max(ARRAY(:)) - min(ARRAY(:)))

Well, adjust this to your needs...

Talby
  • 65
  • 5