Matlab FingerPrint Minutia Extraction - matlab

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.

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)

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 imdilate structural element origin confusion

Consider the following operation:
a =
0 0 0 0
0 1 0 0
0 0 1 0
0 0 0 0
b=imdilate(a,[1,1;1,1])
b =
0 0 0 0
0 1 1 0
0 1 1 1
0 0 1 1
The above result indicates the origin of the structual element is [2,2]. If the origin is floor((size([1,1;1,1])+1)/2)=[1,1] by the definition (http://www-rohan.sdsu.edu/doc/matlab/toolbox/images/morph4.html)
b=
1 1 0 0
1 1 1 0
0 1 1 0
0 0 0 0
What's wrong with my understanding? Thank you!
You are correct that the origin is [1,1], but the origin is in the structuring matrix (2nd input), not the image matrix a (1st input).
Think about placing element [1,1] of your 2x2 structuring matrix on the non-zero values of a and you will see how the imdilate result is correct.
The Mathworks online help has a really nice explanation of dilation.
OK,Ithink I have found the answer.
Similar to convolution, in dilation the structuring element is reflected through its center (rotated 180 degrees) before the max operation is applied.

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;