How to Count Total Number of pixel of padded value used in image(Padded Image)? - matlab

I have one binary image so it has only 2 value like 0 and 1. After, I convert this into a padded image of different values, like the image will have curve shape. I took a 3 X 3 matrix of value and if i get curve shape then I padded the image with 1, or any number. I use 15 different types shape values like junction point, end point etc.
After, I give the values 1 to 15 - or the appropriate number according its shape. As such, I am getting an image like:
Figure
0 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 5 0 0 0 0 0 0 0 1 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 5 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 1 0 0 0 0 0 0 0 0 0 0
I would like to count how many 1s there are in the image, followed by 2s, 3s, etc. up to 15. For example,
as shown in the figure, if the pad number was 5, the total number of pixels would be 3. If the pad number was 1, the total number of pixels would be 6.

Use histc:
>> im = [ 0 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 5 0 0 0 0 0 0 0 1 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 5 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 1 0 0 0 0 0 0 0 0 0 0 ]; %// data
>> values = 1:15; %// possible values
>> count = histc(im(:), values)
count =
6 %// number of 1's
0 %// number of 2's, etc
0
0
3
0
0
0
0
0
0
0
0
0
0
Or compute it manually with bsxfun:
>> count = sum(bsxfun(#eq, im(:), values(:).'), 1)
>> count =
6 0 0 0 3 0 0 0 0 0 0 0 0 0 0

I can also suggest using accumarray:
im = [0 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 5 0 0 0 0 0 0 0 1 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 5 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 1 0 0 0 0 0 0 0 0 0 0 ]; %// data - borrowed from Luis Mendo
counts = accumarray(im(:) + 1, 1);
counts(1) = []
counts =
6
0
0
0
3
Note we have to offset by 1 as accumarray starts indexing the output array at 1. Because you want to disregard the 0s, I simply take the counts result and remove the first entry. This result agrees with what you are seeking. The first element is how many 1s we have encountered, which is 6. The last element is how many 5s you have encountered, which is 3. Because 5 is the largest number encountered in your image, we can say that all symbols after 5 (6, 7, 8, ..., 15) have a count of 0.

Related

How to draw 2 merging trees using an adjacency matrix in Matlab

I have an adjacency matrix describing two trees that merges in the middle. An exemple for 10 nodes:
The corresponding adjacency matrix is a 10x10 matrix where the first row correspond to the first node (start of the first tree, node #1) and the last row to the root of the second tree (end of the second tree, node #10).
Here is the adjacency matrix corresponding to a larger example with 22 nodes:
0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 0 0 1 1 0 0 0 0 0 0 0 0 0 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 0 0
0 1 0 0 0 0 0 1 1 0 0 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 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0
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 0 0 0 1 0 0 0 0 0 0
0 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 0 0 0 1 0 0 0 0 0
0 0 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 0 0 0 1 0 0 0 0
0 0 0 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 0 0 0 1 0 0 0
0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 1 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 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0
I'm trying to plot this adjacency matrix as the picture showed above using Matlab. Matlab as some tools for plotting trees, for example the code given in:
https://blogs.mathworks.com/cleve/2017/03/20/morse-code-binary-trees-and-graphs/
However, using the previous matrix (let's label it 'A') and the following code:
G = digraph(A);
Gp = plot(G);
does not produce a tree, but a graph (not ordered as a tree).
Thus, how to produce a picture of a tree (as showed above) using 'A' in Matlab?
Please note that I also have matrices describing trees where the degree between the children nodes are 3 (or more) rather than 2.
Zero-out half of your adjacency matrix to make the connection one-way.
By default, MATLAB tries to decide the layout of graphs automatically, based on the structure of your graph. There are a few different graph layouts you can choose from.
The option you wanted is the 'Layered' layout; but I tested it with your example, and it definitely still doesn't look like a tree. The reason being that your adjacency matrix is symmetrical, and the connection is two-way. This confuses MATLAB when placing the nodes, and it doesn't think it's a tree.
The easy fix, is you can zero-out the lower triangular half of your adjacency matrix. I used the function tril for this.
% Create a lower triangular matrix with the dimension of A,
idx = tril(ones(size(A)));
% Make it a logical array to select matrix elements with
idx = logical(idx);
% Select the defined lower triangular part, and set that to zero
A(idx) = 0;
% Generate-Plot graph as you did
G = digraph(A);
plot(G)
Result

How to correctly use the col2im function?

This function is confusing to use, and it always gives me an error:
To RESHAPE the number of elements must not change.
That's my code:
im=im2col(zeros(300,300),[3 3]);
im(:,9)=ones(9,1);
im=col2im(im,[3 3],[300 300]);
Basically, this code just gets the block at index 6, replaces it with ones, and reassembles it back into the original image. What's wrong with this code?
It seems you want to create distinct blocks from your input array, change single blocks, and rearrange them. (Your target size is the same as your input array size.) So, you must use the distinct parameter in both, im2col as well as col2im:
blk_size = [3, 3];
im = zeros(9, 9)
temp = im2col(im, blk_size, 'distinct');
temp(:, 3) = ones(prod(blk_size), 1);
im2 = col2im(temp, [3 3], size(im), 'distinct')
Output:
im =
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
im2 =
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 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 1 0 0 0 0 0 0
1 1 1 0 0 0 0 0 0
1 1 1 0 0 0 0 0 0
When using im2col with the sliding parameter, which is also the default, if no parameter is set at all, there'll be a lot more columns in the result than can be rearranged to the input array size, cf. the Tips section on im2col.
Hope that helps!

Matlab: keeping non-zero matrix elements adjacent to each other and ignoring lone elements

Here is an example matrix (but the result shouldn't be constrained to only working on this):
a=zeros(7,7);
a(5,3:6)=1;
a(2,2)=1;
a(2,4)=1;
a(7,1:2)=1
a=
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 0 0 0
0 0 1 1 1 1 0
0 0 0 0 0 0 0
1 1 0 0 0 0 0
I want to get rid of all the 1's that are alone (the noise), such that I only have the line of 1's on the fifth row.
rules:
-the 1's are in 'connected lines' if there are adjacent 1's (including diagonally) e.g.:
0 0 0 1 0 0 1 0 1
1 1 1 0 1 0 0 1 0
0 0 0 0 0 1 0 0 0
(The connected lines are what I want to keep. I want to get rid of all the 1's that are not in connected lines, the connected lines can intersect each other)
the 'connected lines need to be at least 3 elements long. So in the 7x7 example, there would only be one line that matches this criteria. If a(7,3) was set to 1, then there would be a connected line at the bottom left also
I am currently looking at this through a column by column approach, and here is the first draft of my code so far:
for nnn=2:6
rowPoss=find(a(:,nnn)==1);
rowPoss2=find(a(:,nnn+1)==1);
for nn=1:length(rowPoss)
if myResult(rowPoss(nn)-1:rowPoss(nn)+1,n-1)==0 %
%then?
end
end
end
My difficulty is, during this column by column process, I'd have to enable a way to recognise the beginning of the connected line, the middle of the connected line, and when a connected line ends. The same rules for this, when applied to noise (the lone 1's), would just ignore the lone 1's.
The output I want is basically:
b=
0 0 0 0 0 0 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 1 1 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
If you have image processing toolbox, try bwareaopen
b = bwareaopen(a, 3);
Sample Run #1:
>> a
a =
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 0 0 0
0 0 1 1 1 1 0
0 0 0 0 0 0 0
1 1 0 0 0 0 0
>> b
b =
0 0 0 0 0 0 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 1 1 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
Sample Run #2:
>> a
a =
0 0 0 0 0 0 0
0 1 0 1 0 0 0
0 0 1 0 0 0 0
0 0 0 0 0 0 0
0 0 1 1 1 1 0
0 0 0 0 0 0 0
1 1 0 0 0 0 0
>> b
b =
0 0 0 0 0 0 0
0 1 0 1 0 0 0
0 0 1 0 0 0 0
0 0 0 0 0 0 0
0 0 1 1 1 1 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0

Find out first circle in an image on Matlab (wrt. y-axis)

I'm using Matlab. I have a 2-D Binary image/array. like this
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
0 0 0 0 0 1 1 1 0 0 1 0 0
0 0 1 1 0 0 1 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0 0 0 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 0 0
0 0 0 0 0 0 1 0 0 0 0 0 0
I want to find out center of very first white block/Circle with respect to y-axis
Answer of the above image will be.
0 1 0
1 1 1
0 1 0
Anyone who have have a simplest solution for this.
If you are looking for exact matches of the template, you can use a moving filter, one example is:
H=[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;
0 0 0 0 0 1 1 1 0 0 1 0 0;
0 0 1 1 0 0 1 0 0 0 0 0 0;
0 0 0 1 0 0 0 0 0 0 0 0 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 0 0;
0 0 0 0 0 0 1 0 0 0 0 0 0];
b=[0 1 0;
1 1 1;
0 1 0];
C=filter2(b,H, 'same');
[x,y]=find(C==max(max(C)));
x and y are the locations of your template in the order that it appears from the top left corner of your array.
Edit: if you have the Image Processing Toolbox and are looking for a less strict way of finding objects that have a roughly circular shape you can use regionprops with the 'Centroid' and 'Eccentricity' arguments with the bwconncomp function.
ObjectStats=regionprops(bwconncomp(H,4), 'Centroid', 'Eccentricity');
Objects with an 'Eccentricity' of 0 (or close to 0) will be the circles.
idx=find(cell2mat({ObjectStats.Eccentricity})==0); % Change ==0 to <0.2 or something to make it less strict.
ctrs={ObjectStats.Centroid};
>> ctrs{1,idx(1)}
ans =
7 3
Note that in your case, a lone pixel is an object with an eccentricity of 0, it is the smallest 'circle' that you can find. If you need to define a minimum size, use the 'Area' property of regionprops
You can do this with a simple 2 dimensional convolution. It will "overlay" the filter along a larger matrix and multiply the filter by the values it is overlaying. If the product is equal to the sum of the filter, then you know you found a match.
Here is some simple code.
mat = [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
0 0 0 0 0 1 1 1 0 0 1 0 0
0 0 1 1 0 0 1 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0 0 0 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 0 0
0 0 0 0 0 0 1 0 0 0 0 0 0];
filt = [0 1 0
1 1 1
0 1 0];
[row,col] = find(conv2(mat,filt,'same') == sum(filt(:)))

How to replace elements of a matrix by an another matrix in MATLAB?

How to replace elements of a matrix by an another matrix in MATLAB?
Ex: let say if we have a matrix A, where
A=[1 0 0; 0 1 0; 1 0 1]
I want to replace all ones by
J=[1 0 0; 0 1 0; 0 0 1]
and zeros by
K=[0 0 0; 0 0 0; 0 0 0]
So that I can get 9x9 matrix. So how we will code it in MATLAB
Thanks
Sounds like you might want to take a look at the kronecker tensor product. This is not a general case but the idea should work for what you want
>> kron(A==1,J)+kron(A==0,K)
ans =
1 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 0 1 0 0 0 0 0
0 0 0 0 1 0 0 0 0
0 0 0 0 0 1 0 0 0
1 0 0 0 0 0 1 0 0
0 1 0 0 0 0 0 1 0
0 0 1 0 0 0 0 0 1
which, for the example case, would simplify to a simpler command:
>> kron(A,J)
ans =
1 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 0 1 0 0 0 0 0
0 0 0 0 1 0 0 0 0
0 0 0 0 0 1 0 0 0
1 0 0 0 0 0 1 0 0
0 1 0 0 0 0 0 1 0
0 0 1 0 0 0 0 0 1
You can do:
A2=imresize(A,size(A).*size(J),'nearest');
J2=repmat(J,size(A));
K2=repmat(K,size(A));
A2(A2==1)=J2(A2==1);
A2(A2==0)=K2(A2==0)