How to attribute intersection points between poly and lineseg to poly - matlab

I'm trying to plot an animal's trajectory from a set of coordinates as a line segment. I want to see how many coordinates are plotted inside a circular zone vs outside. I think that coordinates which intersect with the circle are being counted as both inside and outside, but I would like them to be strictly counted as inside. This is what I have so far:
[in,out] = intersect(circle_poly,trajectory);
plot(circle_poly)
hold on
plot(in(:,1),in(:,2),'b',out(:,1),out(:,2),'r')
legend('Polygon','Inside','Outside','Location','NorthWest')
num_frames_in = numel([in]) %count num elements/frames in polygon
num_frames_out = numel([out]) %count num element/frames outside polygon
total_frames = num_frames_in + num_frames_out
Any help would be really appreciated since I'm new to Matlab!

Related

How to convert from the image coordinates to Cartesian coordinates

I have this 3D image generated from the simple code below.
% Input Image size
imageSizeY = 200;
imageSizeX = 120;
imageSizeZ = 100;
%# create coordinates
[rowsInImage, columnsInImage, pagesInImage] = meshgrid(1:imageSizeY, 1:imageSizeX, 1:imageSizeZ);
%# get coordinate array of vertices
vertexCoords = [rowsInImage(:), columnsInImage(:), pagesInImage(:)];
centerY = imageSizeY/2;
centerX = imageSizeX/2;
centerZ = imageSizeZ/2;
radius = 28;
%# calculate distance from center of the cube
sphereVoxels = (rowsInImage - centerY).^2 + (columnsInImage - centerX).^2 + (pagesInImage - centerZ).^2 <= radius.^2;
%# Now, display it using an isosurface and a patch
fv = isosurface(sphereVoxels,0);
patch(fv,'FaceColor',[0 0 .7],'EdgeColor',[0 0 1]); title('Binary volume of a sphere');
view(45,45);
axis equal;
grid on;
xlabel('x-axis [pixels]'); ylabel('y-axis [pixels]'); zlabel('z-axis [pixels]')
I have tried plotting the image with isosurface and some other volume visualization tools, but there remains quite a few surprises for me from the plots.
The code has been written to conform to the image coordinate system (eg. see: vertexCoords) which is a left-handed coordinate system I presume. Nonetheless, the image is displayed in the Cartesian (right-handed) coordinate system. I have tried to see this displayed as the figure below, but that’s simply not happening.
I am wondering if the visualization functions have been written to display the image the way they do.
Image coordinate system:
Going forward, there are other aspects of the code I am to write for example if I have an input image sphereVoxels as in above, in addition to visualizing it, I would want to find north, south east, west, top and bottom locations in the image, as well as number and count the coordinates of the vertices, plus more.
I foresee this would likely become confusing for me if I don’t stick to one coordinate system, and considering that the visualization tools predominantly use the right-hand coordinate system, I would want to stick with that from the onset. However, I really do not know how to go about this.
Right-hand coordinate system:
Any suggestions to get through this?
When you call meshgrid, the dimensions x and y axes are switched (contrary to ndgrid). For example, in your case, it means that rowsInImage is a [120x100x200] = [x,y,z] array and not a [100x120x200] = [y,x,z] array even if meshgrid was called with arguments in the y,x,z order. I would change those two lines to be in the classical x,y,z order :
[columnsInImage, rowsInImage, pagesInImage] = meshgrid(1:imageSizeX, 1:imageSizeY, 1:imageSizeZ);
vertexCoords = [columnsInImage(:), rowsInImage(:), pagesInImage(:)];

Randomly drawing from a hypercube in Matlab

Consider the n-cube (defined here) with n>3. Suppose that it centered at the origin of the Cartesian plane and each edge has length 10.
I would like to write a piece of code in Matlab that allows me to randomly draw one point (with n coordinates) from this hypercube. Is there a way to do it without pre-defining a n-dimensional grid? In my particular application n=11.
To draw 1 point from the volume of an n-dimensional hypercube with side s, with all points having equal probability, you call
s = 10;
point = (rand(1,n)-0.5)*s;
Replace the 1 with a larger number if you want to draw many points at once.
Extending Jonas' answer, if you want to specify a center, do this:
center = [1.0 -1.0 2.0 -2.0 ...];
s = 10;
point = (rand(1,n)-0.5)*s + center;

