Monte carlo area of a circle - simulation

is it possible to use Monte carlo to compute the area of circle with a radius bigger than 1?
i tried to make it this way but it only work for a circle of radius 1.
N = 10000
incircle = 0
count = 0
while (count<N)
x = random()
y = random()
if sqrt((x-a)^2 +(y-b)^2) <= R then
incircle = incircle+1
endif
count = count+1
so

Don't know what language you're using but I'll write following code in Python, hope you'll understand it.
I made computation for the case of area computation for circle of radius 2.
Here Monte Carlo algorithm is as follows. Lets create a square having X and Y in range [-R ; R]. Now lets randomly uniformly generate points inside this square.We will count total number of generated points and number of points inside a circle of radius R bounded by given square. A point falls into circle if X^2 + Y^2 <= R^2, otherwise its outside of circle. Finally area of square is (2 * R)^2, while circle area is (approximately) equal to num_points_in_circle / num_points_total-th part of area of a square.
In console output I also show error which shows absolute difference with expected value computed precisely through formula Pi * R^2.
In Python x ** 2 means x raised to the power of 2.
Try it online!
import random, math
R = 2
niters = 300_000
total, in_circle = 0, 0
for j in range(20):
for i in range(niters):
x = random.uniform(-R, R)
y = random.uniform(-R, R)
if x ** 2 + y ** 2 <= R ** 2:
in_circle += 1
total += 1
area = (2 * R) ** 2 * in_circle / total
expected = math.pi * R ** 2
print(f'After {(j + 1) * niters:>8} iterations area is {area:.08f}, ' +
f'error is {abs(area - expected):.08f}', flush = True)
Output:
After 300000 iterations area is 12.59130667, error is 0.02493605
After 600000 iterations area is 12.58341333, error is 0.01704272
After 900000 iterations area is 12.58072889, error is 0.01435827
After 1200000 iterations area is 12.57965333, error is 0.01328272
After 1500000 iterations area is 12.57741867, error is 0.01104805
After 1800000 iterations area is 12.57348444, error is 0.00711383
After 2100000 iterations area is 12.57067429, error is 0.00430367
After 2400000 iterations area is 12.57078000, error is 0.00440939
After 2700000 iterations area is 12.56853926, error is 0.00216864
After 3000000 iterations area is 12.56956800, error is 0.00319739
After 3300000 iterations area is 12.56826182, error is 0.00189120
After 3600000 iterations area is 12.56863111, error is 0.00226050
After 3900000 iterations area is 12.56763897, error is 0.00126836
After 4200000 iterations area is 12.56839238, error is 0.00202177
After 4500000 iterations area is 12.56855111, error is 0.00218050
After 4800000 iterations area is 12.56861667, error is 0.00224605
After 5100000 iterations area is 12.56857725, error is 0.00220664
After 5400000 iterations area is 12.56881185, error is 0.00244124
After 5700000 iterations area is 12.56925193, error is 0.00288132
After 6000000 iterations area is 12.56927733, error is 0.00290672

Related

Plotting speed and distance calculated using accelerometer

I am working on basic distance calculation using accelerometer by dragging object on a single axis for physics class in MATLAB and have problem with plotting data.
My steps are:
1) After calibrating device to read zero g on every axis, I eliminate drift errors:
X_real = X_sample - X_calibrated;
if(X_real <= X_drift )
{
X_real = 0;
}
Where X_drift is 2 mg (From datasheet of accelerometer)
2) Calculate velocity:
velocity = 0; % On start
% Integration
v(i) = v(i-1) - x(i-1)-(x(i)+x(i-1)+x(i-2)+x(i-3))/4;
%Check if we stopped
if(x(i-1)==0 && x(i)==0)
v(i)=0;
end
%Check if velocity is under 0 (Not allowed)
if(v(i) < 0)
v(i)=0;
end
velocity = velocity + v(i);
3) Calculate distance:
distance = 0; % On start
%Integration
s(i) = s(i-1) + v(i-1) + (v(i)-v(i-1)-v(i-2)-v(i-3))/4;
distance = distance + s(i);
After testing this by dragging accelerometer on table 20 cm i got these results:
velocity = 0.09 m/s
distance = 0.21 m
time = 3.2s
Error of 1 cm is OK for classroom.
Chart tells something different:
I tried to plot distance after this:
s(i) = s(i)+s(i-1);
And got 21 cm on chart but after 6 s not after 4 s where it should be.
What am I doing wrong?
*UPDATE: Position y value is in mm not cm! Sorry
Im sorry for asking for help, i thought my formulas were ok, but they didn't. After step by step calculations my final solution is:
1) Velocity:
v(i) = v(i-1) - x(i-1)-(x(i)+x(i-1))/2;
2) Distance:
s(i) = s(i-1) + v(i-1)+(v(i)+v(i-1))/2;
And chart is:
Sorry once more time. I hope this will help someone calculating velocity and distance. It surely helped me as lesson to better study my code next time before asking for help.

