I get an image and also the boundary of regions in the image. For example, I have a mask with logical type, the value of boundary is 1, while for other pixels, the value is 0. I want to label the regions segmented by the boundaries, while I am not sure how to segment and label the region based on the continuous boundary.
The boundary looks like this:
0 0 0 1 0 0 0 1 0 0
0 0 1 0 0 0 0 1 0 0
1 1 0 1 0 0 0 1 0 0
0 0 0 0 1 0 1 0 0 0
With the above diagram, there would be four regions that would be identified.
The function bwlabel from the image processing toolbox is the ideal function you should use to label each continuous region of non-zero pixels in a binary mask. However, you want to perform this on the zero pixels that are delineated by the "boundary" pixels that are set to 1. Therefore, simply use the inverse of the binary mask so that you are operating on the zero pixels instead of the non-zero pixels. Also from your definition, regions are separated using a 4 pixel connectivity. bwlabel by default uses 8 pixel connectivity when searching for continuous regions, which means that it looks in the N, NE, E, SE, S, SW, W and NW directions. You'll want to manually specify 4 pixel connectivity, which looks in only the directions of N, E, S and W.
Supposing your mask was stored in the variable L, simply do:
labels = bwlabel(~L, 4);
The output labels would be a map that tells you the membership of each pixel. Regions of the same membership tells you that those pixels belong to the same group.
Using your example, we get:
>> L = [0 0 0 1 0 0 0 1 0 0
0 0 1 0 0 0 0 1 0 0
1 1 0 1 0 0 0 1 0 0
0 0 0 0 1 0 1 0 0 0];
>> labels = bwlabel(~L, 4)
labels =
1 1 1 0 3 3 3 0 4 4
1 1 0 3 3 3 3 0 4 4
0 0 2 0 3 3 3 0 4 4
2 2 2 2 0 3 0 4 4 4
Each island of zeroes has a unique ID where pixels that belong to same ID belong to the same island or region. If you don't want to use bwlabel and do this from first principles, you can refer to my previous post using Depth First Search to find regions of connected components: How to find all connected components in a binary image in Matlab?. Be advised that this is not efficient code and so you should only use it for educational and research purposes. Using bwlabel is recommended as it is a fast function and well tested. You'll also have to modify the code so that it doesn't search in an 8 pixel connectivity and it should look at only a 4 pixel connectivity. Make sure you also inverse the input before using the code.
Related
I wrote the following code:
imageResult = imshowpair(brain1, brain2,'checkerboard');
But this does not control the checkerboard size.
How can I specify what should the checkerboard square size be?
The imshowpair doc is not clear on that.
If you know a different way , please feel free to suggest it as well!
I don't think that there is an option to do that automatically.
But you can create a checkerboard index manually using the kronecker tensor product.
ind = kron(eye(2,2),ones(5,5))
produce a 2x2 checkerboard with a grid size of 5:
1 1 1 1 1 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0
0 0 0 0 0 1 1 1 1 1
0 0 0 0 0 1 1 1 1 1
0 0 0 0 0 1 1 1 1 1
0 0 0 0 0 1 1 1 1 1
0 0 0 0 0 1 1 1 1 1
You can now duplicate this pattern N times.
For example we duplicate this pattern 10 times.
ind = kron(ones(10,10),ind)
If your images are 3D images, you can still replicate this matrix 3 times:
ind = repmat(ind,1,1,3);
So you obtain a 2X5X10 x 2X5X10 (500x500) checkerboard matrice
Now you can combine your two images, that need also need to be 500x500:
IMG1 = IMG1(logical(ind)) = 0 % an index need to be of type logical.
IMG2 = IMG1(logical(~ind)) = 0
IMG = IMG1+IMG2
If it's impossible to get a checkerboard matrice of the right size because your images have an odd number of columns or lines your can always take a sample of the original matrice
subind = ind(1:size(IMG1,1),1:size(IMG1,2))
Same thing for 3D index:
subind = ind(1:size(IMG1,1),1:size(IMG1,2),:)
You can use the checkerboard function to generate a checkerboard in the appropriate size. e.g.
I = checkerboard(5);
will make a square checkerboard where each square is 5*5. You can further adjust the input to also make it rectangular, e.g. if you want a 5x8 checkerboard instead of an 8x8 checkerboard
I = checkerboard(5,5,8);
Note: if you want a binary checkerboard just adjust the command with
I = checkerboard(5)>0.5;
I need to create a grid that has x columns, y rows, where each cell in the grid can have a point in it, and each point is at least z horizontal/vertical spaces away from all other points.
1) Is there a simple method to calculate the maximum number of points I can place given the grid size and a spacing of z?
Here's an example 5x5 with z = 2. In this case the max number of points is 13.
1 0 1 0 1
0 1 0 1 0
1 0 1 0 1
0 1 0 1 0
1 0 1 0 1
and here's an example 5x5 where z = 3. In this case the max number of points is 6.
1 0 0 1 0
0 0 0 0 0
0 1 0 0 1
0 0 0 0 0
1 0 0 1 0
I'd like to be able, given x, y, and z, the number of points possible to plot.
2) What's the most efficient way of populating the grid in this manner?
Given matrix contains many clusters. Cluster is represented by 1's.
For Example:
0 1 1 1 0
1 1 1 0 0
0 0 0 1 1
1 1 0 0 1
In this example, there are 3 clusters (connected 1's horizontally or vertically).
Now suppose that matrix size is very big and it contains too many clusters.
Now my question is, I want to know the boundary of all the clusters.
For example given matrix:
0 0 1 1 0
0 1 1 1 1
0 0 1 1 0
0 0 0 1 0
Now output should be coordinates of bold locations:
0 0 1 1 0
0 1 1 1 1
0 0 1 1 0
0 0 0 1 0
Consider matrix is huge with many such clusters, suggest optimized way of finding boundaries of all clusters.
A 1 is on the boundary of some cluster only when it has an 0 as one of its immediate neighbors or when it's on the outline of the matrix, so the naive method would be outputting the coordinates of 1's on the outline, then going through all the other matrix cells and outputting the coordinates of 1's satisfying the said condition.
It doesn't look like there is a way to optimize this algorithm, though.
Suppose we have a huge matrix with only one random 1 inside it. There is no way to find it without going through each and every cell out there.
There is also no way to skip 1's of the same cluster by following the outline of it.
Consider this example:
0 0 0 1 1 1 1 1 1 1
0 0 0 1 0 0 0 0 0 1
0 1 1 1 1 1 0 1 0 1
0 0 0 0 0 1 0 0 0 1
0 0 0 0 0 1 1 1 1 1
One cluster can easily fit inside another one, so following the outline is not an option.
I have spent all day reading up on the above MATLAB functions. I can't seem to find any good explanations online, even on the MathWorks website!
I would be very grateful if anyone could explain bwlabel, regionprops and centroid. How do they work if applied to a grayscale image?
Specifically, they are being used in this code below. How do the above functions apply to the code below?
fun=#minutie; L = nlfilter(K,[3 3],fun);
%% Termination LTerm=(L==1);
figure; imshow(LTerm)
LTermLab=bwlabel(LTerm);
propTerm=regionprops(LTermLab,'Centroid');
CentroidTerm=round(cat(1,LTerm(:).Centroid));
figure; imshow(~K)
set(gcf,'position',[1 1 600 600]); hold on
plot(CentroidTerm(:,1),CentroidTerm(:,2),'ro')
That's quite a mouthful to explain!... nevertheless, I'd love to explain it to you. However, I'm a bit surprised that you couldn't understand the documentation from MathWorks. It's actually quite good at explaining a lot (if not all...) of their functions.
BTW, bwlabel and regionprops are not defined for grayscale images. You can only apply these to binary images.
Update: bwlabel still has the restriction of accepting a binary image but regionprops no longer has this restriction. It can also take in a label matrix that is usually output from bwlabel as well as binary images.
Assuming binary images is what you want, my explanations for each function is as follows.
bwlabel
bwlabel takes in a binary image. This binary image should contain a bunch of objects that are separated from each other. Pixels that belong to an object are denoted with 1 / true while those pixels that are the background are 0 / false. For example, suppose we have a binary image that looks like this:
0 0 0 0 0 1 1 1 0 0
0 1 0 1 0 0 1 1 0 0
0 1 1 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 1 1
0 0 1 1 1 1 0 0 1 1
You can see in this image that there are four objects in this image. The definition of an object are those pixels that are 1 that are connected in a chain by looking at local neighbourhoods. We usually look at 8-pixel neighbourhoods where you look at the North, Northeast, East, Southeast, South, Southwest, West, Northwest directions. Another way of saying this is that the objects are 8-connected. For simplicity, sometimes people look at 4-pixel neighbourhoods, where you just look at the North, East, South and West directions. This woudl mean that the objects are 4-connected.
The output of bwlabel will give you an integer map where each object is assigned a unique ID. As such, the output of bwlabel would look something like this:
0 0 0 0 0 3 3 3 0 0
0 1 0 1 0 0 3 3 0 0
0 1 1 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 4
0 0 0 0 0 0 0 0 4 4
0 0 2 2 2 2 0 0 4 4
Because MATLAB processes things in column major, that's why the labelling is how you see above. As such, bwlabel gives you the membership of each pixel. This tells you where each pixel belongs to if it falls on an object. 0 in this map corresponds to the background. To call bwlabel, you can do:
L = bwlabel(img);
img would be the binary image that you supply to the function and L is the integer map I just talked about. Additionally, you can provide 2 outputs to bwlabel, and the second parameter tells you how many objects exist in the image. As such:
[L, num] = bwlabel(img);
With our above example, num would be 4. As another method of invocation, you can specify the connected pixel neighbourhoods you would examine, and so you can do this:
[L, num] = bwlabel(img, N);
N would be the pixel neighbourhood you want to examine (i.e. 4 or 8).
regionprops
regionprops is a very useful function that I use daily. regionprops measures a variety of image quantities and features in a black and white image. Specifically, given a black and white image it automatically determines the properties of each contiguous white region that is 8-connected. One of these particular properties is the centroid. This is also the centre of mass. You can think of this as the "middle" of the object. This would be the (x,y) locations of where the middle of each object is located. As such, the Centroid for regionprops works such that for each object that is seen in your image, this would calculate the centre of mass for the object and the output of regionprops would return a structure where each element of this structure would tell you what the centroid is for each of the objects in your black and white image. Centroid is just one of the properties. There are other useful features as well, but I'm assuming you don't want to do this. To call regionprops, you would do this:
s = regionprops(img, 'Centroid');
The above code will calculate the centroids of each of your objects in the image. You can specify additional flags to regionprops to specify each feature that you want. I do highly encourage that you take a look at all of the possible features that regionprops can calculate, as there are many that are useful in a variety of different applications and situations.
Also, by omitting any flags as input into the function, you would calculate all of the features in your image by default. Therefore, if we were to declare the image that we have seen above in MATLAB, this is what would happen after I run regionprops. After, let's calculate what the centroids are:
img = logical(...
[0 0 0 0 0 1 1 1 0 0;
0 1 0 1 0 0 1 1 0 0;
0 1 1 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 1 1;
0 0 1 1 1 1 0 0 1 1]);
s = regionprops(img, 'Centroid');
... and finally when we display the centroids:
>> disp(cat(1,s.Centroid))
3.0000 2.6000
4.5000 6.0000
7.2000 1.4000
9.6000 5.2000
As such, the first centroid is located at (x,y) = (3, 2.6), the next centroid is located at (x,y) = (4.5, 6) and so on. Take special note that the x co-ordinate is the column while the y co-ordinate is the row.
Hope this is clear!
Supposing you have a 3d box of cubes, with each cube having 3 indices: (x,y,z), and 1 additional attribute to specify if it represents land or air.
Let's say that we have a 3d array to represent this box of cubes, with each cube being an element in the 3d array.
The following array, for example, would represent a bowl shaped piece of land:
y=0:
0 0 0 0 0
0 0 0 0 0
1 1 1 1 1
1 1 1 1 1
y=1:
0 0 0 0 0
0 0 0 0 0
1 0 0 0 1
1 1 1 1 1
y=2:
0 0 0 0 0
0 0 0 0 0
1 0 0 0 1
1 1 1 1 1
y=3:
0 0 0 0 0
0 0 0 0 0
1 1 1 1 1
1 1 1 1 1
What is an algorithm such that given a selection box it would generate hills with f frequency and with average height of h, with v average variation in height?
We can assume that the lowest level of the bonding box is the "baseline", or "sea-level".
function makeTrees(double frequency, int height, double variation)
{
//return 3d array.
}
I'm writing a minecraft MCEdit filter plugin :P
Simplest way is to decompose the problem into three parts:
Write a routine to generate the cubes for a single hill of height h. Start off by making this a simple cone (play with apex angles till you find something that looks pleasing)
Generate a set of n heights between h-v and h+v, using the random number generator of your choice
Place n mountains randomly on your cube. It doesn't matter if they intersect - indeed, it will lead to a better-looking range.
However, I'd also suggest abandoning this approach, and simply generate a fractal terrain within your bounding cube, then discretize it. You can play with the paramaters to your fractal generator to bound the height and variance.
Assuming you would like sinusoidal hills of frequency f (or rather, wavenumber f, since "frequency" is usually used for temporal quantities) as a function of radius r = sqrt(x^2+y^2) from the center:
Define a threshold function like this:
Any element (x,y,z) with z < z_m will be land, and the rest will be air.