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):
Related
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:
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)
how can i count number of particles in each grid box in this code
here is my code below:
xyRange=[1,5];
P=3;
vx=0.6;
vy=0.4;
X=[];
Y=[];
for day=1:5
X=[X;randi(xyRange,P,1)];
Y=[Y;randi(xyRange,P,1)];
X=X+vx;
Y=Y+vy;
end
plot(X,Y,'kd');
grid on;
axis([1,50,1,50]);
j = floor(X/5)+1;
k = floor(Y/5);
box = k*10+j;
If you have the Statistics Toolbox, the easiest way is to use hist3.
In your case, when I plotted the grid, it looks like each box was separated in units of 5. As such, the command is very simply this:
cnt = hist3([X,Y], {0:5:50 - 2.5, 0:5:50 - 2.5});
X and Y are your 2D data points, and the second element is a cell array of X and Y values which denote the centres of each of the points in each grid. Take note that the points that are defined are with respect to the origin being at the top left corner. If you want to make sure that the origin is at the bottom left corner, you would actually need to do this:
cnt = flipud(cnt.');
On my run I get this:
cnt =
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 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 1 6 0 0 0 0 0 0 0 0
0 5 3 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
When producing your plot, I get this:
If you compare the counts in comparison to the grid produced at the top, you'll see that the match. However, because of the way I specified the centre of the bins, the first and last row, and the first and last column are meaningless, so you can safely eliminate these from your analysis.
If you want a nice pictorial example of this, call hist3 without any output arguments:
%// Plot 2D histogram with some transparency
hist3([X,Y], {(0:5:50) - 2.5, (0:5:50) - 2.5}, 'FaceAlpha', 0.65);
%// Set height of each bar coloured according to height
set(get(gca,'child'),'FaceColor','interp','CDataMode','auto');
view(-34,68); %// Change camera view for better look
We get this:
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.
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)