Insert text characters into image pixels - matlab

I am looking for a code to insert characters into image with matlab.
The img is my cover image and msg is my text. I get this error
Error using ==> bitset
Operands to BIT Ops must be numeric.
But mine is numeric. It is not? How do I make it clear?
clear all;
img=imread('img.jpg','jpg');
msgopen=fopen('ramz.txt');
msg=fread(msgopen);
msgbin=dec2bin(msg);
msgsize=size(msg);
x=msgsize(1);
msgsizebin=dec2bin(x,8);
imgh=size(img,1);
imgw=size(img,2);
for i=1:imgh;
for j=1:imgw;
img(i,j)=bitset(img(i,j),msgbin(i,1));
end
end

You can use the text function and then the hardcopy function to create the image with the text coded into the data;
img=imread('img.jpg','jpg');
msgopen=fopen('ramz.txt');
msg=fread(msgopen);
hfig=figure;
imshow(img);
hold on;
text(x_loc,y_loc,msg); %x_loc and y_loc are the locations where you want the text to
% appear. msg is assumed to be a string.
orig_mode = get(hfig, 'PaperPositionMode');
set(hfig, 'PaperPositionMode', 'auto');
img_with_text = hardcopy(hfig, '-Dzbuffer', '-r0');

Related

How to make a GIF from a set of MATLAB images

I have an array of values which I turn into a color image like so:
my_img = imagesc(my_data(:,:,tidx)); axis off; colormap('default'); c=colorbar; c.FontSize=26; c.FontWeight='bold';
I want to know if it's possible to loop through all the index values in my_data and turn them into a GIF.
I tried this:
for tidx = 5:64
my_img = imagesc(my_data(:,:,tidx)); axis off; colormap('default'); c=colorbar; c.FontSize=26; c.FontWeight='bold';
imwrite (my_img, int2str(tidx)+"_cspattern.png");
end
Which gave me this error:
Error using imwrite (line 427)
Expected DATA to be one of these types:
numeric, logical
Instead its type was matlab.graphics.primitive.Image.
I looked it up and tried this solution out:
for tidx = 5:64
my_img = imagesc(my_data(:,:,tidx)); axis off; colormap('default'); c=colorbar; c.FontSize=26; c.FontWeight='bold';
IMG_to_write = uint8(normalize(my_img, 'range', [0 255]));
imwrite(IMG_to_write, int2str(tidx)+"_cspattern.png");
end
But that just gave me this error:
Error using normalize>checkSupportedArray (line 159)
Invalid data type. First argument must be a real numeric or logical array, a table or a timetable.
Error in normalize (line 86)
checkSupportedArray(A,method,methodType,false);
Error in GenerateFigures (line 18)
IMG_to_write = uint8(normalize(SavePattern, 'range', [0 255]));
I feel as if I am overthinking this because there must be a simple way to load the data I want and save it as an image or series of images.
imagesc produces a graphics object, not a data array. It’s meant for displaying images into figures, not saving them into files. You need to hand imwrite your image data directly, along with your desired color map.
for tidx = 5:64
imwrite(my_data(:,:,tidx),parula(),int2str(tidx)+"_cspattern.png");
end
If you want to scale each image so that the full color range is used, the way imagesc does, you can do this manually.
for tidx = 5:64
my_data_slice = double(my_data(:,:,tidx));
my_data_slice = my_data_slice - min(my_data_slice,[],'all');
my_data_slice = my_data_slice / max(my_data_slice,[],'all')*255;
my_data_slice = uint8(my_data_slice);
imwrite(my_data_slice,parula(),int2str(tidx)+"_cspattern.png");
end

Image processing - Character count in dot printed text

