How to add element to array in MatLab? - arrays

I am trying to make a graph of the brightness of a pixel vs the distance from center of that pixel. To do so I used for loops to check each pixel for these values. But when adding them to my array I find that I can't. One of the issues is I have to define the array size first so no values get placed in the right spot. I believe everything else to be working except adding values to the arrays.
I've tried various methods of concatenation to add the values of each pixel to the array. I didn't have any more solutions to try.
folder3 = 'C:\Users\slenka\Desktop\Image_Analysis\Subtracted';
cd('C:\Users\slenka\Desktop\Image_Analysis\Subtracted');
subtractedFiles = [dir(fullfile(folder3,'*.TIF')); dir(fullfile(folder3,'*.PNG')); dir(fullfile(folder3,'*.BMP')); dir(fullfile(folder3,'*.jpg'))];
numberOfSubImages= length(subtractedFiles);
for b = 1 : numberOfSubImages
subFileName=fullfile(folder3, subtractedFiles(b).name);
chartImage=imread(subFileName);
[chartY, chartX, chartNumberOfColorChannels] = size(chartImage);
ccY= chartY/2;
ccX= chartX/2;
c=[ccX,ccY];
distanceArray=zeros(1,chartX);
intensityArray=zeros(1,chartY);
f=1;
g=1;
for y=1:chartY
for x=1:chartX
D = sqrt((y - c(1)) .^ 2 + (x - c(2)) .^ 2);
grayScale= impixel(chartImage, x, y);
distanceArray(f)=[D];
intensityArray(g)=[grayScale];
f=f+1;
g=g+1;
end
end
xAxis=distanceArray;
yAxis=intensityArray;
plot(xAxis,yAxis);
end
I'm expecting 2 arrays one full of the data values for the light intensity of each pixel in the image, and another for that pixels distance from the center of the image. I am wanting to plot these two arrays as the y and x axis respectively. At the moment the actual results is an entirely empty array full of zeros.

Related

Matlab: Plot array such that each value has random shape and a color map