I need to create a 3D sphere from a bunch of 2D slices

I currently have to create a sphere from a stack of 2D slices (2D matrices in MATLAB, which represent 2D gray scale images). I have created a bunch of slices using the code below. To create the sphere I have repeatedly created slices of circles of increasing size till 100, and then of decreasing sizes. All of these slices are added to a 3D matrix.
Circle = ones(200,400,400);
for i = 1:100
[rr cc] = meshgrid(1:400);
C = sqrt((rr-200).^2+(cc-200).^2)<=i;
for j = 1:400
for k = 1:400
Circle(i,j,k) = C(j,k);
end
end
end
index = 100;
for i = 1:100
[rr cc] = meshgrid(1:400);
C = sqrt((rr-200).^2+(cc-200).^2)<=index;
for j = 1:400
for k = 1:400
Circle(i+100,j,k) = C(j,k);
end
end
index = index - 1;
end
viewer3d(Circle);
viewer3d is 3rd part library that helps you view your 3D image stacks of slices as 3d objects. Once I visualized this 'supposed' sphere, I realized that it is a diamond shape top and not a sphere.
Therefore I do not understand how to vary the size of circles till the center point of the sphere in the y plane and then decrease it with the same algorithm.
Thank you for your answers and please do not hesitate to ask me to clarify anything within this question.
Alternatively, create a sphere directly, without using loops:
Circle = zeros(200,400,400);
[x,y,z]=meshgrid(1:size(Circle,1),1:size(Circle,2),1:size(Circle,3));
radius=??; %// e.g. radius=100;
%//this sphere is centered in the middle of the image
Circle(sqrt((x-size(Circle,1)/2).^2+(y-size(Circle,2)/2).^2..
+(z-size(Circle,2)/2).^2)<radius)=1;
Yes, the radius along the Z axis is not linear but varies with cos/sin function. Using this representation:
your radius is "Radius = r sin(Theta)", with "Theta = arccos(r / z)". So "r" is the radius of your sphere, and "z" the level/slice you want to draw in. Don't forget to that "z" goes from -"r" to "r". I've tested the formulae and it works fine for an image stack (slices).

Get pixel values in local area under center-pixel's gradient direction

How to get pixel values in local area under center-pixel's gradient direction using matlab?
I already found function imgradient() that's good, but how to transform angle to line under this angle?
So you want to know how to define a line given a point (x0,y0) and an angle theta? Something like this perhaps:
% T determines the length of the line. I am using a step size
% of 0.5 since it should get each pixel. You could always go finer
% and let the call to unique get rid of the duplicates.
t = 0:0.5:T;
p = unique( round( [x0+t(:)*cos(theta), y0+t(:)*sin(theta) ] ), 'rows' );
p in the above will be a Nx2 array of pixel coordinates that are under (technically within 1/2 a pixel) of the line that starts at (x0,y0) and extends out an angle theta.

Calculate area of polygon recursively

I had to calculate any polygon given cordinates of point in 'x-vector','y-vector' (only thing I know is the cordinates are ordered clockwise and polygons like hourglass are not included).
I tried writing this code:
function [areaofit] = Polygarea(xs,ys,cor,prevsum)
if(length(xs)~=length(ys))
disp('dimentions error!please try again');
end
if(nargin==2)
cor=1;
prevsum=0;
end
if(cor==length(xs)-1)
areaofit=prevsum;
figure(1);
fill(xs,ys,'r');
title(['Area = ' num2str(areaofit)]);
end
if(cor~=length(xs)-1)
mat=[xs(1) ys(1) 1;zeros(2,3)];
for k=2:3
mat(k,1)=xs(cor+k-1);
mat(k,2)=ys(cor+k-1);
mat(k,3)=1;
end
farea=prevsum+abs(det(mat))/2;
Polygarea(xs,ys,cor+1,farea);
end
The function does work with any convex polygon but there are concave polygons it does work with (like 'stars' e.g ). What can be improved in my solution? thanks
I think you need to modify this line:
farea=prevsum+abs(det(mat))/2;
to
farea=prevsum+det(mat)/2;
Like this, the concavities in your polygon will add or subtract areas according to what direction they sweep the 0..2π range. To ensure final positive values for your area, there should be something like areaofit=abs(prevsum);