I have to count the characters that is printed in a beverage tin[1]. So far i have done till removing noise and unwanted pixels and now my text is clear to read 2 but is there any way to count them properly. Ocr fails to detect this text. Or should i join these dots using some algorithm and continue with ocr function?
ROI of image
Here is the code which gave me the above picture.
clear all; close all;
a=imread('coke.jpg');
gray=rgb2gray(a);
thres=150;
lbw=double(gray>thres);
imwrite(lbw,'--\OCR\output.png');
a=imread('output.png');
c=imresize(a,.5);
b = im2bw(c, .9);
b=imcomplement(b);
imwrite(b,'compli.png');
You should definitely join the dots. The first thing I would try is the imclose function, which does morphological closing (dilation followed by erosion).
For example, you could try this:
im = imread('dotMatrix.png');
im2 = imclose(im, strel('line', 5, 90));
im3 = imclose(im2, strel('line', 5, 45));

Using imfreehand within your program

For instance, I start my program as follows reading some image:
I=input('image name: ','s');
img=double(imread(I));
I'm planning to work only on some portion of that image. So, I noticed that I may need h=imfreehand for this purpose.
Thus, I have inserted h=imfreehand under the two lines above. What I got is a white screen. So, how can I get the image and select the region I want? The other thing is, how can I tell my program to work only on that region I have selected?
Thanks.
UPDATE
I did the following in a portion of my code:
figure, imshow(img);
h = imfreehand;
position = wait(h);
% post processing
se=strel('disk',3);
erosion=imerode(h,se);
result_image=imsubtract(h,erosion);.
But, I got the following error:
Error using imerode
Expected input number 1, IM, to be one of these types:
numeric, logical
Instead its type was imfreehand.
Error in morphop>CheckInputImage (line 335)
validateattributes(A, {'numeric' 'logical'}, {'real' 'nonsparse'}, ...
Error in morphop>ParseInputs (line 166)
A = CheckInputImage(A, func_name);
Error in morphop (line 14)
[A,se,pre_pad,...
Error in imerode (line 123)
B = morphop(A,se,'erode',mfilename,varargin{:});
Error in program (line 155)
erosion=imerode(h,se);
Is it to do with erosion? What can be done in this case?
`
Following the advice in the matlab documentation try this:
I=input('image name: ','s');
img=imread(I);
figure, imshow(img);
h = imfreehand;
position = wait(h);
Edit:
The documentation suggests as an alternative
figure, imshow(img);
h = imfreehand(gca);
Try passing the handle of the plot to imfreehand()
I=input('image name: ','s');
img=double(imread(I));
figure;
ih=image(img);
h=imfreehand(ih)
Sorry, I don't have the image processing toolbox to test this.
Seems like converting your image (possibly uint8) to double causes a problem.
I would either do:
use the original coding of the image (for example img_uint8 = imread('coins.png') is coded using integers). The problem is that you won't probably be able to use imfreehand as it needs to read double or single precision float.
convert the image using img_double = double(imread('coins.png')) so that imfreehand will work. The conversion however causes a display problem that you can bypass with imshow(img_double,[]) that is an analogue of imshow(img_double, [min(min(img_double)), max(max(img_double))]). It forces imshow to correctly use the full range of data (255 Vs. 255.0)
The best option is therefore the second one.
To use imfreehand, #Try Hard gave a nice code h = imfreehand or h = imfreehand(gca)

write string on an image

I'm trying to match between 2 different images using sift,
What i want to do is to write a text (number) on the image.
hold on;
cols1 = size(im1,2);
for i = 1:1: size(des1,1)
if (match(i) > 0)
line([loc1(i,2) loc2(match(i),2)+cols1], [loc1(i,1) loc2(match(i),1)], 'Color', 'b');
s = int2str(i);
text (loc1(1,2), loc2(match(1),2)+cols1,s,...
'FontSize',14,...
'HorizontalAlignment','center');
end
end
hold off;
I'm getting an error Subscript indices must either be real positive integers or logicals.
at text (loc1(1,2), loc2(match(1),2)+cols1,s,...
I can't figure out what is wrong!
match(1) in that line may be zero (or at least not an positive integer). I note that you check match(i), but not match(1). Do you mean to use match(i)? That is,
text (loc1(1,2), loc2(match(i),2)+cols1,s,...

How can I display numbers with higher precision in a MATLAB data cursor?

I have a problem with precision loss. I imported a set of values from a CSV file into MATLAB 7 using the following code:
function importfile(fileToRead1)
%#IMPORTFILE(FILETOREAD1)
%# Imports data from the specified file
%# FILETOREAD1: file to read
DELIMITER = ',';
HEADERLINES = 0;
%# Import the file
rawData1 = importdata(fileToRead1, DELIMITER, HEADERLINES);
%# For some simple files (such as a CSV or JPEG files), IMPORTDATA might
%# return a simple array. If so, generate a structure so that the output
%# matches that from the Import Wizard.
[~,name] = fileparts(fileToRead1);
newData1.(genvarname(name)) = rawData1;
%# Create new variables in the base workspace from those fields.
vars = fieldnames(newData1);
for i = 1:length(vars)
assignin('base', vars{i}, newData1.(vars{i}));
end
This very basic script just takes the specified file:
> 14,-0.15893555
> 15,-0.24221802
> 16,0.18478394
And converts the second column to:
14 -0,158935550000000
15 -0,242218020000000
16 0,184783940000000
However, if I select a point with the Data Cursor it only displays 3 or 4 digits of precision:
Is there a way to program a higher precision to get more exact data points?
Your data isn't losing precision, the Data Cursor display just isn't showing the full precision so that the text boxes are a more reasonable size. However, if you want to increase the precision of the display in the text datatip, you can customize it.
If you right click on a Data Cursor text box, you should see a menu like this:
If you then select the Edit Text Update Function... option, it will open a default m-file containing the following:
function output_txt = myfunction(obj, event_obj)
% Display the position of the data cursor
% obj Currently not used (empty)
% event_obj Handle to event object
% output_txt Data cursor text string (string or cell array of strings).
pos = get(event_obj, 'Position');
output_txt = {['X: ', num2str(pos(1), 4)], ...
['Y: ', num2str(pos(2), 4)]};
% If there is a Z-coordinate in the position, display it as well
if length(pos) > 2
output_txt{end+1} = ['Z: ', num2str(pos(3), 4)];
end
Notice that the text for the X and Y coordinate data is formatted using num2str, with the second argument being a 4. This converts the coordinate value to a string representation with 4 digits of precision. If you want more digits displayed, simply increase this number, then save the newly-created m-file on your path.
Now your datatip text should display more precision for your numbers. If you want to accomplish all of the above programmatically, you would first create your text update function, save it to a file (like 'updateFcn.m'), then turn on Data Cursors using the function datacursormode and set them to use your user-defined text update function. Here's an example:
plot(1:10, rand(1, 10)); % Plot some sample data
dcmObj = datacursormode; % Turn on data cursors and return the
% data cursor mode object
set(dcmObj, 'UpdateFcn', #updateFcn); % Set the data cursor mode object update
% function so it uses updateFcn.m
If you want to make a permanent change - Warning: This is a slight hack to MATLAB - open:
C:\Program Files\Matlab\R2007b\toolbox\matlab\graphics\#graphics\#datacursor\default_getDatatipText.m
or a similar file depending on your version and change DEFAULT_DIGITS.
Don't quote me on this, but:
1) You haven't lost precision, MATLAB stores the full value, it is only the display that has been pared down.
2) In my version of MATLAB (R2009a) I can modify the way long numbers are shown in the command menu by going to
File>Preferences>Variable Editor
where a dropdown menu lets me pick between short, long, short e, long e, short g, long g, short eng, long eng, bank, + and rat.
I have no idea whether that affects what the Data Cursor shows, though.
You can add the following in your script:
dcm_obj = datacursormode(fig);
set(dcm_obj,'Updatefcn',#myfunction_datacursor);
You need to create and save myfunction_datacursor file with the following in your path (get path by calling path in MATLAB prompt)
function output_txt = myfunction_datacursor(obj,event_obj)
% Display the position of the data cursor
% obj Currently not used (empty)
% event_obj Handle to event object
% output_txt Data cursor text string (string or cell array of strings).
pos = get(event_obj,'Position');
output_txt = {['X: ',num2str(pos(1),8)],...
['Y: ',num2str(pos(2),4)]};
% If there is a Z-coordinate in the position, display it as well
if length(pos) > 2
output_txt{end+1} = ['Z: ',num2str(pos(3),8)];
end