I have a question to you...
Imagine square with size A x A. Now lets simulate circles with diameter of d, randomly distributed within this square, something like on the image below (in this case d's are the same, but its not the rule, they might be also randomly distributed within some range like d1 to d2).
Lets say that circles are described in matrix as:
circles(1, :) = [x, y, d];
circles(2, :) = [x, y, d];
...and so on
where x, y are coordinates, d is diameter. Now the question is, how to simulate this circles, until given crowding parameter c is reached? c is simply defined as: c = yellow area / square area (in this case A^2).
And the second thing - lets say that everything is simulated and I want to check if some coordinate (x,y) is within or outside yellow area... How to do it? I was doing it by checking if my (x,y) is within area of each circle (but its getting more difficult when instead of circles I use i.e. round shape rectangles), one by one, but there must be some better way of doing it.
Thanks for help : )
Here is an approach that should do the trick:
Start with a large empty matrix (big enough to guarantee that every shape generated is fully inside the matrix). Suppose we do it like this color = zeros(100)
while we have not yet reached the cowding ratio: the midpoint and diameter of one circle, I assume you can manage this
change the color of all points in the circle, for example by setting it to one.
Calculate the crowding ratio (something like c = mean(mean(color))
Note, if you only want to use part of the matrix (enable shapes to fall partially out of the picture) this can for example be achieved by using mean(mean(color(11:end-11)) in step 4, ignoring the 10 pixels near the edge.
Now if you want to know whether point (x,y) is yellow, simply check the value of color(x,y). Or if you want to ignore the edges check color(x+10,y+10)
Related
I have two sets of 3D images (they come in form of 2D stacks). Image A is 10 micron, with size: 1000 x 1024 x 1017, while image B is 5 micron, with size: 2004 x 2048 x 2036. I like to make some computations on randomly chosen set of the 2D slices of A, and then compare this to the same set of slices for B. However, since B has twice the number of slices for each slice of A, will it be sensible to compare two slices of B to each of A? If so, how do i determine exactly which of the two slices of B make up a slice of A?
While contemplating on this, i also thought of blowing up A by 2 using imresize function for each 2D slice that i chose for the computation. Will it be okay to compare this new B with the A, considering that i have completely ignored what happens with the z-coordinate?
Thank you.
As you mentioned this is microCT, I am assuming that both images are different size resolution of the same object. This means that pixels have specific spatial location, not only value, therefore for this case, there are no pixels (assuming a pixel is a infinitesimally small dot in the center of the cube) that match in both images.
So, lets assume that in image A, the locations of the pixel centers are their indices (1,1,1), (1,1,2) etc. This means that the image starts (pixel boundaries) at "world value" 0.5, and ends at size(imgA)+0.5
Now, first lets transform the desired pixel coordinates for interpolation to this range. imgB pixel centers are then in locations (ind-0.5)*size(imgA)/size(imgB)+0.5.
Example: Assume
size(imgA,1)=3; size(imgB,1)=4;
therefore the pixels in imgA are at x location 1:3. The pixels on imgB are, using the above formula, in [0.8750 1.6250 2.3750 3.1250].
Note how the first pixel is 0.375 from 0.5 (our image border) and the next pixel is at 0.75 (double 0.375*2).
We scaled a higher resolution image to the same "real world" coordinates.
Now to the real stuff.
We need to create the desired coordinates in the reference (A) image. For that, we do:
[y, x, z]=...
ndgrid((1:size(imgB,1)-0.5)*size(imgA,1)/size(imgB,1)+0.5),...
(1:size(imgB,2)-0.5)*size(imgA,2)/size(imgB,2)+0.5),...
(1:size(imgB,3)-0.5)*size(imgA,3)/size(imgB,3)+0.5);
Now these 3 have the coordinates we want. Caution! each of these are size(imgB) !!! You need to have the RAM 5*size(imgB) in total to work with this.
Now we can interpolate
imAinB=interp3(imgA,x,y,z,'linear'); % Or nearest
It seems to be that your function is imresize3. You can change one volume to the other's dimentions with:
B = imresize3(V,[numrows numcols numplanes])
You can also explore interpolation methods.
Normally this table is around 600 points but I didn't want to type it all, let's say I have points like this:
240.021000000000 291.414100000000
250.985100000000 297.566300000000
260.143500000000 310.125800000000
270.605100000000 315.355400000000
279.775500000000 327.352000000000
288.302300000000 335.765900000000
301.487400000000 348.374900000000
313.892100000000 340.501400000000
323.391400000000 328.044800000000
334.615100000000 322.182400000000
Where number on the left is X and number on the right is Y of a coordinate where there is a "thing" or let's say where the color is white and rest is black.
And I want to turn this into an image, what I did so far is this:
% Added 50 more pixels to not stick to edge of image
image = uint8(zeros(max(table(:, 1))+50, max(table(:, 2)+50))
for i = size(table(:))
image(round(table(i, 1)), round(table(i, 2))) = 256;
end
imshow(image);
I am wondering how accurate this is and how I can improve it or if I can improve it?
Reason here is I will do this for two tables and need to compare the similarity of two images that belong to these tables, but I don't even have an image and rounding didn't feel like the best way since 270.49999999 and 270.5000001 are similar, yet 270 and 271 are different. There can also be points that overlap each other if all is just rounded up or just rounded down.
I see two approaches, you can increase the resolution by binning your image to be N*600 by N*600 point instead of 600x600, for example 6000x6000, then each 0.1 value will be in a different pixel. Or, you can convolve your 1 pixel with a distribution like a 5x5 Gaussian of signa=1 that will capture the spread around that point position. For example using exp(- ((x-xn).^2+(x-yn).^2)/2) where xn and yn are the n-th point coordinate in your question, and x and y are obtained via [x y]=meshgrid(1:600) or whatever your image size is....
What we want is to draw several solid circles at random locations, with random gray scale colors, on a dark gray background. How can we do this? Also, if the circles overlap, we need them to change color in the overlapping part.
Since this is an assignment for school, we are not looking for ready-made answers, but for a guide which tools to use in MATLAB!
Here's a checklist of things I would investigate if you want to do this properly:
Figure out how to draw circles in MATLAB. Because you don't have the Image Processing Toolbox (see comments), you will probably have to make a function yourself. I'll give you some starter code:
function [xout, yout] = circle(x,y,r,rows,cols)
[X,Y] = meshgrid(x-r:x+r, y-r:y+r);
ind = find(X.^2 + Y.^2 <= r^2 & X >= 1 & X <= cols & Y >= 1 & Y <= rows);
xout = X(ind);
yout = Y(ind);
end
What the above function does is that it takes in an (x,y) co-ordinate as well as the radius of
the circle. You also will need to specify how many rows and how many columns you want in your image. The reason why is because this function will prevent giving you co-ordinates that are out of bounds in the image that you can't draw. The final output of this will give you co-ordinates of all values inside and along the boundary of the circle. These co-ordinates will already be in integer so there's no need for any rounding and such things. In addition, these will perfectly fit when you're assigning these co-ordinates to locations in your image. One caveat to note is that the co-ordinates assume an inverted Cartesian. This means that the top left corner is the origin (0,0). x values increase from left to right, and y values increase from top to bottom. You'll need to keep this convention in mind when drawing circles in your image.
Take a look at the rand class of functions. rand will generate random values for you and so you can use these to generate a random set of co-ordinates - each of these co-ordinates can thus serve as your centre. In addition, you can use this class of functions to help you figure out how big you want your circles and also what shade of gray you want your circles to be.
Take a look at set operations (logical AND, logical OR) etc. You can use a logical AND to find any circles that are intersecting with each other. When you find these areas, you can fill each of these areas with a different shade of gray. Again, the rand functions will also be of use here.
As such, here is a (possible) algorithm to help you do this:
Take a matrix of whatever size you want, and initialize all of the elements to dark gray. Perhaps an intensity of 32 may work.
Generate a random set of (x,y) co-ordinates, a random set of radii and a random set of intensity values for each circle.
For each pair of circles, check to see if there are any co-ordinates that intersect with each other. If there are such co-ordinates, generate a random shade of gray and fill in these co-ordinates with this new shade of gray. A possible way to do this would be to take each set of co-ordinates of the two circles and draw them on separate temporary images. You would then use the logical AND operator to find where the circles intersect.
Now that you have your circles, you can plot them all. Take a look at how plot works with plotting matrices. That way you don't have to loop through all of the circles as it'll be inefficient.
Good luck!
Let's get you home, shall we? Now this stays away from the Image Processing Toolbox functions, so hopefully these must work for you too.
Code
%%// Paramters
numc = 5;
graph_size = [300 300];
max_r = 100;
r_arr = randperm(max_r/2,numc)+max_r/2
cpts = [randperm(graph_size(1)-max_r,numc)' randperm(graph_size(2)-max_r,numc)']
color1 = randperm(155,numc)+100
prev = zeros(graph_size(1),graph_size(2));
for k = 1:numc
r = r_arr(k);
curr = zeros(graph_size(1),graph_size(2));
curr(cpts(k,1):cpts(k,1)+r-1,cpts(k,2):cpts(k,2)+r-1)= color1(k)*imcircle(r);
common_blob = prev & curr;
curr = prev + curr;
curr(common_blob) = min(color1(1),color1(2))-50;
prev = curr;
end
figure,imagesc(curr), colormap gray
%// Please note that the code uses a MATLAB file-exchange tool called
%// imcircle, which is available at -
%// http://www.mathworks.com/matlabcentral/fileexchange/128-imcircle
Screenshot of a sample run
As you said that your problem is an assignment for school I will therefore not tell you exactly how to do it but what you should look at.
you should be familiar how 2d arrays (matrices) work and how to plot them using image/imagesc/imshow ;
you should look at the strel function ;
you should look at the rand/randn function;
such concepts should be enough for the assignment.
Trying to find the distance from point a to point b given a custom axis. I have some pictures to help me better explain:
I'm trying to find the distance from red to pink (or gray) on two custom axes. The axis from red to green (axis RG) and the axis from red to blue (axis RB).
You're asking about vector projection.
Given two vectors A and B, what is A projected onto B?
In your case, A seems to be the difference between red and pink, where B is what you're calling a custom axis.
Calculating this projection usually involves a dot product. Lucky for you, Unity provides Vector3.Dot to make this easy.
We can calculate the projection as a scalar. A is "this much" in the direction of B:
float projScalar = Vector3.Dot(A, B.normalized);
This gives us the length you're asking about.
If needed, we can convert that result into a vector, by casting that length in the direction of B:
Vector3 projVector = B.normalized * projScalar;
The question is
a.write a function which finds the circle with the minimal area s.t it bounds a given list of points (use fminsearch and give appropriate plot).
b.If you managed do the same for sphere (find one with minimal volume)
What I've tried so far:
%%Main function
function minarea= mincircle(points)
maxx=max(points(1,:));
maxy=max(points(2m:));
radius=max(maxx,maxy);
minarea=fminsearch(#(x) circle(x,r,c),[0,0])
end
%%This function is supposed to give equalation of circle
function eq=circle(x,r,c)
eq=(x(1)-c(1)).^2+(x(2)-c(2)).^2 %=r?
% and here I don't know how to insert r:
end`
For better understanding I'll attach a sketch.
In these terms I want to find the area of the circle whose center is in O
Note: I don't believe that the circle you drew is the smallest possible bounding circle. It should be a little smaller, up and to the right, and should touch at least two points on its perimeter.
Approaching the problem
We have a set of points, and we want to draw a circle that encompasses all of them. The problem is that you need three bits of information to define a circle: the X and Y coordinates of the circle's center, and the circle's radius. So the problem doesn't seem straightforward.
However, there is a related problem that is much easier to solve. Suppose the circle's center is fixed. From that point, we make a circle grow concentrically outwards so that it becomes bigger and bigger. At some point, the circle will encompass one of the points in our set. As it gets bigger, it will encompass a second point, and a third, until all the points in our set fall within our circle. Clearly, as soon as the last point in the set falls within our circle, we have the smallest possible circle that encompasses all the points, given that we started by fixing the center point of the circle.
Moreover, we can determine what the radius of this circle is. It is simply the maximum distance from any point in the set to the center of the circle, since we stop when the last point is touched by the perimeter of our expanding circle.
The next problem is to determine What is the best starting point to place the center of our circle? Clearly if the starting point is far away from all the points in our set, then the radius must be very large to even encompass one point in the set. Intuitively, it must be "in the middle" of our points somewhere. But where, exactly?
Using fminsearch
My suggestion is that you want to find the point P(x, y) that minimises how large you have to grow the circle to encompass all the points in the set. And we're in luck that we can use fminsearch to find P.
According to the fminsearch documentation, the function you pass in must be a function of one parameter (which may be an array), and it must return a scalar. The idea is that you want the output of your function to be as small as possible, and you want to find out what inputs will make that possible.
In our case, we want to write a function that outputs the size of our circle, given the center of the circle as input. That way, fminsearch will find the center of the smallest possible circle that will still encompass all the points. I'm going to write a function that outputs the radius required to encompass all the points given a center point P.
pointsX = [..]; % X-coordinates of points in the set
pointsY = [..]; % Y-coordinates of points in the set
function r = radiusFromPoint(P)
px = P(1);
py = P(2);
distanceSquared = (pointsX - px).^2 + (pointsY - py).^2;
r = sqrt(max(distanceSquared));
end
Then we want to use fminsearch to find the point that gives us the smallest radius. I've just naively used the origin (0, 0) as my starting estimate, but you may have a better idea (like using the first point in the set)
P0 = [0, 0]; % starting estimate
[P, radiusMin] = fminsearch(#radiusFromPoint, P0);
The circle is defined by its center at P and radius of radiusMin.
And I'll leave it to you to plot the output and generalize to the 3D case!
Actually, while you may need it to complete your homework assignment (I assume that is what this is) you don't really need to use an optimizer at all. The minboundcircle code posted with my minimal bounding tools does it without use of an optimizer. (There is also a minboundsphere tool.)
Regardless, you might find a few tricks in there that will be useful. At the very least, learn how to reduce the size of the problem (and so the speed of solution) by use of a convex hull. After all, it is only the points on the convex hull that can determine a minimal bounding circle. All other points are simply a waste of CPU time.