Tuning Gabor filter

I am trying to seek out pathologies in pictures of noisy vertical stacked layers
with Gabor filtering. For each column, i regard the neigborhood with 10 pixels to the left and right and filter the part of the image with the gabor kernel. Then I take the frobenious norm, so that I have for each column a scalar value.
Here is my result using that image posted below. For me it seems counterintuitive that the response of 0 degree is that much higher than the response of 45 degrees.
But the desired effect is satisfied, meaning that i can state a condition such that the pathology near the 300th column is hit using that the value of 0 degrees is below the value of 45 degrees.
I expected the other way round or is my image just too noisy?
So my questions are: How can I refine the parameter lambda and gamma to maximize the effect when the structure of vertcal stacked layers are broken?(in the middle of the picture around column 290 - 320)
When I tried to change parameters I got too much false positives such that i can not distinguish anymore.
And how can it be that the values of 0 degree is that greater than the filter response of 45 degrees? For me it seems very odd considering that image.
================
Here is the image
Here is my code
windowRadius = 10;
bw = 1;
for k=0:23
theta(k+1)= k*pi/12;
end
psi = [0 pi/2];
lambda = 8; % std value 8
gamma = 0.5; % std value 0.5
for colIndx=1: size(Img,2)
if colIndx-windowRadius < 1
left = 1;
else
left = colIndx - windowRadius;
end
if colIndx+windowRadius > size(Img,2)
right = size(Img,2);
else
right = colIndx + windowRadius;
end
for i=1:length(theta)
gb{i} = gabor_fn(bw,gamma,psi(1),lambda,theta(i)) ...
+ 1i * gabor_fn(bw,gamma,psi(2),lambda,theta(i));
end
gabor_out0deg{colIndx} = imfilter(Img(:, left : right),gb{1},'symmetric');
gabor_out45deg{colIndx} = imfilter(Img(:, left : right),gb{4},'symmetric');
gabor_out90deg{colIndx} = imfilter(Img(:, left : right),gb{7},'symmetric');
gaborFroNorm0deg(colIndx) = norm(gabor_out0deg{colIndx},'fro') / ((right - left) * size(Img,1));
gaborFroNorm45deg(colIndx)= norm(gabor_out45deg{colIndx},'fro') / ((right - left) * size(Img,1));
gaborFroNorm90deg(colIndx)= norm(gabor_out90deg{colIndx},'fro') / ((right - left) * size(Img,1));
end

Find Position based on signal strength (intersection area between circles)

