write string on an image - matlab

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

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

Graph Legend MATLAB For Loop

I've got a lab where I need to first derrive a transfer function for a fourth order mass spring damper system, then plot this for a 200N step response.
The dashpot damping coefficient is a variable and we are to plot a range of values graphically and choose the optimium value i.e (the one closest to a critically damped response).
I have all of the above tasks working fully as expected, and maybe I'm just being dumb here but I can't get the graph legend to behave as desired.
I'd ideally like it to say "B="Current Value of B for that itteration of the loop.
%Initialisations
close all;format short g;format compact;clc;clear;
k1=500000;
k2=20000;
m1=20;
m2=400;
opt=stepDataOptions('StepAmplitude',200);
for (b = [1000:1000:15000])
Hs = tf([b k2],[(m1*m2) (b*(m1+m2)) (k2*(m1+m2)+k1*m2) (b*k1) (k1*k2)]);
hold on;
stepplot(Hs,opt)
title("Shock Absorber Performance to Step Input");
ylabel("Force (N)");
legend;
hold off;
end
Thanks in advance :)
Although not such a clean solution, this will work:
close all;format short g;format compact;clc;clear;
k1=500000;
k2=20000;
m1=20;
m2=400;
opt=stepDataOptions('StepAmplitude',200);
% initialize a cell array that will hold the labels
labels = {};
for (b = [1000:1000:15000])
Hs = tf([b k2],[(m1*m2) (b*(m1+m2)) (k2*(m1+m2)+k1*m2) (b*k1) (k1*k2)]);
hold on;
stepplot(Hs,opt)
title("Shock Absorber Performance to Step Input");
ylabel("Force (N)");
hold off;
% set the label name, with the value for b
labels{end+1} = ['B = ' num2str(b)];
end
% create the legend with the labels
legend(labels)

Flip order of elements function in MATLAB R2011a

I am using MATLAB version R2011a, a friend of mine is using R2014b which contains the function "Flip", which flips the order of elements, this function is vital to our program that compares Matrix'es.
My problem is R2011a does not have this function, it has fliplr,flipud and flipdim. I have tried using fliplr and then flipud to try and recreate the same function but eventually it doesn't work since i'm using the function corr which requires using that it's two arguments be the same dimensions.
I need advise on how to create the flip function that is available on R2014b.
The function that is problematic:
%This function gets the DNA signiture with the relative freq of each perm at
%the refernce text, the DNA signiture with the relative freq of each perm at
%the compare text, and the MaxPerm, and return the relative editor distance
%between the 2 texts.
function [distance]=EditorDistance2 (RefDNAWithFreq,CmpDNAWithFreq,MaxPerm)
if MaxPerm>2
MaxPerm=2;
end
str='Editor Distance compare begun';
disp(str);
distance=[];
for PermLength=1:MaxPerm
freq=sum(0:PermLength);
PermInitial=freq+1;
permEnd=freq+PermLength;
%create an ordered matrix of all the perms with length "PermLength"
%in the ref text
CurRefPerms=RefDNAWithFreq(:,freq:permEnd);
OrderedRefCurPerms=sortrows(CurRefPerms);
OrderedRefCurPerms=flip(OrderedRefCurPerms);
OrderedRefCurPerms(:,1)=[];
OrderedRefCurPerms=ZeroCutter(OrderedRefCurPerms);
%create an ordered matrix of all the perms with length "PermLength"
%in the cmp text
CurcmpPerms=CmpDNAWithFreq(:,freq:permEnd);
OrderedCmpCurPerms=sortrows(CurcmpPerms);
OrderedCmpCurPerms=flip(OrderedCmpCurPerms);
OrderedCmpCurPerms(:,1)=[];
OrderedCmpCurPerms=ZeroCutter(OrderedCmpCurPerms);
len1=size(OrderedRefCurPerms,1);
len2=size(OrderedCmpCurPerms,1);
edit=1;
matrix=zeros(len2,len1);
%initiate first row of the first stirng
for i=2:len1
matrix(1,i)=matrix(1,i-1)+1;
end
%initiate first column of the second stirng
for i=2:len2
matrix(i,1)=matrix(i-1,1)+1;
end
%start algoritem
for i=2:len2
for j=2:len1
if OrderedRefCurPerms(j-1,:)==OrderedCmpCurPerms(i-1,:)
edit=0;
end
if (i>2 & j>2 & OrderedRefCurPerms(j-1,:)==OrderedCmpCurPerms(i-2,:) & RefDNAWithFreq(j-2)==CmpDNAWithFreq(i-1) )
matrix(i,j)= min([matrix(i-1,j)+1,... deletion
matrix(i,j-1)+1,... insertion
matrix(i-2,j-2)+1,... substitution
matrix(i-1,j-1)+edit... transposition
]);
else
matrix(i,j) = min([matrix(i-1,j)+1,... deletion
matrix(i,j-1)+1,... insertion
matrix(i-1,j-1)+edit... substitution
]);
end
edit=1;
end
end
%The Distance is the last elment of the matrix.
if i~=1
tempdistance = matrix( floor( len2 / 3 ) , floor( len1 / 3 ) );
tempdistance=tempdistance/floor(len2/3);
else
tempdistance = matrix( len2,len1 );
tempdistance= tempdistance/len2;
end
tempdistance=1-tempdistance;
distance=[distance tempdistance];
end
end
I will further explain myself, the function which I am trying to use is A=flip(A)
The function that causes me problems is this one
%This function gets the DNA signiture with the relative freq of each perm at
%the refernce text, the DNA signiture with the relative freq of each perm at
%the compare text, and the MaxPerm, and return the corralation between the 2 texts.
function [Corvector]=CorrelationCompare(RefDNAWithFreq,CmpDNAWithFreq,MaxPerm)
str='corraltion compare begun';
disp(str);
%this vector will contain the corralation between the freqs of
%each perms vector(each length)
Corvector=[];
for PermLength=1:MaxPerm
freq=sum(0:PermLength);
PermInitial=freq+1;
permEnd=freq+PermLength;
%Cor is correlation between the 2 texts
refPerms=RefDNAWithFreq(:,freq);
cmpPerms=CmpDNAWithFreq(:,freq);
refPerms=ZeroCutter(refPerms);
cmpPerms=ZeroCutter(cmpPerms);
tempCor=corr(refPerms,cmpPerms);
Corvector =[Corvector tempCor];
% making a graph of the perms, and the relative freq of the texts.
x=ZeroCutter ( RefDNAWithFreq(:,PermInitial:permEnd) );
y1=refPerms;
y2=cmpPerms;
xchars=char(x);
Xcols=size(x,1);
o=ones(Xcols,1);
xco=mat2cell(xchars,o,PermLength);
xaxis=(1:Xcols);
figure
stem(xaxis,y1,'r');
hold
stem(xaxis,y2,'g');
set(gca,'XTick',xaxis)
set(gca,'XTickLabel',xco,'fontname','david');
xlabel('Perms');
ylabel('Perm frequency');
TitleOfGraph=sprintf('comapre between reference text to the compared, %d letters perm\n correlation=%f',PermLength,Corvector(PermLength));
legend('reference','compared');
title(TitleOfGraph);
end
end
The Error that I recieve when using a diffrent flip command is
??? Error using ==> corr at 102
X and Y must have the same number of rows.
Error in ==> CorrelationCompare at 27
tempCor=corr(refPerms,cmpPerms);
I apologize for the long codes but it's hard to explain it all since it's a big project and a lot of it was done by my partner
This should work for you -
function out = flip_hacked(A,dim)
%// Get an array of all possible dimensions
dims = 1:ndims(A);
%// Interchange first dimension and dim
dims(dim) = 1;
dims(1) = dim;
A1 = permute(A,[dims]);
%// Reshape A1 into a 2D matrix and then flip along the first dimension,
%// which would correspond to the flipping along dim and then interchange dim
%// and first dim again to keep the size of data same as input and elements
%// being flipped along dim for the desired output
A2 = reshape(A1,size(A1,1),[]);
out = permute(reshape(A2(end:-1:1,:),size(A1)),dims);
return;
It follows the same syntax as the official flip function that's stated in the official documentation as follows -
B = flip(A,dim) reverses the order of the elements in A along
dimension dim. For example, if A is a matrix, then flip(A,1) reverses
the elements in each column, and flip(A,2) reverses the elements in
each row.
In addition to the generic solution provided by Divakar you could simply use:
flip = #(A) A(end:-1:1, :);
A = flip(A);
To reverse the elements in each column of a matrix A. Even simpler:
A = A(end:-1:1, :);

