How do I populate matrix with a vector, considering Matrix as chart and vector as line - matlab

Consider following values
result=zeros(11,11);
line=(4:0.4:8);
Imagine result as a 11x11 X-Y chart paper. So initially we have a blank chart paper. As in a chart plot, I want to populate values of line in result matrix so that we get an upward sloping line when we display matrix.
Consider following figure which I want as result.
Here, result matrix can be visualized as chart paper with origin at bottom left corner. Now, for X=1, line(1)=4; for X=2, line(2)=4.4,.. and so on.
I have written following code which serves the purpose.
result=zeros(11,11);
line=(4:0.4:8);
for i=1:length(line)
temp=floor(line(i));
result(length(line)-temp+1,i)=line(i);
end
Is there a more efficient way to implement this solution? (I shall be working with 20000x20000 matrix, so method needs to be fast)
As suggested in comments, Problem Description is as follows:
I have lets say 1000 lines. All of these lines have different slopes and intercept. I know the x range of the lines and y range of the lines. There is not much I can infer from data if I plot these lines simultaneously on a single plot. The resulting image will be something like this:
Not much can be inferred about this plot. However, if I can get this information saved in a big matrix, then I can analyse where maximum lines are passing through at a particular X index and make further analysis accordingly.
Further Details
I am discretinizing Y axis into 1000 equally spaced interval:
sample code as follows:
range=max(data)-min(data);
percent=0.20;
outerRange= max(data)+range*percent - (min(data)-range*percent);
outerRangeValues=min(data)-range*percent:outerRange/1000:max(data)+range*percent;
Even though it is entirely possible that a particularly steep line will pass through 2 or more rows in a single column, I'll only select only one of the rows to be filled by line in a single column. This can be done by taking average of rows values for a particular column and assigning single row to be its value for that column

You can use sub2ind to keep things vectorized and avoid loops.
The idea is to find all the row and column indices which will have to be modified.
For X axis it is easy, it is simply one per column so the X indices will be 1,2,3,...,np.
For the Y axis, you have to bin the line values into the Y grid. Since indices have to be integers, you have to convert your floating point values into integers. For that you can choose between round, floor and ceil. Each will place some values slightly differently, it is up to you to define which rounding method makes sense for your problem.
Once you have your indices [row_indices,column_indices], you convert them to linear indices into the matrix by using sub2ind, then you assign the values of line into these linear indices.
In code:
line=(4:0.4:8); % your input (line vector)
np = numel(line) ; % determine size of matrix/chart
% identify column and row indices to modify
idCol = 1:np ;
idRow = fliplr( round( line ) ) ; % choose "round", "floor" or "ceil"
% build the result
result = zeros(np);
linearInd = sub2ind( [np,np], idRow, idCol ) ;
result(linearInd) = line ;
Gives you:
>> result
result =
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 7.2 7.6 8
0 0 0 0 0 0 6.4 6.8 0 0 0
0 0 0 5.2 5.6 6 0 0 0 0 0
0 4.4 4.8 0 0 0 0 0 0 0 0
4 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0

Related

assigning coordinate to a matrix in MATLAB

I'm writing a MATLAB code, I encountered a problem: I have a (2N+1)*(2N+1) matrix for example 7*7. I want to assign coordinate system to it such that the matrix center is the origin of coordinate system. I mean I want to assign (0,0) to row 4 and column 4 of matrix, (1,0) to row 4 and column 5 of matrix and so on. please help me
Thank you in advance
I want to generate a line of ones in all possible directions in a square matrix like this:
0 0 0 0 0 0 0
0 0 0 0 0 0 1
0 0 0 0 0 1 0
0 0 0 1 0 0 0
0 1 0 0 0 0 0
1 0 0 0 0 0 0
0 0 0 0 0 0 0
center of matrix is the origin. this line has 30 degree from horizontal axis.
What you want is a simple mapping from the original matrix counting system to a customized one. Here I have built two cell matrices, representing the coordinates of the elements in the matrix.
Here I have done a simple mapping as follows:
for ii = 1:7
for jj=1:7
D{ii,jj} = C{ii,jj} - [4,4];
end
end
Generally, for matrix of size 2*N+1, you will do the following:
for ii = 1:2*N+1
for jj = 1:2*N+1
D{ii,jj} = C{ii,jj} - [N+1,N+1];
end
end
where C is the original matrix and D is the mapped matrix. After you well-understood what I have done here, you can then replace the for-loops with more efficient functions such as bsxfun.

