I have a binary image. I have several single pixels in images. Single pixels are white (1) and all of their neighborhoods are black (0). for example image below shows a single pixel (at center) and two pixels (at left-bottom):
0 0 0 0 0
0 0 0 0 0
0 0 1 0 0
0 0 0 0 0
1 1 0 0 0
How can I remove single pixels with morphological operations in Matlab?
I give you another option without loop, using a 2D convolution with conv2:
M = [0 0 0 0 0
0 0 1 0 0
0 0 0 0 0
0 0 0 0 0
1 1 0 0 0]
C = [0 1 0
1 1 1
0 1 0]; % The matrice that is going to check if a `1` is alone or not.
%if you also want to consider the neibhbors on the diagonal choose:
%C = ones(3);
R = M.*conv2(M,C,'same')>1 %Check for the neighbors.
RESULT
R =
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
1 1 0 0 0
Upon request by the OP, I'm converting my short comment into a reply:
Since you explicitly asked for morphological operations: bwmorph has a 'clean' option which is described as "Removes isolated pixels (individual 1s that are surrounded by 0s)" with an example close to yours. Have a look at the bwmorph documentation page.
As in your previous question, you can use bwboundaries:
if P is the binary image, than:
B = bwboundaries(P,8);
for k = 1:numel(B)
if size(B{k})<=2
P(B{k}(1,1),B{k}(1,2)) = 0;
end
end
So for the example above P becomes:
P =
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
1 1 0 0 0
Related
I have this following matrix:
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 1 0 0 0 0 0
1 0 0 0 0 1 1
1 0 0 0 0 1 1
And I want to dilate it with the following structuring element:
1 0 0
1 1 1
1 1 1
I already did dilation on Matlab but the result does not match with the one I did by hand. So I guess I missing something here. As far as I know if any '1' of the structuring element touches any of the '1' in the matrix, then it means it is a hit and the center of the current window should be set as 1. If I make dilation in such fashion I would get following (without considering edges):
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 1 1 0 0 0 0
1 1 1 0 1 1 0
1 1 1 0 1 1 1
1 0 0 0 0 1 1
But Matlab gives the following result:
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 0 0
1 1 1 0 1 1 0
1 1 1 0 1 1 1
1 1 0 0 1 1 1
Without considering edges it almost looks like my result but pixels styled with bold are '1' in my result but '0' in Matlab's result. What am I doing wrong? Pixel just below those '0's are '1's in the original image and the structuring element has '1' at that space when the center of the window is on those '0's so it is a hit and the center must be set '1' but Matlab doesn't do this. Can anyone explain me why? Am I missing something essential here?
Suppose matrix A is your image and matrix B is structuring element. You should pad the matrix A with zeroes on all sides. So let's say you have matrix C. Then you should perform Logical AND operation of C and B. The result matrix called D will be a dilated matrix. For further information, please see here.
Here is the code of Matlab which dilate image without 'imdilate' function:
clc;clearvars;close all;
%Image Dilation without using 'imdilate' function
% Matrix A is our image
A=[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 1 0 0 0 0 0;
1 0 0 0 0 1 1 ;
1 0 0 0 0 1 1 ];
%Structuring element
B=[1 0 0; 1 1 1; 1 1 1];
%Pad zeros on all the sides
C=padarray(A,[1 1]);
%Intialize a matrix of matrix size A with zeros
D=false(size(A));
for i=1:size(C,1)-2
for j=1:size(C,2)-2
%Perform logical AND operation
D(i,j)=sum(sum(B&C(i:i+2,j:j+2)));
end
end
display(D);
And this is my output, dilated matrix D:
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 need a matlab script that is going to return the n nodes of maximum degree in a graph.
For exemple:
N = maxnodes(Graph,n)
Graph is a matrix
n the number of nodes that we need
N is a vector that conatains the n nodes.
Here is my source code (script). But it doesn't work well.
M = [0 1 0 0 0 1 1 0 0 0 0 0 0 0 0 0;
1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0;
0 0 1 0 1 0 0 1 0 0 0 0 0 0 0 0;
0 0 1 1 0 1 0 0 0 0 0 1 0 0 0 0;
1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0;
1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0;
0 0 0 1 0 0 0 0 1 1 0 0 0 0 0 0;
0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 1;
0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0;
0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0;
0 0 0 0 0 0 0 0 0 1 1 0 1 0 0 0;
0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0;
0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0;
0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 1;
0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0;];
n = 5; % The number of nodes that we want
G=[]; % I'll store here the n nodes of maximum degree
for i=1:size(M)
G1(1,i)=sum(M(i,:)); % I'm storing each node with its degree in G1
G1(2,i)=i;
C(1,i)=G1(1,i); %I store only degree of nodes
end
C1 = sort(C,'descend'); % I sort "descendly" the degrees of nodes
for i=1:n %We want to take only the n nodes that we need and save it in C2
C2(1,i) = C1(1,i);
end
C2; % This vector stores the n descend maximum degrees that I need.
%My actual problem is here. How could I find the node that correspond to each degree?
%I tried to do it with the following loop:
for j=1:n
for i=1:size(M)
if C2(1,j) == G1(1,i)
G2(1,j)=G1(2,i);
end
end
end %But this loop doesn't store well the nodes in G2 because it repeats nodes.
G2
You have absolutely shown no effort so you actually shouldn't be getting any help from anyone.... but I love graph problems, so I'll throw you a bone.
I'm going to assume that Graph is an adjacency matrix, where each element (i,j) in the matrix corresponds to an edge connected between the two nodes i and j. I also am assuming that you have an undirected graph as input. If you examine the nature of the adjacency matrix (that Wikipedia article has a great example), it's not hard to see that the degree of a node i is simply the sum over all of the columns of row i in the adjacency matrix. Recall that the degree is defined as the total number of edges connected to a particular node. As such, all you have to do is sum over all of the columns for each row, and determine the rows that have the largest degree in your graph. Once we do this, we simply return the nodes that have this largest degree, which is up to n.
However, we will put in a safeguard where if we specify n to be larger than number of nodes having this maximum degree, we will cap it so that we only show up to this many nodes rather than n.
Therefore:
function [N] = maxnodes(Graph, n)
%// Find degrees of each node
degs = sum(Graph, 2);
%// Find those nodes that have the largest degree
locs = find(degs == max(degs));
%// If n is larger than the total number of nodes
%// having this maximum degree, then cap it
if n > numel(locs)
n = numel(locs);
end
%// Return those nodes that have this maximum degree
N = locs(1:n);
Here is a script that works very well and solves my problem. Otherwise, I would have liked well that my source code above would be debug.
function N = maxnodes(M,n)
nb1_rows= sum(M,2);
[nbs,is] = sort(nb1_rows,'descend');
N = transpose(is(1:n));
I have a 480-by-640 matrix A. For each pixel, I want to check its neighbors. The neighbors of the pixel are determined by a value N. For example, this is a part of matrix A where all the zeros are the neighbours of pixel X when N=3:
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 X 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
As shown, because N=3, all these zeros are pixel X's neighbors. The problem is if X is located before the index N=3. Here the neighbors will be pixels with one values:
X 1 1 1 0 0 0
1 1 1 1 0 0 0
1 1 1 1 0 0 0
1 1 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
Could anyone advise on how to handle this?
The simplest way to proceed is just to pad your array with with values that do not return true for whatever you are checking (say, if you're looking for nonzeros, pad with zeros, or if you're looking for finite values, pad with NaN.) The padarray function can do this for you, but requires the Image Processing Toolbox*. Otherwise, you can pad arrays yourself. For example, an unoptimized way to proceed might be
A = rand(m,n);
Apadded = [zeros(N,2*N+n); [zeros(m,N), A, zeros(m,N)]; zeros(N,2*N+n)];
for i = N+1:N+m+1
for j = N+1:N+n+1
% Process neighborhood of A(i,j)
end
end
*Also note that these sorts of "sliding neighborhood" operations, being common in image processing, are implemented for you in the Image Processing Toolbox.
i am making image compression in matlab.
After i applied DCT on image and i had img matrix, i want to apply a threshold mask on that matrix.
mask = [1 1 1 1 0 0 0 0
1 1 1 0 0 0 0 0
1 1 0 0 0 0 0 0
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];
maskedImg = blkproc(img,[8 8],mask );
I used that function but it didnt work and i get error message:
Error in ==> blkproc at 67
[a, block, border, fun, params, padval] = parse_inputs(varargin{:});
According to latest Matlab documentation; closest blockproc syntax (for your case) is B = blockproc(A,[M N],fun). So apparently your mask really should be a function!
However, I recall that blkproc has been a valid Matlab function for a while ago, thus double check the proper way to call it by typing (in the command line) > help blkproc. (Al tough I'm quite confident that it will share the calling signature with blockproc [in this case]).