assigning coordinate to a matrix in MATLAB - 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.

Related

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

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

Determine matrix boundary without loops

I have got a 2D matrix. There is some region in the matrix where the elements are non-zero, in particular everywhere around the edge they are zero.
I plot the matrix using image as a colorplot and would like to add the curve that shows the boundary between non-zero values to zero values in the matrix. Is there any neat way to do this without loops?
This looks like a job for convhull :
To illustrate this code i'll take a dummy example :
A=zeros(10);
B=binornd(1,0.5,8,8);
A(2:end-1,2:end-1)=B
A =
0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0
0 0 1 1 1 1 1 1 0 0
0 0 1 1 0 0 0 0 1 0
0 0 0 1 0 0 0 1 0 0
0 1 0 0 0 0 0 1 0 0
0 0 0 1 1 1 1 1 1 0
0 0 1 0 1 1 1 1 0 0
0 1 0 1 1 1 1 0 1 0
0 0 0 0 0 0 0 0 0 0
1/ Find the locations of all non zero entries :
[row,col]=find(A);
2/ Take the convex hull of these locations
k=convhull(row,col);
3/ Plot the convex hull (I plot the non zero points aswell but in your problem it will be your image points)
plot(row(k),col(k),'r-',row,col,'b*')
Result :
Another option is using the image processing toolbox and the bwperim function. This will work if you know that your area is completely closed (i.e. has no holes in the boundary)
This is an example using a black and white image, and you have 2 options: fill the inner gaps before, or not. You can see in the result the differences.
A = imread('circles.png');
Afill=imfill(A,'holes'); % optional
Abound1=bwperim(Afill);
Abound2=bwperim(A);
imshow([A,Abound, Abound2])
You can plot one on top of the other with:
[x,y]= find(Abound2);
hold on
image(A*255) %// If A is logical, else use just A (not *255)
colormap('gray')
plot(y,x,'r.')
hold off
axis tight
If you have a gray-scale image (or a matrix with a single value in each position (2D matrix), then you can binarize it first by either:
If you know everything outside your object is EXACTLY zero
A=yourA>0;
If you want to separate your object from the background, and the background is not exactly zero by A=im2bw(yourA,level), by choosing your own level, or letting Otsu do it for you with level=graythresh(yourA)

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.

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)