Matlab FingerPrint Minutia Extraction

I am very interested in fingerprint verification and studying minutia extraction at present. I have found the following code online and wonder if someone would be kind enough to explain it? I have looked up centroid, regionprops etc, I understand these a little but the code below has me puzzled!
fun=#minutie;
L = nlfilter(K,[3 3],fun);
%% Termination
LTerm=(L==1);
imshow(LTerm)
LTermLab=bwlabel(LTerm);
propTerm=regionprops(LTermLab,'Centroid');
CentroidTerm=round(cat(1,propTerm(:).Centroid));
imshow(~K)
set(gcf,'position',[1 1 600 600]);
hold on
plot(CentroidTerm(:,1),CentroidTerm(:,2),'ro')
%% Bifurcation
LBif=(L==3);
LBifLab=bwlabel(LBif);
propBif=regionprops(LBifLab,'Centroid','Image');
CentroidBif=round(cat(1,propBif(:).Centroid));
plot(CentroidBif(:,1),CentroidBif(:,2),'go')
The code first filters the binary image with a neighborhood of 3x3 pixels. nfilter is a moving filter function. It will go through all the pixels in the image given as argument and apply an operation based on the values of the neighboring pixels.
I don't know the exact content of the minutie filter, but judging by the rest of the code, it probably counts the pixels with a value of 1 in the neighborhood of all 1s. In other words it will be equal to one at the end of a segment, and equal to 3 when there are 3 branches (a bifurcation).
Example:
Let a filter sum up the ones in the neighborhood, like this:
sum(block(1,1:3), block(3,1:3), block(2,1), block(2,3))*block(2, 2);
where block denotes a neighborhood around each pixel of the binary image.
In the left matrix below (if you ignore the boundary exceptions) there is one position with a one that has exactly one 1 in its 3x3 neighborhood, in the right matrix, there is one position with a one that has exactly three 1s in its 3x3 neighborhood.
[0 0 0 0 0 [0 0 1 0 0
0 0 0 0 0 0 0 1 0 0
0 0 1 0 0 1 1 1 0 0
0 0 1 0 0 0 0 1 0 0
0 0 1 0 0] 0 0 1 0 0]
The filtered output would be:
[0 0 0 0 0 [0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 3 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0] 0 0 0 0 0]
It found a termination in the left matrix, and a bifurcation in the right matrix.
The filtered image are then thresholded at the value 1 and 3, then the use of bwlabel and regionprops is somewhat mysterious to me† since bifurcations and terminations are single points, their position is simply their index. I think you could simply achieve the detection of the coordinates of the terminations and bifurcation using something like:
[It Jt]= find(L==1);
[Ib Jb]= find(L==3);
† one reason I can think of is that coordinates in images and arrays are different in matlab, and these two function output coordinates in the image format, which is easier to plot on top of the original image.

Convert digit to vector octave/matlab [duplicate]

