MATLAB: Applying transparent mask over an RGB image and blending with another

后端 未结 2 1724
长情又很酷
长情又很酷 2021-01-03 13:14

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 bac

相关标签:
2条回答
  • 2021-01-03 13:56

    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

    0 讨论(0)
  • 2021-01-03 13:56

    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...

    0 讨论(0)
提交回复
热议问题