I'm trying to estimate a position based on signal strength received from 4 Wi-Fi Access Points. I measure the signal strength from 4 access points located in each corner of a square room with 100 square meters (10x10). I recorded the signal strengths in a known position (x, y) = (9.5, 1.5) using an Android phone. Now I want to check how accurate can a multilateration method be under the circumstances.
Using MATLAB, I applied a formula to calculate distance using the signal strength. The following MATLAB function shows the application of the formula:
function [ d_vect ] = distance( RSS )
% Calculate distance from signal strength
result = (27.55 - (20 * log10(2400)) + abs(RSS)) / 20;
d_vect = power(10, result);
end
The input RSS is a vector with the four signal strengths measured in the test point (x,y) = (9.5, 1.5). The RSS vector looks like this:
RSS =
-57.6000
-60.4000
-44.7000
-54.4000
and the resultant vector with all the estimated distances to each access points looks like this:
d_vect =
7.5386
10.4061
1.7072
5.2154
Now I want to estimate my position based on these distances and the access points position in order to find the error between the estimated position and the known position (9.5, 1.5). I want to find the intersection area (In order to estimate a position) between four circles where each access point is the center of one of the circles and the distance is the radius of the circle.
I want to find the grey area as shown in this image :
http://www.biologycorner.com/resources/venn4.gif
If you want an alternative way of estimating the location without estimating the intersection of circles you can use trilateration. It is a common technique in navigation (e.g. GPS) to estimate a position given a set of distance measurements.
Also, if you wanted the area because you also need an estimate of the uncertainty of the position I would recommend solving the trilateration problem using least squares which will easily give you an estimate of the parameters involved and an error propagation to yield an uncertainty of the location.
I found an answear that solved perfectly the question. It is explained in detail in this link:
https://gis.stackexchange.com/questions/40660/trilateration-algorithm-for-n-amount-of-points
I also developed some MATLAB code for the problem. Here it goes:
Estimate distances from the Access Points:
function [ d_vect ] = distance( RSS )
result = (27.55 - (20 * log10(2400)) + abs(RSS)) / 20;
d_vect = power(10, result);
end
The trilateration function:
function [] = trilat( X, d, real1, real2 )
cla
circles(X(1), X(5), d(1), 'edgecolor', [0 0 0],'facecolor', 'none','linewidth',4); %AP1 - black
circles(X(2), X(6), d(2), 'edgecolor', [0 1 0],'facecolor', 'none','linewidth',4); %AP2 - green
circles(X(3), X(7), d(3), 'edgecolor', [0 1 1],'facecolor', 'none','linewidth',4); %AP3 - cyan
circles(X(4), X(8), d(4), 'edgecolor', [1 1 0],'facecolor', 'none','linewidth',4); %AP4 - yellow
axis([0 10 0 10])
hold on
tbl = table(X, d);
d = d.^2;
weights = d.^(-1);
weights = transpose(weights);
beta0 = [5, 5];
modelfun = #(b,X)(abs(b(1)-X(:,1)).^2+abs(b(2)-X(:,2)).^2).^(1/2);
mdl = fitnlm(tbl,modelfun,beta0, 'Weights', weights);
b = mdl.Coefficients{1:2,{'Estimate'}}
scatter(b(1), b(2), 70, [0 0 1], 'filled')
scatter(real1, real2, 70, [1 0 0], 'filled')
hold off
end
Where,
X: matrix with APs coordinates
d: distance estimation vector
real1: real position x
real2: real position y
If you have three sets of measurements with (x,y) coordinates of location and corresponding signal strength. such as:
m1 = (x1,y1,s1)
m2 = (x2,y2,s2)
m3 = (x3,y3,s3)
Then you can calculate distances between each of the point locations:
d12 = Sqrt((x1 - x2)^2 + (y1 - y2)^2)
d13 = Sqrt((x1 - x3)^2 + (y1 - y3)^2)
d23 = Sqrt((x2 - x3)^2 + (y2 - y3)^2)
Now consider that each signal strength measurement signifies an emitter for that signal, that comes from a location somewhere at a distance. That distance would be a radius from the location where the signal strength was measured, because one would not know at this point the direction from where the signal came from. Also, the weaker the signal... the larger the radius. In other words, the signal strength measurement would be inversely proportional to the radius. The smaller the signal strength the larger the radius, and vice versa. So, calculate the proportional, although not yet accurate, radius's of our three points:
r1 = 1/s1
r2 = 1/s2
r3 = 1/s3
So now, at each point pair, set apart by their distance we can calculate a constant (C) where the radius's from each location will just touch one another. For example, for the point pair 1 & 2:
Ca * r1 + Ca * r2 = d12
... solving for the constant Ca:
Ca = d12 / (r1 + r2)
... and we can do this for the other two pairs, as well.
Cb = d13 / (r1 + r3)
Cc = d23 / (r2 + r3)
All right... select the largest C constant, either Ca, Cb, or Cc. Then, use the parametric equation for a circle to find where the coordinates meet. I will explain.
The parametric equation for a circle is:
x = radius * Cos(theta)
y = radius * Sin(theta)
If Ca was the largest constant found, then you would compare points 1 & 2, such as:
Ca * r1 * Cos(theta1) == Ca * r2 * Cos(theta2) &&
Ca * r1 * Sin(theta1) == Ca * r2 * Sin(theta2)
... iterating theta1 and theta2 from 0 to 360 degrees, for both circles. You might write code like:
for theta1 in 0 ..< 360 {
for theta2 in 0 ..< 360 {
if( abs(Ca*r1*cos(theta1) - Ca*r2*cos(theta2)) < 0.01 && abs(Ca*r1*sin(theta1) - Ca*r2*sin(theta2)) < 0.01 ) {
print("point is: (", Ca*r1*cos(theta1), Ca*r1*sin(theta1),")")
}
}
}
Depending on what your tolerance was for a match, you wouldn't have to do too many iterations around the circumferences of each signal radius to determine an estimate for the location of the signal source.
So basically you need to intersect 4 circles. There can be many approaches to it, and there are two that will generate the exact intersection area.
First approach is to start with one circle, intersect it with the second circle, then intersect the resulting area with the third circle and so on. that is, on each step you know current intersection area, and you intersect it with a new circle. The intersection area will always be a region bounded by circle arcs, so to intersect it with a new circle you walk along the boundary of the area and check whether each bounding arc intersects with a new circle. If it does, then you leave only the part of the arc that lies inside a new circle, remember that you should continue with an arc from a new circle, and continue traversing the boundary until you find the next intersection.
Another approach that seems to result in a worse time complexity, but in your case of 4 circles this will not be important, is to find all the intersection points of two circles and choose only those points that are of interest for you, that is which lie inside all other circles. These points will be the corners of your area, and then it is rather easy to reconstruct the area. After googling a bit, I have even found a live demo of this approach.

