MATLAB STL 3D modelling from IMU Data - matlab

I am trying to upload an STL file to MATLAB and be able to manipulate it but can't find the best way to do it.
What I am trying to do is import an STL a file of a hand tool and be able to rotate the 3D image by giving it roll, pitch and yaw angles. The whole system will involve a live read out from an IMU which calculates these angles (going to use a 9 axis IMU - 9250 and hope to incorporate space movement into this but that's progress for another day) which will feed into a function which alters the orientation of the model made from the STL to show in real time how the body is moving. Its important to note the body is fixed so no points can move relative to each other (simplifying the problem).
Currently I have not got far but have modeled the STL fixed in space:
model = createpde(3);
importGeometry(model,'Test_model.stl');
pdegplot(model);
This will plot the STL file. The model is made up of a certain number of faces and vertices which can be plotted but I cannot see a way of manipulating these. I figure that there should be some way of converting this to a 3D matrix of points in x,y,z which I can mulitply by a rotation vector to give a new position rotated by the three angles.
Rx = rotx(psi);
Ry = roty(theta);
Rz = rotz(phi);
R = Rx*Ry*Rz;
Then multiply the model by this and update the plot.
I will also need a way of offsetting all points by certain values to be able to change the point of rotation (where the IMU is placed). I figure once I get the coordinates in a matrix then I can offset them all by certain values in each direction x, y and z.
Can anyone help with this, I have been looking for similar projects but I have not been able to find anything with good code explanations as of yet. The way I am proposing is only my idea, if there is an easier method then please say. Thanks!

I do not have comment privileges so this may not seem like a complete answer.
I've done exactly this type of thin in MATLAB for other research but had to write my own data parsers as I do not have any tool boxes, or importGeometry() didn't exist at the time. The STL is structured as a list of triangles each with a normal and three vertices. I'd ask you, after importing STL what is the data format? An array of positions, a struct or object? Also, what s/w was used to make it. The gmsh format is easier to work with as it gives you a reduced list of points and lists of connections between them based on what simplex contains the points.
If the output of importGeometry is a struct with the full data set then you will have repeated data and need to (1) parse the struct, (2) delete duplicates, (3) stack the results in a 3-by-N or N-by-3 matrix, then operate on this result with the rotation matrix and update plots.
You haven't really asked a specific question but I hope that my comments were helpful.

Related

MATLAB: Digitizing a plot with multiple variables and implementing the data

I have 8 plots which I want to implement in my Matlab code. These plots originate from several research papers, hence, I need to digitize them first in order to be able to use them.
An example of a plot is shown below:
This is basically a surface plot with three different variables. I know how to digitize a regular plot with just X and Y coordinates. However, how would one digitize a graph like this? I am quite unsure, hence, the question.
Also, If I would be able to obtain the data from this plot. How would you be able to utilize it in your code? Maybe with some interpolation and extrapolation between the given data points?
Any tips regarding this topic are welcome.
Thanks in advance
Here is what I would suggest:
Read the image in Matlab using imread.
Manually find the pixel position of the left bottom corner and the upper right corner
Using these pixels values and the real numerical value, it is simple to determine the x and y value of every pixel. I suggest you use meshgrid.
Knowing that the curves are in black, then remove every non-black pixel from the image, which leaves you only with the curves and the numbers.
Then use the function bwareaopen to remove the small objects (the numbers). Don't forget to invert the image to remove the black instead of the white.
Finally, by using point #3 and the result of point #6, you can manually extract the data of the graph. It won't be easy, but it will be feasible.
You will need the data for the three variables in order to create a plot in Matlab, which you can get either from the previous research or by estimating and interpolating values from the plot. Once you get the data though, there are two functions that you can use to make surface plots, surface and surf, surf is pretty much the same as surface but includes shading.
For interpolation and extrapolation it sounds like you might want to check out 2D interpolation, interp2. The interp2 function can also do extrapolation as well.
You should read the documentation for these functions and then post back with specific problems if you have any.

Use calibrated camera get matched points for 3D reconstruction

I am trying to compute the 3D coordinates from several pair of two view points.
First, I used the matlab function estimateFundamentalMatrix() to get the F of the matched points (Number > 8) which is:
F1 =[-0.000000221102386 0.000000127212463 -0.003908602702784
-0.000000703461004 -0.000000008125894 -0.010618266198273
0.003811584026121 0.012887141181108 0.999845683961494]
And my camera - taken these two pictures - was pre-calibrated with the intrinsic matrix:
K = [12636.6659110566, 0, 2541.60550098958
0, 12643.3249022486, 1952.06628069233
0, 0, 1]
From this information I then computed the essential matrix using:
E = K'*F*K
With the method of SVD, I finally got the projective transformation matrices:
P1 = K*[ I | 0 ]
and
P2 = K*[ R | t ]
Where R and t are:
R = [ 0.657061402787646 -0.419110137500056 -0.626591577992727
-0.352566614260743 -0.905543541110692 0.235982367268031
-0.666308558758964 0.0658603659069099 -0.742761951588233]
t = [-0.940150699101422
0.320030970080146
0.117033504470591]
I know there should be 4 possible solutions, however, my computed 3D coordinates seemed to be not correct.
I used the camera to take pictures of a FLAT object with marked points. I matched the points by hand (which means there should not be obvious mistake exists about the raw material). But the result turned out to be a surface with a little bit banding.
I guess this might be due to the reason pictures did not processed with distortions (but actually I remember I did).
I just want to know whether this method to solve the 3D reconstruction issue right? Especially when we already know the camera intrinsic matrix.
Edit by JCraft at Aug.4: I have redone the process and got some pictures showing the problem, I will write another question with detail then post the link.
Edit by JCraft at Aug.4: I have posted a new question: Calibrated camera get matched points for 3D reconstruction, ideal test failed. And #Schorsch really appreciate your help formatting my question. I will try to learn how to do inputs in SO and also try to improve my gramma. Thanks!
If you only have the fundamental matrix and the intrinsics, you can only get a reconstruction up to scale. That is your translation vector t is in some unknown units. You can get the 3D points in real units in several ways:
You need to have some reference points in the world with known distances between them. This way you can compute their coordinates in your unknown units and calculate the scale factor to convert your unknown units into real units.
You need to know the extrinsics of each camera relative to a common coordinate system. For example, you can have a checkerboard calibration pattern somewhere in your scene that you can detect and compute extrinsics from. See this example. By the way, if you know the extrinsics, you can compute the Fundamental matrix and the camera projection matrices directly, without having to match points.
You can do stereo calibration to estimate the R and the t between the cameras, which would also give you the Fundamental and the Essential matrices. See this example.
Flat objects are critical surfaces, not possible to achive your goal from them. try adding two (or more) points off the plane (see Hartley and Zisserman or other text on the matter if still interested)

Force Calculation at a Point Within a Vector Field, and then Reacting to that Force

So, this is going to be pretty hard for me to explain, or try to detail out since I only think I know what I'm asking, but I could be asking it with bad wording, so please bear with me and ask questions if need-be.
Currently I have a 3D vector field that's being plotted which corresponds to 40 levels of wind vectors in a 3D space (obviously). These are plotted in 3D levels and then stacked on top of each other using a dummy altitude for now (we're debating how to go about pressure altitude conversion most accurately--not to worry here). The goal is to start at a point within the vector space, modeling that point as a particle that can experience physics, and iteratively go through the vector field reacting to the forces, thus creating a trajectory of sorts through the vector field.
Currently what I'm trying to do is whip up code that would allow me to to start a point within this field and calculate the forces that the particle would feel at that point and then establish a resultant force vector that would indicate the next path of movement throughout the vector space.
Right now I'm stuck in the theoretical aspects of the code, as I'm trying to think through how the particle would feel vectors at a distance.
Any suggestions on ways to attack this problem within MatLab or relevant equations to use?
In order to run my code, you'll need read_grib.r4 and to compile that mex file here is a link to a zip with the code and the required files.
https://www.dropbox.com/s/uodvixdff764frq/WindSim_StackOverflow_Files.zip
I would try to interpolate the wind vector from the adjecent ones. You seem to have a regular grid, that should be no problem. (You can use interp3 for this)
Afterwards, you can use any differential-equation solver for your problem, as you have basically a field of gradients and an initial value. Forward euler would be the simplest one but need a small step size. (N.B.: Your field should be a gradient field)
You may read about this in Wikipedia: http://en.wikipedia.org/wiki/Vector_field#Flow_curves
In response to comment #1:
Yes. In a regular grid, any (arbitrary chosen) point will have eight neighbors. interp3 will so a trilinear interpolation to determine an interpolated gradient vector.
If you use forward-euler, you will then move a small distance in that direction. There you interpolate a gradient and go a small step into this new direction and so on. What happens are two things:
You get a series of points that lie on a streamline and thus form the trajectory of a particle moving along the field
Get large errors, the further you move and the larger the step size is. Use a small step size or use a better solver (Runge-Kutta comes to my mind)
If all you want is plotting, then the streamline function might help.

