问题
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');
回答1:
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
回答2:
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...
来源:https://stackoverflow.com/questions/25321211/matlab-applying-transparent-mask-over-an-rgb-image-and-blending-with-another