Trouble with the assignment of values to pixels

I'm currently trying to write a function in MatLab which loops over each pixel, takes the mean intensity of the pixels within a radius around it and then applies that intensity to the central pixel, effectively blurring the image.
I start by declaring the function and finding the maximum width and height of the image, nx and ny:
function [] = immean(IMAGE, r)
[nx, ny] = size(IMAGE);
I then create a completely black image of the same size as the image variable IMAGE. This is so that I can store the value of each pixel, once the mean intensity of its neighbourhood has been found.
average = zeros(size(IMAGE));
I then loop through the image:
for x = 1:nx
for y = 1:ny
and apply a series of if-statements to deal with cases where the radius of the circle around the pixel does not fit the image. (For example, a pixel at (1,1) with a radius of 5 would have a starting point of -4, which would cause an error):
if x-r <= 0
startx = 1;
else
startx = x-r;
end
if x+r > nx
endx = nx;
else
endx = x+r;
end
if y-r <= 0
starty = 1;
else
starty = y-r;
end
if y+r > ny
endy = ny;
else
endy = y+r;
end
This effectively creates a square of values that may fall under the domain of the circular sample, which speeds up the program dramatically. After that, I iterate through the values within this square and find any pixels which fall within the radius of the central pixel. The intensities of these pixels are then added to a variable called total and the count pixelcount increments:
total = 0;
pixelcount = 0;
for xp = startx : endx
for yp = starty : endy
if (x-xp)^2 + (y-yp)^2 <= r^2
total = total + uint64(IMAGE(xp, yp));
pixelcount = pixelcount + 1;
end
end
end
I then find the mean intensity of the circular sample of pixels, by dividing total by pixelcount and then plug that value into the appropriate pixel of the completely black image average:
mean = total / pixelcount;
average(x,y) = mean;
The trouble is: this isn't working. Instead of a blurred version of the original image, I get an entirely white image instead. I'm not sure why - when I take the ; from the last line, it shows me that mean constitutes many values - it's not like they're all 255. So I figure that there must be something wrong with the assignment line average(x,y) = mean;, but I can't find out what that is.
Can anyone see why this is going wrong?

Matlab: given 4 points, fit the closest rhombus/square