Matlab get vector of specific pixels

I am pretty new to Matlab and encountered a problem when working with images.
I want to get a pixel that is in a specific colour (blue) in the following image:
image
My current code looks something like this:
function p = mark(image)
%// display image I in figure
imshow(image);
%// first detect all blue values higher 60
high_blue = find(image(:,:,3)>60);
%cross elements is needed as an array later on, have to initialize it with 0
cross_elements = 0;
%// in this iteration the marked values are reduced to the ones
%where the statement R+G < B+70 applies
for i = 1:length(high_blue)
%// my image has the size 1024*768, so to access the red/green/blue values
%// i have to call the i-th, i+1024*768-th or i+1024*768*2-th position of the "array"
if ((image(high_blue(i))+image(high_blue(i)+768*1024))<...
image(high_blue(i)+2*768*1024)+70)
%add it to the array
cross_elements(end+1) = high_blue(i);
end
end
%// delete the zero element, it was only needed as a filler
cross_elements = cross_elements(cross_elements~=0);
high_vector = zeros(length(cross_elements),2);
for i = 1:length(cross_elements)
high_vector(i,1) = ceil(cross_elements(i)/768);
high_vector(i,2) = mod(cross_elements(i), 768);
end
black = zeros(768 ,1024);
for i = 1:length(high_vector)
black(high_vector(i,2), high_vector(i,1)) = 1;
end
cc = bwconncomp(black);
a = regionprops(cc, 'Centroid');
p = cat(1, a.Centroid);
%// considering the detection of the crosses:
%// RGB with B>100, R+G < 100 for B<150
%// consider detection in HSV?
%// close the figure
%// find(I(:,:,3)>150)
close;
end
but it is not optimized for Matlab, obviously.
So i was wondering if there was a way to search for pixels with specific values,
where the blue value is larger than 60 (not hard with the find command,
but at the same time the values in the red and green area not too high.
Is there a command I am missing?
Since English isn't my native language, it might even help if you gave me some suitable keywords for googling ;)
Thanks in advance
Based on your question at the end of the code, you could get what you want in a single line:
NewImage = OldImage(:,:,1) < SomeValue & OldImage(:,:,2) < SomeValue & OldImage(:,:,3) > 60;
imshow(NewImage);
for example, where as you see you provide a restriction for each channel using logical operators, that you can customize of course (eg. using | as logical OR). Is this what you are looking for? According to your code you seem to be looking for specific regions in the image like crosses or coins is that the case? Please provide more details if the code I gave you is completely off the track :)
Simple example:
A = imread('peppers.png');
B = A(:,:,3)>60 & A(:,:,2)<150 & A(:,:,1) < 100;
figure;
subplot(1,2,1);
imshow(A);
subplot(1,2,2)
imshow(B);
Giving this:

Insert text characters into image pixels

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');