This question already has answers here:
Construct this matrix based on two vectors MATLAB
(3 answers)
Closed 8 years ago.
I have a vector y = [0; 2; 4]
I want to convert each element of it into vector, where all elements are zero but element with index equal to digit is 1.
I'd like to do it without loops.
For example [0; 2; 4] should be converted to
[1 0 0 0 0 0 0 0 0 0;
0 0 1 0 0 0 0 0 0 0;
0 0 0 0 1 0 0 0 0 0]
(in this example vector first index is 0)
The usual trick with sparse can be used to simplify the process. Let n denote the desired number of columns. Then
result = full(sparse(1:numel(y), y+1, 1, numel(y), n));
For example, y = [0;2;4] and 10 produce
result =
1 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0
First you need to decide how many digits you want to represent each number. In your case, you have 10 digits per number, so let's keep that in mind.
Once you do this, it's just a matter of indexing each element in your matrix. In your case, you have 10 digits per number. As such, do something like this:
y = [0; 2; 4]; %// Your digits array
out = zeros(numel(y), 10); %// 10 digits per number
ind = sub2ind(size(out), [1:numel(y)].', y+1);
out(ind) = 1;
The output should look like this:
out =
1 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0
Let's go through this code slowly. y defines the digits you want per row of the output matrix. out allocates a matrix of zeroes where the number of rows is defined by how many digits you want in y. out will thus store your resulting matrix that you have shown us in your post.
The number of columns is 10, but you change this to be whatever you want. ind uses a command called sub2ind. This allows to completely vectorize the assignment of values in your out matrix and avoids a for loop. The first parameter is an array of values that defines how many rows and columns are in your matrix that you are trying to assign things to. In this case, it's just the size of out. The second and third parameters are the rows and columns you want to access in your matrix. In this case, the rows vary from 1 to as many elements as there are in y. In our case, this is 3. We want to generate one number per row, which is why it goes from 1 to 3. The columns denote where we want to set the digit to one for each row. As MATLAB indexes starting at 1, we have to make sure that we take y and add by 1. ind thus creates the column-major indices in order to access our matrix. The last statement finally accesses these locations and assigns a 1 to each location, thus producing our matrix.
Hope this helps!

Index an Array using values from a Matrix, Matlab [duplicate]

This question already has answers here:
2D logical matrix from vector of coordinates (Basic matlab)
(2 answers)
Closed 9 years ago.
I would like to use values from a matrix to index an array. I will use a 3x2 matrix in the example but it could be a matrix of any height in the actual code. The array will be 5x5 in the example but could be a square array of any size. The size of the array and height of the matrix have no relationship.
Here is my code
X =
2 1
4 3
1 4
Grid=zeros(5,5)
Grid =
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
So i would like to access points 2,1 4,3 and 1,4 and add one to the value in that location.
I have tried the following code
Grid(X(:,1),X(:,2))=Grid(X(:,1),X(:,2))+1
Which gives this result
Grid =
1 0 1 1 0
1 0 1 1 0
0 0 0 0 0
1 0 1 1 0
0 0 0 0 0
Which is not what I require.
I have tried other ways with no luck, I think i could use a loop or create a FLAT array but don't really want to, I think there must be a more efficient way.
Anyone have any ideas? I'm using Matlab 2012b.
As always thanks for your time and any help you may be able to give.
Edit-1 Required Result
This is the result I would like
Grid =
0 0 0 1 0
1 0 0 0 0
0 0 0 0 0
0 0 1 0 0
0 0 0 0 0
Edit-2
The coordinate matrix may hold duplicate values, so I would like the value in the relative location in the Array (Grid in the example) to show how many times this coordinate occurs. So my solution is
Grid(sub2ind(size(Grid),X(:,1),X(:,2)))=Grid(sub2ind(size(Grid),X(:,1),X(:,2)))+1
Using the answer to 2D logical matrix from vector of coordinates (Basic matlab) that Oleg pointed me to. I managed to solve my question by converting subscripts to linear indexes:
pos = sub2ind(size(Grid), X(:,1), X(:,2));
Grid(pos) = 1;

Trim Binary Matrix in MatLab

I have a binary matrix like this:
0 0 0 0 0 0
0 0 0 1 0 0
0 1 0 0 0 0
0 0 1 0 1 0
0 0 0 1 0 0
0 0 0 0 0 0
and I want to trim this matrix (in other words, remove zeroes at the boundaries) to be like:
0 0 1 0
1 0 0 0
0 1 0 1
0 0 1 0
How to do this the "Matlab" way? that's not to use conventional loops and conditions.
To be clearer, the matrix should be reduced to start from the first column which has at least one 1, and ends at the last column with the same condition, inclusive. Any column out of this range should be removed. Same rules apply for rows.
Thanks.
If you have the data in matrix M...
x = find(any(M,2),1,'first'):find(any(M,2),1,'last');
y = find(any(M),1,'first'):find(any(M),1,'last');
M(x, y)
Or, if you know that there will be a 1 in every row/col except the edges:
M(any(M,2), any(M))
Extension to higher dimensions:
Assuming a 3D matrix to be trimmed, this is more straightforward:
M=rand(3,3,3); % generating a random 3D matrix
M(2,:,:)=0; % just to make a check if it works in extreme case of having zeros in the middle
padded = padarray(M,[2 2 2]); % making some zero boundaries
[r,c,v]=ind2sub(size(padded),find(padded));
recoveredM=padded(min(r):max(r),min(c):max(c),min(v):max(v));
check=M==recoveredM % checking to see if M is successfully recovered
You could use the fact that find can return row and column indices:
[r1, c1] = find(x, 1, 'first')
[r2, c2] = find(x, 1, 'last')
x(r1:r2, c1:c2)