I need a script that "checks" if 4 given points form a square or a rhombus.
I am working in a QR code segmentation script in which I try to locate the vertex by looking for the non-negative values of a binary image traversing it by rows and columns.
There are some cases in which checking is not neccessary, like in this image:
It is a bit hard to see, but the vertex are labelled as 4 points in green, magenta, cyan and yellow. In this case the script should return the same input points, since no modification is needed.
On the other hand, there are cases in which the vertex are labeled as so:
It can be seen that the magenta and cyan labels rely on the top right corner of the image. This is obviously not correct, but it fullfills the specified condition: traverse each row of the image until you find a row satisfying sum(row)>1 (greater than 1 to avoid single, noisy pixels).
How can I locate the misplaced vertex and place it using the remaining vertex coordinates?
EDIT
Solved the problem. I'm posting the code of the function in case someone needs it:
function correctedCorners = square(corners)
correctedCorners = corners;
X = corners(:,1);
Y = corners(:,2);
sortedX = sort(corners(:,1));
sortedY = sort(corners(:,2));
%% DISTANCES BW POINTS
for i=1:4
for j=1:4
distances(i,j) = sqrt((corners(i,1)-corners(j,1))^2+ (corners(i,2)-corners(j,2))^2);
end
end
%% relationship bw distances
% check corner 1
d11 = distances(1,1);%0
d12 = distances(1,2);%x
d13 = distances(1,3);%sqrt(2)*x
d14 = distances(1,4);%x
bool1 = [(d12*0.8<=d14)&(d12*1.2>=d14) (d12*0.8*sqrt(2)<=d13)& (d12*1.2*sqrt(2)>=d13) (d14*0.8<=d12)&(d14*1.2>=d12) (d14*0.8*sqrt(2)<=d13)&(d14*1.2*sqrt(2)>=d13)];
% check corner 2
d21 = distances(2,1);%x
d22 = distances(2,2);%0
d23 = distances(2,3);%x
d24 = distances(2,4);%sqrt(2)*x
bool2 = [(d21*0.8<=d23)&(d21*1.2>=d23) (d21*0.8*sqrt(2)<=d24)&(d21*1.2*sqrt(2)>=d24) (d23*0.8<=d21)&(d23*1.2>=d21) (d23*0.8*sqrt(2)<=d24)&(d23*1.2*sqrt(2)>=d24)];
% check corner 3
d31 = distances(3,1);%sqrt(2)*x
d32 = distances(3,2);%x
d33 = distances(3,3);%0
d34 = distances(3,4);%x
bool3 = [(d32*0.8<=d34)&(d32*1.2>=d34) (d32*0.8*sqrt(2)<=d31)&(d32*1.2*sqrt(2)>=d31) (d34*0.8<=d32)&(d34*1.2>=d32) (d34*0.8*sqrt(2)<=d31)&(d34*1.2*sqrt(2)>=d31)];
% check corner 4
d41 = distances(4,1);%x
d42 = distances(4,2);%sqrt(2)*x
d43 = distances(4,3);%x
d44 = distances(4,4);%0
bool4 = [(d41*0.8<=d43)&(d41*1.2>=d43) (d41*0.8*sqrt(2)<=d42)&(d41*1.2*sqrt(2)>=d42) (d43*0.8<=d41)&(d43*1.2>=d41) (d43*0.8*sqrt(2)<=d42)&(d43*1.2*sqrt(2)>=d42)];
bool = [bool1; bool2;bool3;bool4];
idx = 0;
for i=1:4
if (sum(bool(i,:))==0)
idx = [idx i];
end
end
if (length(idx)>=2)
for i=2:length(idx)
switch idx(i)
case 1
correctedCorners(1,:) = abs(corners(4,:)-(corners(3,:)-corners(2,:)));
case 2
correctedCorners(2,:) = abs(corners(3,:)-(corners(4,:)-corners(1,:)));
case 3
correctedCorners(3,:) = abs(corners(2,:)+(corners(1,:)-corners(1,:)));
case 4
correctedCorners(4,:) = abs(corners(1,:)+(corners(3,:)-corners(2,:)));
end
end
end
From basic geometry about squares:
TopLeft distance to BotLeft = x
TopLeft distance to TopRight= x
TopLeft distance to BotRight= sqrt(2)*x
Use the same logic for BotLeft to other points, etc.
Allow yourself something like 10-20% margin of error to declare an incorrect point. That is, if TopLeft distance to 2 points outside of the range (80%;120%)*x , and its distance to the third point is outside of the range (80%;120%)*sqrt(2)*x, you can declare the point as placed incorrectly.
In your case, the TopLeft point fails on all distance tests:
0 instead of x to TopRight (about 100% error)
sqrt(2)*x vs x to BotLeft (about 44% error)
x vs sqrt(2)*x to BotRight) (about 31% error)
As long as the rhombus is very similar to a square, a 20% margin of error while treating it as a square should still work.