In Matlab:
How do I modify plot(x,y,'o'), where x=1:10 and y=ones(1,10), such that each point in the plot will have a random shape?
And how can I give it colors chosen from a scheme where the value at x=1 is the darkest blue, and x=10 is red (namely some sort of heat map)?
Can this be done without using loops? Perhaps I should replace "plot" with a different function for this purpose (like "scatter"? I don't know...)? The reason is that I am plotting this inside another loop, which is already very long, so I am interested in keeping the running-time short.
Thanks!
First, the plain code:
x = 1:20;
nx = numel(x);
y = ones(1, nx);
% Color map
cm = [linspace(0, 1, nx).' zeros(nx, 1) linspace(1, 0, nx).'];
% Possible markers
m = 'o+*.xsd^vph<>';
nm = numel(m);
figure(1);
hold on;
for k = 1:nx
plot(x(k), y(k), ...
'MarkerSize', 12, ...
'Marker', m(ceil(nm * (rand()))), ...
'MarkerFaceColor', cm(k, :), ...
'MarkerEdgeColor', cm(k, :) ...
);
end
hold off;
And, the output:
Most of this can be found in the MATLAB help for the plot command, at the Specify Line Width, Marker Size, and Marker Color section. Colormaps are simply n x 3 matrices with RGB values ranging from 0 to 1. So, I interpreted the darkest blue as [0 0 1], whereas plain red is [1 0 0]. Now, you just need a linear "interpolation" between those two for n values. Shuffling the marker type is done by simple rand. (One could generate some rand vector with size n beforehand, of course.) I'm not totally sure, if one can put all of these in one single plot command, but I'm highly sceptical. Thus, using a loop was the easiest way right now.

Plotting arrays using a grouped horizontal bar graph

I am trying to generate a graph that should look similar to:
My arrays are:
Array4:[Nan;Nan;.......;20;21;22;23;24;..........60]
Array3:[[Nan;Nan;.......;20;21;22;23;24;..........60]
Array2:[0;1;2;3;4;5;6;Nan;Nan;Nan;Nan;17;18;.....60]
Array1:[0;1;2;3;4;5;6;Nan;Nan;Nan;Nan;17;18;.....60]
I cannot find the right way to group my arrays in order to plot them in the way shown on the above graph.
I tried using the following function explained in: http://uk.mathworks.com/help/matlab/ref/barh.html
barh(1:numel(x),y,'hist')
where y=[Array1,Array2;Array3,Array4] and x={'1m';'2m';'3m';......'60m'}
but it does not work.
Why Your Current Approach Isn't Working
Your intuition makes sense to me, but the barh function you are using doesn't work the way you think it does. Specifically, you are interpreting the meaning of the x and y inputs to that function incorrectly. Those are inputs are constant values, not entire axes. The first y input refers to the end-point of the bar that stretches horizontally from x = 0 and the first x input refers to location on the y-axis of the horizontal bar. To illustrate what I mean, I've provided the below horizontal bar graph:
You can find this same picture in the official documentation of the MATLAB barh function. The code used to generate this bar graph is also given in the documentation, shown below:
x = 1900:10:2000;
y = [57,91,105,123,131,150,...
170,203,226.5,249,281.4];
figure;
barh(x, y);
The individual elements of the x array, rather confusingly, show up on the y-axis as the starting locations of each bar. The corresponding elements of the y array are the lengths of each bar. This is the reason that the arrays must be the same length, and this illustrates that they are not specifications of the x and y axes as one might intuitively believe.
An Approach To Solve Your Problem
First things first, the easiest approach is to do this manually with the plot function and a set of lines that represent floating bars. Consult the official documentation for the plot function if you'd like to plot the lines with some sort of color coordination in mind - the code I present (modified version of this answer on StackOverflow) just switches the color of the floating bars between red and blue. I tried to comment the code so that the purpose of each variable is clear. The code I present below matches the floating bar graph that you want to be plotted, if you are alright with replacing thick floating bars with 2D lines floating on a plot.
I used the data that you gave in your question to specify the floating horizontal bars that this script would output - a screenshot is shown below the code. Array1 & Array2:[0;1;2;3;4;5;6;Nan;Nan;Nan;Nan;17;18;.....60], these arrays go from 0 to 6 (length = 6) and 17 to 60 (length = 60 - 17 = 43). Because there is a "discontinuity" of sorts from 7 to 16, I have to define two floating bars for each array. Hence, the first four values in my length array are [6, 6, 43, 43]. Where the first 6 and the first 43 correspond to Array1 and the second 6 and the second 43 correspond to Array2. Recognizing this "discontinuity", the starting point of the first floating bar for Array1 and Array2 is x = 0 and the starting point of the second floating bar for Array1 and Array2 is x = 7. Putting that all together, you arrive at the x-coordinates for the first four points in the floating_bars array, [0 0; 0 1.5; 17 0; 17 1.5]. The y-coordinates in this array only serve to distinguish Array1, Array2, and so on from each other.
Code:
floating_bars=[0 0; 0 1.5; 17 0; 17 1.5; 20 6; 20 7.5]; % Each row is the [x,y] coordinate pair of the starting point for the floating bar
L=[6, 6, 43, 43, 40, 40]; % Length of each consecutive bar
thickness = 0.75;
figure;
for i=1:size(floating_bars,1)
curr_thickness = 0;
% It is aesthetically pleasing to have thicker bars, this makes the plot look for like the grouped horizontal bar graph that you want
while (curr_thickness < thickness)
% Each bar group has two bars; set the first to be red, the second to be blue (i.e., even index means red bar, odd index means blue bar)
if mod(i, 2)
plot([floating_bars(i,1), floating_bars(i,1)+L(i)], [floating_bars(i,2) + curr_thickness, floating_bars(i,2) + curr_thickness], 'r')
else
plot([floating_bars(i,1), floating_bars(i,1)+L(i)], [floating_bars(i,2) + curr_thickness, floating_bars(i,2) + curr_thickness], 'b')
end
curr_thickness = curr_thickness + 0.05;
hold on % Make sure that plotting the current floating bar does not overwrite previous float bars that have already been plotted
end
end
ylim([ -10 30]) % Set the y-axis limits so that you can see more clearly the floating bars that would have rested right on the x-axis (y = 0)
Output:
How Do I Do This With the barh Function?
The short answer is that you'd have to modify the function manually. Someone has already done this with one of the bar graph plotting functions provided by MATLAB, bar3. The logic implemented in this modified bar3 function can be re-applied for your purposes if you read their barNew.m function and tweak it a bit. If you'd like a pointer as to where to start, I'd suggest looking at how they specify z-axis minimum and maximums for their floating bars on the plot, and apply that same logic to specify x-axis minimum and maximums for your floating bars in your 2D case.
I hope this helps, happy coding! :)
I explain here my approach to generate these type of graphs. Not sure if it is the best but it works and there is no need to do anything manually. I came up with this solution based on the following Vladislav Martin's explained fact: "The y-coordinates in this array only serve to distinguish Array1, Array2, and so on from each other".
My original arrays are:
Array4=[Nan....;20;21;22;23;24;..........60]
Array3=[Nan....;20;21;22;23;24;..........60]
Array2=[0;1;2;3;4;5;6;Nan;Nan;Nan;Nan;17;18;.....60]
Array1=[0;1;2;3;4;5;6;Nan;Nan;Nan;Nan;17;18;.....60]
x={'0m';'1m';'2m';'3m';'4m';....'60m'}
The values contained in these arrays make reference to the x-axis on the graph. In order to make the things more simple and to avoid having to code a function to determine the length for each discontinuity in the arrays, I replace these values for y-axis position values. Basically I give to Array1 y-axis position values of 0 and to Array2 0+0.02=0.02. To Array3 I give y-axis position values of 0.5 and to Array4 0.5+0.02=0.52. In this way, Array2 will be plotted on the graph closer to Array1 which will form the first group and Array4 closer to Array3 which will form the second group.
Datatable=table(Array1,Array2,Array3,Array4);
cont1=0;
cont2=0.02;
for col=1:2:size(Datatable,2)
col2=col+1;
for row=1:size(Datatable,1)
if isnan(Datatable{row,col})==0 % For first array in the group: If the value is not nan, I replace it for the corresponnding cont1 value
Datatable{row,col}=cont1;
end
if isnan(Datatable{row,col2})==0 % For second array in the group: If the value is not nan, I replace it for the corresponnding cont2 value
Datatable{row,col2}=cont2;
end
end
cont1=cont1+0.5;
cont2=cont2+0.5;
end
The result of the above code will be a table like the following:
And now I plot the Arrays using 2D floating lines:
figure
for array=1:2:size(Datatable,2)
FirstPair=cell2mat(table2cell(Datatable(:,array)));
SecondPair=cell2mat(table2cell(Datatable(:,array+1)));
hold on
plot(1:numel(x),FirstPair,'r','Linewidth',6)
plot(1:numel(x),SecondPair,'b','Linewidth',6)
hold off
end
set(gca,'xticklabel',x)
And this will generate the following graph:

Scatter plot: Using different colour for different data set

I have 3 Nx1 arrays, say X,Y,Z. I'd like to create a 3D plot such that each of the arrays I can assign different colours to improve the visibility of points. My main objective now is to change only the colour of array Z, such that elements of array X and Y have different colours as that of elements of Z .
I tried scatter3 function and gscatter MATLAB functions, but not able to achieve what I desire.
If we see the Vertical axis in image (Z axis), the colour of points is varying from Blue to Orange/Yellow. I want to set the colour of all these Z points as Red. Rest, all the colours of X and Y points remain same
scatter(x, y, a, c) takes arguments x and y, and then a for size, and c for colour. a can either be a single scalar, or a vector with a size for each (x,y) point. c can be an RGB triplet, or a vector, the same size as x and y. For example:
x = 1:4;
scatter(x, x, 10*x, x);
results in
scatter3(x,y,z,s,c) is similar, so in your case, perhaps
scatter3(X,Y,Z,[],Z)
will result in your data having a different colour determined by its z value.
One little example which I think is what you're looking for:
X = rand(100,1);
Y = rand(100,1);
Z = rand(100,1);
scatter3(X,Y,Z,[],Z)
Produces:
I got the answer by trying different MATLAB functions.
I used the gscatter function. As I had to colour all the Z points(consider 'Z' array as the 3rd data set) as Red and rest X and Y data set (the other 2 data set) as green or other colour, I used the following code:
group = Z(:,1);
gscatter(X(:,1),Y(:,1),group, 'gr', 'xo');
It creates a 2D plot but serves my purpose.
The Image is made of 3 data sets, but the first 2 data sets are intentionally combined (in Green Cross) and 3rd data set is kept Red, to visualize the relation of 3rd data set with 1st and 2nd data sets combined.
Click here for Image.

MATLAB - copying specific values from one 3d array to another

I need to update image 1 with rgb values from image 2 for specific coordinates.
I have two 2d matrices (im1Cart_toupdate 2x114056 and im2EstCart_tocopyfrom also 2x114056). These contain the ordered x-y pairs for which I want to copy rgb values from image 2 to image 1.
i.e. there are 114,056 pixels where I want to copy colours across.
im1 (440x1370x3) and im2 (240x320x3) are the image arrays. Note im2 is going to be stretched, so some pixels from im2 will appear more than once in im2EstCart_tocopyfrom.
I need an efficient way of doing this, as even with the above image sizes my current implementation is very slow. I had thought that there may be some approach using sub2ind - but am not sure how to do this with 3d arrays.
Here's my current code. It's the for loop that's killing me!
%Create a matrix of all pixel coordinates in im1 (homogenised form)
[im1gridx im1gridy]=meshgrid(1:im1width,1:im1height);
im1Cart = [im1gridx(:) im1gridy(:)]';
im1Hom = [im1Cart; ones(1,numel(im1gridy))];
%transform pixel positions with homography (HEst is a matrix built
%elsewhere) to find where they are in the coordinates of image 2
im2EstHom = HEst*im1Hom;
im2EstCart = im2EstHom(1:2,:)./repmat(im2EstHom(3,:),2,1);
im2EstCart = round(im2EstCart);
%check if the the transformed position is within the boundary of image 2
validCoords = im2EstCart(1,:)>0 & im2EstCart(2,:)>0 & im2EstCart(1,:)<=im2width & im2EstCart(2,:)<=im2height;
im1Cart_toupdate=im1Cart(:,validCoords);
im2EstCart_tocopyfrom=im2EstCart(:,validCoords);
%copy colour from image 2 to image 1 - currently pixel by pixel
%but CAN THIS BE VECTORISED?
for i=1:size(im1Cart_toupdate,2)
im1y=im1Cart_toupdate(1,i);
im1x=im1Cart_toupdate(2,i);
im2y=im2EstCart_tocopyfrom(1,i);
im2x=im2EstCart_tocopyfrom(2,i);
im1(im1y,im1x,:) = im2(im2y,im2x,:);
drawnow
end
Many thanks for any advice!
Approach #1
This would be one vectorized approach using linear indexing with bsxfun -
[m2,n2,r2] = size(im2);
RHS_idx1 = (im2EstCart_tocopyfrom(2,:)-1)*m2 + im2EstCart_tocopyfrom(1,:)
RHS_allidx = bsxfun(#plus,RHS_idx1(:),(0:r2-1)*m2*n2)
[m1,n1,r1] = size(im1);
LHS_idx1 = (im1Cart_toupdate(2,:)-1)*m1 + im1Cart_toupdate(1,:)
LHS_allidx = bsxfun(#plus,LHS_idx1(:),(0:r1-1)*m1*n1)
im1(LHS_allidx) = im2(RHS_allidx)
Approach #2
Here's another approach that reshapes the input 3D array to a 2D array after merging the first two dimensions, then using linear indexing for extracting and setting values and finally reshaping back to its original 3D size, like so -
[m2,n2,r2] = size(im2)
RHS_idx1 = (im2EstCart_tocopyfrom(2,:)-1)*m2 + im2EstCart_tocopyfrom(1,:)
im2r = reshape(im2,[],r2)
[m1,n1,r1] = size(im1)
LHS_idx1 = (im1Cart_toupdate(2,:)-1)*m1 + im1Cart_toupdate(1,:)
im1r = reshape(im1,[],r1)
im1r(LHS_idx1,:) = im2r(RHS_idx1,:)
im1 = reshape(im1r,size(im1));

MatLab: Create an 3D array out of x,y,z coordinates and corresponding intensity values

I have a large 2D-array (31100 x 4) built up like this:
Intensity | X | Y | Z
out of this array I would like to create a 3D-array to visualize it as a 3D-image.
I would somehow have to transform the 2D into a 3D-array. Since there will be plenty of points where there is no intensity value available all of these points should be zero values.
Side information:
min(x) = -152.0120;
max(x) = 161.4350;
min(y) = -256.2560;
max (y) = -52.3801;
min(z) = -428.5920;
max (z) = -152.4210;
Because of the larger number of decimal places I might have to round up. Yet, this would possibly lead to several intensities being assigned to the same coordinate combination. Logically, I would have to add up the intensities in these cases.
This makes everything really complicated.
I would be happy if someone could teach me how to transform a 2D into a 3D array with zero-values for spots without intensity values.
Thanks for reading.

Resources