How to add legend in a highlighted graph? - matlab

I want to add legend in a graph G according to different highlighted edges. Is it possible to do it with only one graph G?
Here is a toy example to play with. I have a plot G.
adj =[0 0 1 1 1; % adjacency matrix
1 0 1 0 1;
0 1 0 1 1;
1 1 1 0 1;
0 0 1 0 0]
G = digraph(adj);
I highlighted all edges with 3 colors according to types of edges. 3 types of edges indicate there are 3 different relation between nodes in my case.
This is how I highlighted all edges:
M(:,:,1)=[0 0 1 0 0;1 0 0 0 1;0 0 0 0 0;1 0 0 0 0;0 0 1 0 0];
M(:,:,2)=[0 0 0 1 0; 0 0 1 0 0;0 1 0 0 1;0 0 0 0 0;0 0 0 0 0];
M(:,:,3)=[0 0 0 0 1; 0 0 0 0 0; 0 0 0 1 0;0 1 1 0 1;0 0 0 0 0];
The difficulty in my problem is that I have to remove vertices whose out-degree is less than some integel (say it's 2). Thus I can't plot 3 graphs independently.
rmvNode=find(outdegree(G)<2); % outdegree is the reason why single G is neccesary
adj(rmvNode,:)=[]; adj(:,rmvNode)=[];
M(:,rmvNode,:)=[]; M(rmvNode,:,:)=[];
G=digraph(adj);
Then we can plot it.
for k=1:3 %Looping depending on the third dimension
[r,c]= find(M(:,:,k)); %Finding non-zero elements
s{k}=r; t{k}=c;
end
h=plot(G);
highlight(h,s{1},t{1},'EdgeColor','r');
highlight(h,s{2},t{2},'EdgeColor','g');
highlight(h,s{3},t{3},'EdgeColor','b');
My ideal situation would be a legend like this: assign red edges to label 'type 1', assign blue edges to 'type 2', and assign green ones to 'type 3'. I want something like this:
Once more: I can't plot 3 graphs independently according to 3 pages in M, combine 3 plots together and then add a legend. Because as you can see, outdegree requires a whole graph G as input, it's not viable to divide G into G1, G2 and G3.

One way would be to manipulate the legend function by adding an invisible plot like this:
%put this at the end of your code
hold on; %to retain current plot
ax=plot(NaN,NaN,'r',NaN,NaN,'g',NaN,NaN,'b'); %plotting invisible points of desired colors
legend(ax,'Type 1','Type 2','Type 3'); %adding the legend
which gives:

Related

How to assign specific values to colours in imagesc

I'm trying to assign three possible values of a matrix to three colours when plotted using imagesc in MATLAB.
All I want is imagesc() to represent 0 as white, 1 as black and 2 as red.
Initially imagesc() does this, but as the for-loop proceeds, the colours for 1 and 2 get swapped.
I have tried re-ordering the colours assigned to colormap(), but the colours still swap.
Here is my code:
Grid = 10;
M = zeros(Grid);
M(3,1:3)=1;M(2,3)=1;M(1,2)=1;
Black = [0 0 0];
White = [1 1 1];
Red = [1 0 0];
Background = White;
colormap([Background; Red; Black])
figure()
imagesc(M)
...so far, so good. I have five black squares in the corner.
However as my loop proceeds and 2's are introduced, the matrix looks like this:
0 0 0 0 0 0 0
0 2 1 0 0 0 0
1 0 1 0 0 0 0
0 1 1 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 0 0 0
but now the image shows BLACK for 2, and RED for 1.
How do I maintain the colour-to-value relationships?
Your main mistake is having the red and black colors reversed in your colormap. You probably did this because putting the colors in the correct order made the pixels red in your first matrix - which was unwanted. The reason for this is the way pixel values are mapped to colormap colors, which can be seen by showing a colorbar. Your custom colormap happened to work because red was used for pixels with a value of about 0.5 - of which there were none.
What you need to do is correctly set the color limits for your axes:
colormap([Background; Black; Red])
set(gca, 'CLim', [0 2]);
Then, this is what would happen for the initial matrix (note that there are no red pixels in the image, but the colormap is ready for them nonetheless):

Color discrimination of matrix connected components

In Matlab, I have a matrix M, say:
M=[0 0 2 2 0 0
0 0 2 2 0 3
1 1 2 2 3 3
1 1 0 0 0 0
1 1 0 0 0 0];
with some connected components labeled 1,2 and 3.
I need to discriminate the components (1, 2 and 3) by using different colors (red, green and blue for example). Any help to do this. Thanks in advance
You can use image and colormap. From the documentation of the former,
image(C) displays the data in array C as an image. Each element of C
specifies the color for 1 pixel of the image.
When C is a 2-dimensional m-by-n matrix, the elements of C are used as
indices into the current colormap to determine the color. For 'direct' CDataMapping (the default),
values in C are treated as colormap indices (1-based if double, 0-based
if uint8 or uint16).
Thererfore, you only need to call image(M+1), so that the values start at 1; and then define a suitable colormap. The colormap is a 3-column matrix, where each row defines a color in terms of its R, G, B components.
M = [0 0 2 2 0 0;0 0 2 2 0 3;1 1 2 2 3 3;1 1 0 0 0 0;1 1 0 0 0 0];
imagesc(M+1) % add 1 so that values start at 1, not 0
cmap = [1 1 1; % white
.7 0 0; % dark red
0 .7 0; % dark green
0 0 .7]; % dark blue
colormap(cmap) % set colormap
axis tight % avoid white space around the values
axis equal % aspect ratio 1:1

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.

How to color a matrix?

I have a matrix in matlab of the following form:
A=[1 1 1 -1 -1
0 1 0 1 0
0 1 1 1 1
2 2 0 1 2
2 2 2 2 -1]
This matrix represents a map in the plane. Every A(i, j) is a cell in this map. I want to give color to each cell according to its number. So:
If(A(i, j)<=0)
color(A(i, j)) with black
Elseif(A(i, j)==k)
color(A(i, j)) with color k other than black
end
How to do this in matlab? Any suggestions please?
You can define a number of colours that you want using hsv or manually.
hsv(3)
ans =
1 0 0
0 1 0
0 0 1
Then use colormap to specify the color map.
colormap(hsv(3))
and then use imagesc
imagesc(A)
If you want to specify the colour also it is easy:
a = hsv(3)
a(1,:) = 1; % make the first color white
a(3,:) = 0; % make the last color black
a =
1 1 1
0 1 0
0 0 0
colormap(a)
imagesc(A)

From 4-connectivity to 8-connectivity in MATLAB

Say I have an boundary image in a logical matrix where true means boundary and false means region interior. The image encodes a tessellation of a 2D domain.
I was wondering if there is a compact way in MATLAB to "fix" those pixel neighborhoods where the separation between adjacent regions is only 4-connected and transform them into 8-connected in a manner that preserves the topology of the tessellation.
I believe this can be done with LUTs, but I'm not sure how to proceed. Do I have to, and if so, how do I exactly evaluate all the 3x3 pixel regions where the connectivity is only 4-wise to fill-in the corresponding pixels?
My proposed solution: use BWHITMISS to find the pixels whose neighborhood is at least 4-connected, dilate the result with a rectangular-shaped structuring element to convert those neighborhoods to 8-connected, finally we combine with the original image using logical-OR.
Example:
bw = [
0 0 0 1 0 1 0
0 0 1 1 1 1 1
0 1 1 1 0 1 0
0 0 1 0 1 0 0
0 1 1 0 0 0 0
0 0 1 0 1 1 1
0 0 1 0 0 1 0
];
hm = bwhitmiss(bw, [0 1 0; 1 1 1; 0 1 0]); %# [-1 1 -1; 1 1 1; -1 1 -1]
bw2 = imdilate(hm,ones(3)) | bw;
We can visualize the result:
[r c] = find(hm);
subplot(121), imshow(bw), hold on, plot(c(:),r(:),'o')
subplot(122), imshow(bw2)