How can I loop over a binary image to get 4 equal quadrants always?

I am following this steps to get 4 equal quadrants from a binary image:
r1=q1(1:size(q1,1)/2,1:size(q1,2)/2,:);
r2=q1(size(q1,1)/2+1:size(q1,1),1:size(q1,2)/2,:);
r3=q1(1:size(q1,1)/2,size(q1,2)/2+1:size(q1,2),:);
r4=q1(size(q1,1)/2+1:size(q1,1),size(q1,2)/2+1:size(q1,2),:);
After this, I want to get 4 equal quadrants from r1,r2,r3,r4 indivisually. This process will continue as long as we can get 4 equal quadrants . How can I simply do this with the help of any loop.

3 Comments

Why do you have a 3rd dimension in a binary image?
To confirm: if the original image happened to be a power of 2 on each side, such as 512 x 512, then you would want the division into equal quadrants to continue right down to the point where the quadrant sizes were 1 x 1 ? But for a 513 x 513 matrix, then no sub-division would be done, since you cannot make equal quardrants ?
Walter Roberson: I am working on set of images.images are of different sizes. Now what I am doing I am taking two square sized boxes from both side of centroid. After that I want to do this division work individually on both the square sized blocks as long as I can get 4 equal quadrants.

Sign in to comment.

Answers (2)

Using 4 distinct variables is less convenient than reshaping the array:
s = size(q1);
q2 = reshape(q1, s(1)/2, 2, s(2)/2, 2);
Now you have e.g. your r4 stored in q2(:, 2, :, 2). In general:
s = size(q1); % Assuming that q1 is a binary image ==> 2D!
% How often can the size be divided by 2:
n = min(sum(factor(s(1)) == 2), sum(factor(s(2)) == 2));
twos = repmat(2, 1, n);
div = 2^n;
qq = reshape(q1, [s(1) / div, twos, s(2) / div, twos]);
Perhaps you want to permute the array (you did not mention, what you need as output).
qq = permute(qq, [1, n+2, 2:n+1, n+3:2*n+2]);
% And maybe:
qq = reshape(qq, s(1)/div, s(2)/div, []);
Now qq(:, :, i) contains the i.th quadrant.

3 Comments

I want to get no of white pixels count
What is "no of white pixels count" and what is the relation to the original question?
Number of white pixels in each blocks. You asked me about the output

Sign in to comment.

function splitted = rsplit4(img)
[r, c, p] = size(img);
if mod(r,2) || mod(c,2)
splitted = img;
else
splitted = {rsplit4(img(1:end/2,1:end/2, :)), rsplit4(img(1:end/2,end/2+1:end, :));
rsplit4(img(end/2+1:end,1:end/2,:)), rsplit4(img(end/2+1:end,end/2+1:end,:))};
end
end

13 Comments

I am getting this error
Function definitions are not permitted in this context.
a = imread('image1.png');
img =bwareafilt(~a, 1);
m=rsplit4(img);
function splitted = rsplit4(img)
[r, c, p] = size(img);
if mod(r,2) || mod(c,2)
splitted = img;
else
splitted = {rsplit4(img(1:end/2,1:end/2, :)), rsplit4(img(1:end/2,end/2+1:end, :));
rsplit4(img(end/2+1:end,1:end/2,:)), rsplit4(img(end/2+1:end,end/2+1:end,:))};
end
end
You cannot define a function at the command prompt.
If you are using R2016a or earlier, you cannot define a function as part of a script and would need to store the function I posted as rsplit4.m
If you are using R2016b or later, you can define a function as part of a script. But you might as well store the function I posted as rsplit4.m so that you can use it from multiple places.
Ok I am done this.
now calling
m=rsplit4(image1);
Now m is 79X79 logical that is the original size of the image1. where I will get all the eual sized blocks?
I want to get access of all the blocks as want to count number of white pixels.
The 79 x 79 result is the only block.
You need to define more clearly how you want to handle even and odd sizes. If you have:
ABCDEFGH
then where would you divide that, what would go into each half? And if you had
ABCDEFGHI
then how would you divide that, what would go into each half?
When you talk about "on each side of the centroid", that could imply that you want to divide as ABCD and FGHI since the centroid is at E and those two would be "on each side" of the centroid. However, if you do this, then you are likely to miscount the whitespace that occurs on column E.
I am finding out the left, right and top distances from centroid upto it's boundary box. Then considering the maximum distance as a length for the square that I am going to take from the both side.
Here I can't store all quadrants with this code. I am always getting back to my original image here.
Are you saying that the taking of quardants should be based upon the content of the image ?
What if there was a blob that looked like
**
**
**
********************
**
**
**
Centroid is 7.25 into the middle row. Maximum distance from centroid to bounding box is 12.75. But 12.75 to the left of the centroid is outside the image.
you please give me the idea how i will store all the quandrants from the last iteration. I have taken two equal size blocks from both the sides of centriod. Now I am considering each block as separate image. As both the images are of square sized so its becoming easy for me to get 4 equal quadrants. But problem is I want to continue this process till I get 1x1 size quadrants. After getting all the quadrants I want to calculate number of white pixels from each quadrants. mean first I am getting 80X80. Diving it into four parts so four 20x20,next four 10x10 and so on. I want to do this in loop.
The rsplit4 code I posted would take an 80 x 80 and convert it to a 2 x 2 cell array, each entry of which was a 2 x 2 cell array, and so on, until it got down to 5 x 5. After 5 x 5, it can no longer divide the into equal parts -- not unless it leaves out rows and columns like I was asking about in the ABCDEFGHI example (which you did not answer.)
Can I get something like the attached picture ?
Can I store all the small equal equal quadrants in cell array or something so that can get white pixels count ?
I do not see an attached picture.
The code I posted creates hierarchy of cell arrays. It does not assume that all of the subarrays will be the same size.
Anyhow: take the code I posted, and change the
splitted = img;
to
splitted = nnz(img);
then in the other assignment to splitted, change the { } brackets to [ ] brackets.
Note that if your image happens to be a power of 2 in each direction, then the output will happen to exactly equal the input when the input is a binary matrix, because you keep subdividing into quadrants until you get down to 1 x 1, and the number of whitespace elements in that is the same as the question of whether the pixel is true or not.
Sorry,I have attached now.
by changing
splitted = nnz(img);
and {} to [] not getting white pixels count of one block. but i want to get for all the blocks like i have attached the picture
Note that if your image happens to be a power of 2 in each direction, then the output will happen to exactly equal the input when the input is a binary matrix, because you keep subdividing into quadrants until you get down to 1 x 1, and the number of whitespace elements in that is the same as the question of whether the pixel is true or not.
I was doing this :
rowMid = ceil(rows / 2);
colMid = ceil(columns / 2);
So you have, in this example, an 80 x 160 image, and you want to sub-divide down to 10 x 10 ? It is not clear why you did not continue on to 5 x 5.
The centroid of the 80 x 160 would be at (40, 80), and the maximum horizontal or vertical distance from the centroid to the edge would be 80. Your previous requirements say that we must take an 80 x 80 square on each side of the centroid. However, with the centroid being at (40,80), we cannot take an 80x80 square to either side of it.

Sign in to comment.

Asked:

on 17 Apr 2019

Commented:

on 17 Apr 2019

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!