Reputation: 949
I am going to generate random ellipses in Matlab. The information that I have is: distribution of large radius of ellipse, distribution of small radius of ellipse, and proportion (e.g., I want to stop this process after a certain amount, or proportion, of the grid is filled).
I tried the following code for circle:
out_size = [200 200];
out = zeros(out_size(1),out_size(2));
[xx,yy] = meshgrid(1:out_size(1),1:out_size(2));
for i=1:40
obj = [random('unif',1,200) random('unif',1,200),random('unif',4,8)];
d = sqrt((xx-obj(1)).^2 + (yy-obj(2)).^2);
out(d <= obj(3))=1;
end
figure, imagesc(out), axis equal tight xy
Any ideas?
Upvotes: 0
Views: 1103
Reputation: 104493
For those in the StackOverflow community that seem confused, I will rephrase what the question is asking (go Mentalist!).
The OP wishes to draw random ellipses in an image. For each ellipse, we can characterize it by its major length, minor length and its centre location. For each ellipse, the OP wishes to randomly sample from a distribution (Uniform, Gaussian, etc.) to obtain a major length, a minor length and the centre locations. Once these are generated, the OP wishes to draw these onto an image.
The amount of ellipses to generate is contingent on the proportion of painted pixels drawn on this image. Should the amount of painted pixels exceed a certain amount, we stop drawing.
You seem to be on the right track. However, what I would do is generate the major, minor and centre coordinates first. After, you can use a loop to loop over each quartet of parameters, generate the correct spatial locations for the ellipse, then use these locations to index into your image and set an intensity. I'm going to be playful and I will randomize the intensity to set for each ellipse. However, to be sure you can see the ellipse, I will restrict the intensities generated between [32,255]
.
In addition, I would recommend you don't sample from a Gaussian distribution for the major and minor lengths, as the definition of these require they be positive. Now, to review, the equation of an ellipse, given a centre point (x_0, y_0)
and major and minor lengths (a,b)
is defined as:
Note that if a > b
, the major axis is horizontal and so you get a horizontally wide ellipse. If b > a
, the major axis is vertical and so you get a vertically wide ellipse. This won't affect our code though.
Now, what we will do is we will have a while
loop that keeps iterating and populating your image until a certain proportion of your image is full. We then stop after we fill up this many pixels. For now, I'll choose 40% of the total image.
Therefore, do something like this, assuming that you know the maximum a
and b
to be used in the image. I would make them both equal so that you have an equal change generating horizontally and vertically wide ellipses:
%// Declare output image
out = zeros(200,200);
%// Declare a and b
a = 20;
b = 20;
%// Declare reference coordinates
[X,Y] = meshgrid(1:size(out,2), 1:size(out,1));
%// Proportion
prop = 0.4;
%// Set seed for reproducibility
rng(123123);
while true
%// Generate random a, b and centre
x_axis = a*rand;
y_axis = b*rand;
centre = [size(out,2)*rand size(out,1)*rand];
%// Define coordinates with respect to this centre
Xmove = X - centre(1);
Ymove = Y - centre(2);
%// Check ellipse equation and filter out those locations
%// that satisfy result
ind = (((Xmove.^2) / x_axis^2) + ((Ymove.^2) / y_axis^2)) <= 1;
%// Set these locations in the output image to a random intensity
intensity = floor(223*rand) + 32;
out(ind) = intensity;
%// Check proportion
if sum((out(:) > 0) / numel(out)) >= prop
break;
end
end
%// Cast and show the output
out = uint8(out);
imshow(out);
This code probably requires some explanation. We first declare an output image of a given size, and we also declare the minimum and maximum values of a
and b
. We also define a meshgrid
of points so that we can use this to generate our spatial coordinates for each ellipse we generate.
We define a proportion that we want the image to be filled before we quit, so I chose 40% here and I set the random seed to be 123123 through rng
.
Now, we will keep looping until the proportion of pixels that are being filled in the image either is equal to or exceeds this proportion. At each iteration of the loop, we generate our a
, b
and our centres ensuring that they respect the boundaries of the image. We then offset our reference grid of coordinates so that the random centre is now the origin, and we check to see which points in this new grid of coordinates satisfies the ellipse equation. Whichever points satisfy the equation, we set these points in the image to a random intensity between [32,255]
. Bear in mind that I chose the less than inequality so that we can fill the ellipse. I also made sure to choose a minimum intensity of 32 on purpose so that we can count how many pixels in the filled up image have been filled in. To determine how much the image has been filled up, we count how many non-zero pixels there are, and see how much this proportion is and compare with our desired proportion. If it's equal to or greater, we stop. If not, we keep generating ellipses until this proportion is met.
With all of that, this is what I get with a run-through of the above code.
Upvotes: 2