Corner Detection in 2D Vector Data

I am trying to detect corners (x/y coordinates) in 2D scatter vectors of data.
The data is from a laser rangefinder and our current platform uses Matlab (though standalone programs/libs are an option, but the Nav/Control code is on Matlab so it must have an interface).
Corner detection is part of a SLAM algorithm and the corners will serve as the landmarks.
I am also looking to achieve something close to 100Hz in terms of speed if possible (I know its Matlab, but my data set is pretty small.)
Sample Data:
[Blue is the raw data, red is what I need to detect. (This view is effectively top down.)]
[Actual vector data from above shots]
Thus far I've tried many different approaches, some more successful than others.
I've never formally studied machine vision of any kind.
My first approach was a homebrew least squares line fitter, that would split lines in half resurivly until they met some r^2 value and then try to merge ones with similar slope/intercepts. It would then calculate the intersections of these lines. It wasn't very good, but did work around 70% of the time with decent accuracy, though it had some bad issues with missing certain features completely.
My current approach uses the clusterdata function to segment my data based on mahalanobis distance, and then does basically the same thing (least squares line fitting / merging). It works ok, but I'm assuming there are better methods.
[Source Code to Current Method] [cnrs, dat, ~, ~] = CornerDetect(data, 4, 1) using the above data will produce the locations I am getting.
I do not need to write this from scratch, it just seemed like most of the higher-class methods are meant for 2D images or 3D point clouds, not 2D scatter data. I've read a lot about Hough transforms and all sorts of data clustering methods (k-Means etc). I also tried a few canned line detectors without much success. I tried to play around with Line Segment Detector but it needs a greyscale image as an input and I figured it would be prohibitivly slow to convert my vector into a full 2D image to feed it into something like LSD.
Any help is greatly appreciated!
I'd approach it as a problem of finding extrema of curvature that are stable at multiple scales - and the split-and-merge method you have tried with lines hints at that.
You could use harris corner detector for detecting corners.

