how to combine 2 pictures in Matlab, fuji writing on mount fuji note: the background of the writing of fuji is transparent.

4 次查看(过去 30 天)
  4 个评论
Rahmat Anbi Ancing
Rahmat Anbi Ancing 2022-10-27
编辑:Rahmat Anbi Ancing 2022-10-27
There are 2 pictures of Mount Fuji and an image of Fuji writing on a pink background. I want to combine the image with the words Fuji on Mount Fuji with a transparent Fuji writing background. so the result will be an image of Mount Fuji with Fuji writing on it.
@DGM sorry i uploaded the picture

请先登录,再进行评论。

回答(1 个)

DGM
DGM 2022-10-27
编辑:DGM 2022-10-28
There are many different ways to approach this based on the details of what's required.
The typical recommendation is to simply stack the images in a figure.
% SIMPLE IN-FIGURE COMPOSITION
% foreground image is RGB, antialiased
FG = imread('Fuji.jpg');
BG = imread('Gunung.jpg');
% calculate subscripts for FG placement
offset = [-150 -50]; % offset from center [y x] (px)
sfg = [size(FG,1) size(FG,2)];
sbg = [size(BG,1) size(BG,2)];
os = min(max(round((sbg-sfg)/2 + offset),1),sbg-sfg);
y = [os(1) os(1)+sfg(1)-1];
x = [os(2) os(2)+sfg(2)-1];
% display the images
imshow(BG); hold on
hi2 = imshow(FG,'xdata',x,'ydata',y);
hi2.AlphaData = 0.5;
While that allows for simple scalar alpha blending, I consider it bad practice to treat display tools as compositing tools. This is equivalent to taking a screenshot of your work in Photoshop. If you want to save or use the results, it's a needlessly destructive and poorly-controlled workflow.
I prefer to perform image composition on the images themselves. This can be simple, or it can be complicated. Let's start simple. The most basic thing you could do is to just directly insert one image into another. Since they're both rectangular, simple addressing suffices.
% DIRECT INSERTION
% foreground image is RGB, antialiased
FG = imread('Fuji.jpg');
BG = imread('Gunung.jpg');
% calculate subscripts for FG placement
offset = [-150 -50]; % offset from center [y x] (px)
sfg = [size(FG,1) size(FG,2)];
sbg = [size(BG,1) size(BG,2)];
os = min(max(round((sbg-sfg)/2 + offset),1),sbg-sfg);
rows = os(1):os(1)+sfg(1)-1;
cols = os(2):os(2)+sfg(2)-1;
% insert the FG into the result
outpict = BG;
outpict(rows,cols,:) = FG;
imshow(outpict)
That's probably not what you wanted, but it demonstrates the core of the addressing task.
The foreground opacity can be adjusted by doing a simple alpha blend.
% SIMPLE SCALAR ALPHA COMPOSITION
% foreground image is RGB, antialiased
FG = imread('Fuji.jpg');
BG = imread('Gunung.jpg');
% calculate subscripts for FG placement
offset = [-150 -50]; % offset from center [y x] (px)
sfg = [size(FG,1) size(FG,2)];
sbg = [size(BG,1) size(BG,2)];
os = min(max(round((sbg-sfg)/2 + offset),1),sbg-sfg);
rows = os(1):os(1)+sfg(1)-1;
cols = os(2):os(2)+sfg(2)-1;
% extract a BG region in the ROI
roisample = BG(rows,cols,:);
% do a simple scalar alpha blend
alpha = 0.5;
roisample = im2uint8(alpha*im2double(FG) + (1-alpha)*im2double(roisample));
% insert the modified sample into the result
outpict = BG;
outpict(rows,cols,:) = roisample;
imshow(outpict)
That's better, but the sparsity of the FG object content (the text) makes the FG matting (the pink area) stick out like a sore thumb. While this example adjusts FG opacity with a scalar factor applied to the entire image, it's often desired to have more control over which regions within the image are transparent.
Let's say we don't want the pink matting or the Nama Kulo logo at all. How could we exclude those so that we just have the word "Fuji" with adjustable transparency? This is where it starts to get difficult. The text in the FG image is nicely antialiased. That makes it look nice, but it makes it difficult to select neatly. I'm sure the common suggestion will be to simply do a color-based thresholding operation to generate a mask. The problem is that a logical mask cannot preserve antialiased edges. It will either overselect (leaving jagged pink edges) or underselect (making the letters jagged and skinny).
% NAIVE LOGICAL MASKED COMPOSITION
% foreground image is RGB, antialiased
FG = imread('Fuji.jpg');
BG = imread('Gunung.jpg');
% calculate subscripts for FG placement
offset = [-150 -50]; % offset from center [y x] (px)
sfg = [size(FG,1) size(FG,2)];
sbg = [size(BG,1) size(BG,2)];
os = min(max(round((sbg-sfg)/2 + offset),1),sbg-sfg);
rows = os(1):os(1)+sfg(1)-1;
cols = os(2):os(2)+sfg(2)-1;
% extract a BG region in the ROI
roisample = BG(rows,cols,:);
% use some terrible HSV masking to isolate the text from the FG matting
% this ruins any antialiasing and will necessarily either overselect or underselect
L = [0 1; 0 0.131; 0.929 1];
FGhsv = rgb2hsv(FG);
mask = ((FGhsv(:,:,1) >= L(1,1)) & (FGhsv(:,:,1) <= L(1,2))) & ...
((FGhsv(:,:,2) >= L(2,1)) & (FGhsv(:,:,2) <= L(2,2))) & ...
((FGhsv(:,:,3) >= L(3,1)) & (FGhsv(:,:,3) <= L(3,2)));
% combine the scalar alpha blend and logical comp into a single operation
alpha = 0.8;
alpha = alpha * double(mask);
roisample = im2uint8(alpha.*im2double(FG) + (1-alpha).*im2double(roisample));
% insert the modified sample into the result
outpict = BG;
outpict(rows,cols,:) = roisample;
imshow(outpict)
While this is a fairly forgiving example due to the relative size of the text, it's still not a great method. It gets recommended because it's the hammer that's at hand.
Why can't we just make the FG variably transparent based on its "pinkness"? We can, but we'd have to graduate to third-party tools (or reinvent that wheel ourselves). MIMT color2alpha() takes an RGB image and a color tuple and returns an RGBA image, wherein the output is transparent based on the dominance of the specified color within each pixel. Some of the other tools in this example are also from MIMT.
% RGBA COMPOSITION USING MIMT color2alpha()
% foreground image is RGB, antialiased
FG = imread('Fuji.jpg');
BG = imread('Gunung.jpg');
% calculate subscripts for FG placement
offset = [-150 -50]; % offset from center [y x] (px)
sfg = imsize(FG,2);
sbg = imsize(BG,2);
os = min(max(round((sbg-sfg)/2 + offset),1),sbg-sfg);
rows = os(1):os(1)+sfg(1)-1;
cols = os(2):os(2)+sfg(2)-1;
% extract a BG region in the ROI
roisample = BG(rows,cols,:);
% add alpha channel to FG
% by default, color2alpha() selects the most frequent color
% otherwise, a specific color may be specified
FG = color2alpha(FG); % this is now RGBA
% composite the two images
alpha = 0.8;
roisample = replacepixels(FG,roisample,alpha);
roisample = splitalpha(roisample); % strip extraneous alpha channel
% insert the modified sample into the result
outpict = BG;
outpict(rows,cols,:) = roisample;
imshow(outpict)
It's not perfect due to the damage from JPG compression, but it's generally preferable when trying to mask off soft-edged regions against a flat color field.
Of course, if we're using MIMT, there are other ways to do the same composition:
% MIMT IMSTACKER/C2A
% foreground image is RGB, antialiased
FG = imread('Fuji.jpg');
BG = imread('Gunung.jpg');
% add alpha channel to FG
FG = color2alpha(FG);
% stack the images on dim4 (default)
% output geometry is the union of frame geometries (default)
% pad images with transparent black (default)
% images are centered (default) and offset as specified
ST = imstacker({FG BG},'offset',[-150 -50; 0 0]);
% composite the two images with scalar alpha
alpha = 0.5;
outpict = mergedown(ST,alpha,'normal');
outpict = splitalpha(outpict); % strip extraneous alpha channel
imshow(outpict)
... and the output is the same as the prior example. It's computationally more expensive, but it's easier to write and is closer to the concepts one might understand from working with images in image manipulation programs.
That, and MIMT tools can do more than simple compositing. Mergedown() and imblend() can do proper image blending as Photoshop, etc might do.
% MIMT MERGEDOWN/IMBLEND
% foreground image is RGB, antialiased
FG = imread('Fuji.jpg');
BG = imread('Gunung.jpg');
% stack the images on dim4 (default)
% output geometry is the union of frame geometries (default)
% pad images with transparent black (default)
% images are centered (default) and offset as specified
ST = imstacker({FG BG},'offset',[-150 -50; 0 0]);
% blend the two images and composite with scalar alpha
alpha = 0.8;
outpict = mergedown(ST,alpha,'linearburn'); % pick any blend mode
outpict = splitalpha(outpict); % strip extraneous alpha channel
imshow(outpict)
So it's really up to you where you want to go with it.
Lastly, as @KALYAN ACHARJYA points out, if all you want is text, it might be good to generate a fresh text overlay. Inserttext() is part of CVT, but if you don't have that, there are other options.
This answer covers one clumsy native workaround for text insertion, as well as a number of third-party text tools including ones from MIMT. For this particular task, the MIMT text tools are probably not the ones you want, though MIMT composition tools may help you incorporate the generated text overlay into the image.
  3 个评论
KALYAN ACHARJYA
KALYAN ACHARJYA 2022-10-28
@DGM Detail explanation, I appreciate your time and efforts! +1
@Rahmat Anbi Ancing As the question has been answered in detail, you can accept the answer as a due credit to the contributor. These people are really kind and always selflessly help all of us.

请先登录,再进行评论。

类别

Help CenterFile Exchange 中查找有关 Images 的更多信息

产品


版本

R2022a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by