I need to choose one pixel from a range of, for example, 0 to 1920 pixels with the normal distribution, but I have no idea how to do this in MatLab. I know that I can use normrnd()
to retrieve a random value given mu
and sigma
, but how do I apply this to my situation?
mu
might be at 500 pixels and sigma
100 pixels, for example.
My current approach is this
function xpos = apply_normal_distribution(mu, sigma, min_xpos=1, max_xpos=1920)
% Applies normal distribution with median mu and standard deviation sigma
% xpos will always be: min <= xpos <= max
xpos = ceil(normrnd(mu, sigma));
if xpos > max_xpos
xpos = max_xpos;
elseif xpos < min_xpos
xpos = min_xpos;
endif
end
So I'm just using normrnd
and cutting off if the value is higher or lower than my bounds. Don't know how good this is, but it works.
The moment you bound a normal distribution (or filter its results in any other way) it is not a normal distribution anymore. However, there exists a truncated normal distribution which is the closest thing to what you are looking for. It has it's own set of properties which are similar to a normal distribution if the bounds are far away from the mean and you have a low variance. With Matlab you can make that with:
mu = 500;
sigma = 100;
%truncate at 0 and 1920
pd = truncate(makedist('Normal',mu,sigma),0,1920);
% take some (10) samples
samples = random(pd,10,1);
Building it from scratch for Octave:
Your self-made proposal has the problem that if a realisation is outside the bound, you set the value to the bound value. Therefore the bound value will be overly proportional chosen. A less dirty way is instead to just draw a fresh value. I don't have a working Octave, but something like this should do it:
function xpos = apply_normal_distribution(mu, sigma, min_xpos=1, max_xpos=1920)
% new realisations are drawn as long as they are outside the bounds.
while xpos<min_xpos | xpos>max_xpos
xpos = ceil(normrnd(mu, sigma));
end
end
Just as a warning: If it is unlikely that a realisation will be within the bounds then this may run for a very long time...