Reading DICOM-RT files to create 3D binary matrix?

I'm currently working with DICOM-RT files (which contain DICOM along with dose delivery data and structure set files). I'm mainly interested in the "structure set" file (i.e. RTSS.dcm), which contains the set of contour points for an ROI of interest. In particular, the contour points surround a tumor volume. For instance, a tumor would have a set of 5 contours, each contour being a set of points that encircle that slice of the tumor.
I'm trying to use MatLab to use these contour points to construct a tumor volume in a binary 3D matrix (0 = nontumor, 1=tumor), and need help.
One possible approach is to fill each contour set as a binary slice, then interpolate the volume between slices. So far I've used the fill or patch function to create binary cross-sections of each contour slice, but I'm having difficulty figuring out how to interpolate these binary slices into a 3D volume. None of the built-in functions appear to apply to this particular problem (although maybe I'm just using them wrong?). A simple linear interpolation doesn't seem appropriate either, since the edges of one contour should blend into the adjacent contour in all directions.
Another option would be to take the points and tesselate them (without making slices first). However, I don't know how to make MatLab only tesselate the surface of the tumor and not intersecting the tumor volume. Currently it seems to find triangles within the tumor. If I could get it into just a surface, I'm not sure how to take that and convert it into a binary 3D matrix volume either.
Does anyone have experience with either 3D slice interpolation OR tesselation techniques that might apply here? Or perhaps any relevant toolkits that exist? I'm stuck... :(
I'm open to approaches in other languages as well: I'm somewhat familiar with C# and Python, although I assumed MatLab would handle the matrix operations a little easier.
Thanks in advance!
I'm not sure from what program you're exporting your dicom-rt structure files, but I believe I found a more elegant solution for you, already described in an open-source software (GDCM, CMake, ITK) in an Insight journal article.
I was discussing a similar problem with one of our physicists, and we saw your solution. It's fine if whatever structure you're attempting to binarize has no concavities, but if so, they'll be rendered inaccurately.
This method is verified for dicom-rt structure sets from Eclipse and Masterplan. Hope it helps.
http://www.midasjournal.org/download/viewpdf/701/4
I think I found an answer in another post (here). Rather than trying to interpolate the "missing slices" between the defined contours, treating the contour points as a point cloud and finding the convex hull might be a more efficient way of doing it. This method created the binary 3D volume that I was after.
Here is the code I used, hope it might be helpful to those who need to work with DICOM-RT files:
function mask = DicomRT2BinaryVol(file)
points = abs(getContourPoints(file));
%%NOTE: The getContourPoints function simply reads the file using
%%'dicominfo' method and organizes the contour points into an n-by-3
%%matrix, each column being the X,Y,Z coordinates.
DT = DelaunayTri(points);
[X,Y,Z] = meshgrid(1:50,1:50,1:50);
simplexIndex = pointLocation(DT, X(:), Y(:), Z(:));
mask = ~isnan(simplexIndex);
mask = reshape(mask,size(X));
end
This method is a slightly modified version of the method posted by #gnovice in the link above.
iTk is an excellent library for this sort of thing: http://www.itk.org/
HTH