How can I add text to an image and make the text become part of the image within MATLAB?

189 views (last 30 days)
I would like to add a few characters to an image. I want the characters to be part of the image, not a text object.

Accepted Answer

MathWorks Support Team
MathWorks Support Team on 16 Feb 2021
Edited: MathWorks Support Team on 22 Feb 2021
If you have the Computer Vision System Toolbox, you can use the "insertText" function:
For example:
I = imread('peppers.png');
J = insertText(I, [100 315 ], 'Peppers are good for you!');
imshow(J);
"insertText" supports unicode format. Please refer the following link for more information:
 
If the Computer Vision Toolbox is not available, you can use the following workaround:
You can display a text and use the GETFRAME function to capture the text as an image first. Then you replace the image pixels with the pixels from the text. The code below demonstrates the suggested steps above. Make sure that the image and axes objects are visible within the figure window when executing the GETFRAME command.
% Read example image
load('clown.mat');
im = uint8(255*ind2rgb(X,map));
%% Create the text mask
% Make an image the same size and put text in it
hf = figure('color','white','units','normalized','position',[.1 .1 .8 .8]);
image(ones(size(im)));
set(gca,'units','pixels','position',[5 5 size(im,2)-1 size(im,1)-1],'visible','off')
% Text at arbitrary position
text('units','pixels','position',[100 100],'fontsize',30,'string','some text')
% Capture the text image
% Note that the size will have changed by about 1 pixel
tim = getframe(gca);
close(hf)
% Extract the cdata
tim2 = tim.cdata;
% Make a mask with the negative of the text
tmask = tim2==0;
% Place white text
% Replace mask pixels with UINT8 max
im(tmask) = uint8(255);
image(im);
axis off
  2 Comments
Mikhail
Mikhail on 2 Sep 2015
You can't "really" use the vision.TextInserter system object from Computer Vision System Toolbox. The vision.TextInserter is not equivalent to the manual approach above because vision.TextInserter only supports ASCII character subset (as also mentioned in documentation). While the manual approach works fine (tried at least with Cyrillic).

Sign in to comment.

More Answers (2)

Dima Lisin
Dima Lisin on 3 Jun 2014
Edited: Dima Lisin on 10 Sep 2015
There is now an insertText function in the Computer Vision System Toolbox which will draw text into an image. It supports unicode characters as of R2015b.

DGM
DGM on 15 Jul 2021
Edited: DGM on 12 Feb 2023
Doing display capture seems like a poor workaround. The suggested method will fail for any practically large images. A reduced-size text image would need to be generated and padded out to correct geometry and text position. ... and all for a crudely binarized copy of what used to be antialiased text. If you're going to do display capture, at least preserve the antialiasing.
% process parameters
textstring = 'LOOK AT ALL THESE ROCKS';
fontsize = 100; % in pixels, not points
os = [900 300]; % offset
textcolor = [85 250 118];
inpict = imread('parkavenue.jpg');
s = size(inpict);
% create a text image on a base matting assumed large enough to enclose text
% this is just a quick guess on my part. i don't know of a good way to
% predict the output size with variable width fonts
hf = figure('units','normalized','position',[0 0 1 1]);
imshow(ones(fontsize*3,fontsize*numel(textstring)));
tt = text('units','pixels','position',[fontsize fontsize],'fontunits','pixels', ...
'fontsize',fontsize,'string',textstring);
tpict = getframe(gca);
tpict = tpict.cdata;
% crop out the base text object, invert, pad to image size
ttpos = round(tt.Extent); close(hf)
ttpos(2) = size(tpict,1)-ttpos(2);
tpict = tpict(ttpos(2)-ttpos(4):ttpos(2),ttpos(1):ttpos(1)+ttpos(3));
tpict = imcomplement(im2double(tpict));
st = size(tpict);
if st(2)>s(2)
error('text is too big to fit %dpx>%dpx',st(2),s(2))
elseif (os(2)+st(2))>s(2)
error('text is too big to fit with given offset (%dpx+%dpx)>%dpx',os(2),st(2),s(2))
end
tpict = padarray(tpict,os,0,'pre');
tpict = padarray(tpict,s(1:2)-(os+st),0,'post');
% generate a colored field
cpict = ones(s(1:2)).*permute(textcolor,[1 3 2]);
% composite the images
outpict = double(inpict).*(1-tpict) + double(cpict).*tpict;
outpict = uint8(outpict);
imshow(outpict)
The above code is not unbreakable, particularly due to the guesstimate for the required text matting size. It will also fail if the text block itself is too large to be rendered on screen. At least this demonstrates the concept and preserves the antialiasing because it uses linear blending.
This FEX submission by Daniel Warren has its shortcomings, but is probably the foundation of a better conceptual approach to exploiting figure capture for text insertion.
Is there something else?
I suppose it really depends what the needs and expectations are. There are a number of text to image tools on the File Exchange. The result is a small image of text. Combining that into any image should be a simple task. Some may support antialiased output suitable for linear blending like the above example. Others support only binary output, which has different utility and can allow compositing with simple masking.
For example, using textim() from MIMT (binary masking):
% process parameters
textstring = 'potato';
os = [150 150]; % offset
textcolor = [250 100 220];
% note that this is a grayscale RGB image
% also note that these operations presume a uint8 image
inpict = repmat(imread('coins.png'),[1 1 3]);
si = size(inpict);
tt = textim(textstring,'ibm-vga-16x9');
st = size(tt);
m = zeros(si(1:2));
m(os(1)+(1:st(1)),os(2)+(1:st(2))) = tt;
outpict = inpict;
outpict(repmat(logical(m),[1 1 size(inpict,3)])) = 0;
outpict = outpict + uint8(m.*permute(textcolor,[1 3 2]));
imshow(outpict)
MIMT has other tools that would simplify the positioning/compositing, but this example is generalized except for the textim() call.
What's on the FEX?
MIMT has both textim() and textblock(), which generate compact images of text in legacy hardware fonts. (CP437 based)
text2im() by Tobias Kiessling is similar, but only capable of a single font (the same default font used by MIMT textim()) (also CP437 based)
text2im by Rik offers a handful of modern font faces, though it supports a small charset and requires network connection.https://www.mathworks.com/matlabcentral/fileexchange/75021-text2im
text_to_image by Alec Jacobson is more flexible, but uses Imagemagick (external dependency), and is consequently slower.
There are also others:
And there are slightly different approaches:
  1 Comment
DGM
DGM on 22 May 2023
Edited: DGM on 22 May 2023
For what it's worth, MIMT now has a slightly more convenient tool specifically for inserting text into an existing image. You're still restricted to the monospaced bitmap fonts used by textim(), but at least it makes it easier by taking care of the transformation and compositing.
Color and alpha may be specified for both foreground and background. The text location can be specified relative to one of nine positions specified by the 'gravity' parameter. This makes it simple to place text in image corners or center it on edges
See the examples in the webdocs:

Sign in to comment.

MathWorks Support

Categories

Find more on Convert Image Type in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!