I am working with structured 2.5D and unstructured 3D data, which generally is available in (X,Y,Z) coordinates, i.e. point clouds. Now I want to impose a regular voxel grid onto the data. This is not meant for visualization purposes, but rather for "cleaning" or fusing the data. I imagine cases, where e.g. 3 points fall within the volume of one voxel. Then I would aim at either just setting this voxel to "activated" and discarding the 3 original points or alternatively I would like to calculate the euclidian mean of the points and return the thus "cleaned" point cloud as an irregularly structured one again.
I hope I could make my intentions clear enough: It's not about visualization and not necessarily about using volumetric cubes instead of points. It's only about manipulating possibily irregular point clouds in a structured way.
I was thinking about kd-tree or octree based solutions in this context, but can anybody point me in the proper direction? Hinting at existing MATLAB implementations would be most appreciated.
If the data is irregularly spaced, what you want to use is something which both smooths and interpolates your data points. A very good method for doing so is Gaussian process regression. Here's an example for the same problem but in 2D.
Related
I want to construct a 3D cube in MATLAB. I know that the units of any 3D shape are voxels not pixels. Here is what I want to do,
First, I want to construct a cube with some given dimensions x, y, and z.
Second, according to what I understand from different image processing tutorials, this cube must consists of voxels (3D pixels). I want to give every voxel an initial color value, say gray.
Third, I want to access every voxel and change its color, but I want to distinguish the voxels that represent the faces of the cube from those that represent the internal region. I want to axis every voxel by its position x,y, z. At the end, we will end up with a cube that have different colors regions.
I've searched a lot but couldn't find a good way to implement that, but the code given here seems very close in regard to constructing the internal region of the cube,
http://www.mathworks.com/matlabcentral/fileexchange/3280-voxel
But it's not clear to me how it performs the process.
Can anyone tell me how to build such a cube in MATLAB?
Thanks.
You want to plot voxels! Good! Lets see how we can do this stuff.
First of all: yeah, the unit of 3D shapes may be voxels, but they don't need to be. You can plot an sphere in 3D without it being "blocky", thus you dont need to describe it in term of voxels, the same way you don't need to describe a sinusoidal wave in term of pixels to be able to plot it on screen. Look at the figure below. (same happens for cubes)
If you are interested in drawing voxels, I generally would recommend you to use vol3D v2 from Matlab's FEX. Why that instead of your own?
Because the best (only?) way of plotting voxels is actually plotting flat square surfaces, 6 for each cube (see answer here for function that does that). This flat surfaces will also create some artifacts for something called z-fighting in computer graphics. vol3D actually only plots 3 surfaces, the ones looking at you, saving half of the computational time, and avoiding ugly plotting artifacts. It is easy to use, you can define colors per voxel and also the alpha (transparency) of each of them, allowing you to see inside.
Example of use:
% numbers are arbitrary
cube=zeros(11,11,11);
cube(3:9,3:9,3:9)=5; % Create a cube inside the region
% Boring: faces of the cube are a different color.
cube(3:9,3:9,3)=2;
cube(3:9,3:9,9)=2;
cube(3:9,3,3:9)=2;
cube(3:9,9,3:9)=2;
cube(3,3:9,3:9)=2;
cube(9,3:9,3:9)=2;
vold3d('Cdata',cube,'alpha',cube/5)
But yeah, that still looks bad. Because if you want to see the inside, voxel plotting is not the best option. Alphas of different faces stack one on top of the other and the only way of solving this is writing advanced computer graphics ray tracing algorithms, and trust me, that's a long and tough road to take.
Very often one has 4D data, thus data that contains 3D location and a single data for each of the locations. One may think that in this case, you really want voxels, as each of them have a 3D +color, 4D data. Indeed! you can do it with voxels, but sometimes its better to describe it in some other ways. As an example, lets see this person who wanted to highlight a region in his/hers 4D space (link). To see a bigger list I suggest you look at my answer in here about 4D visualization techniques.
Lets try wits a different approach than the voxel one. Lets use the previous cube and create isosurfaces whenever the 4D data changes of value.
iso1=isosurface(cube,1);
iso2=isosurface(cube,4);
p1=patch(iso1,'facecolor','r','facealpha',0.3,'linestyle','none');
p2=patch(iso2,'facecolor','g','facealpha',1,'linestyle','none');
% below here is code for it to look "fancy"
isonormals(cube,p1)
view(3);
axis tight
axis equal
axis off
camlight
lighting gouraud
And this one looks way better, in my opinion.
Choose freely and good plotting!
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.
I have 3D space. And I know for example N points in this space (x1,y1,z1), (x2,y2,z2)..., (xn,yn,zn). I want to interplolate points, that is different from this. How can I do this in Matlab?
interp3 may help you. Here is the documentation.
As always, there are questions left unanswered by your one line query.
If the data is of the form where there is a functional relationship z(x,y), (or y(x,z) or x(y,z)) then you might potentially be able to use one of the interpolation tools. Thus, suppose you have data that lies on a lattice in the (x,y) plane, thus some value of z at each point in that lattice. In this case, you can use interp2.
Alternatively, if the data is scattered, but there is some single valued functional relationship z(x,y) that you don't have, but it is some continuous function. Infinite first derivatives are a problem too here. In this case, assuming that you have data that at least fills some convex domain in the (x,y) plane, you can still interpolate a value of z. For this, use griddata, or TriScatteredInterp. Or you might use my own gridfit tool, as found on the file exchange.
Next, the way you describe the data, I'm not at all positive that you have something in one of the above forms. For example, if your data lies along some curved path in this 3D domain, and you wish to interpolate points along that curved arc can be done using my interparc tool, also found on the file exchange.
One last case that people often seem to have when they talk about interpolation of a spatial set like this, is just a general surface, that they wish to build a neatly interpolated, smooth surface. It might be something as simple as the surface of a sphere, or something wildly more complex. (These things are never simple.) For this, you might be able to use a convex hull to approximate something, if it is a closed convex surface. More complex surfaces might require a tool like CRUST, although I have no implementation of it I can offer to you. Google will help you there, if that is what you need.
The point of all this is, how you interpolate your data depends on what form the data is in, what it represents, and the shape of the relationship you will be interpolating.
I am to create a 3D volume out of grayscale image set using Matlab. A set contains a continuous and quantized slices of 2D grayscale image. I am still considered myself a rookie in Matlab, but this is what I currently have in my mind:
create an empty space for 3D volume.
On each image, we perform all the preprocessing operation so that we only got the part that is of our interest. (In this question, assume that this preprocessing part always work flawlessly)
Go through the image, each pixel's x and y coordinate on 2D will be transfer to the empty space. For z coordinate, we can use the slice number with respect to the distance between each slice. If a pixel is adjacent to another pixel, the 3D points will be connected together.
Repeat the previous 2 steps until all slices are done. We will now have all the points connected just like in the 2D slices.
But here comes the trouble, how can we connect the points between the slices, so that these points can become a volume? Or is there a more robust way to do in Matlab? Any suggestion is highly appreciated.
Part 0 - Assumptions
all 2D images are of the same dimension, hence your 3D volume can hold all of them in a rectangular cube
majority of the pixels in each of the 2D images have 3D spatial relationships (you can't visualize much if the pixels in each of the 2D images are of some random distribution. )
Part 1 - Visualizing 3D Volume from A Stack of 2D Images
To visualize or reconstruct a 3D volume from a stack of 2D images, you can try the following toolkits in matlab.
1 3D CT/MRI images interactive sliding viewer
http://www.mathworks.com/matlabcentral/fileexchange/29134-3d-ctmri-images-interactive-sliding-viewer
[2] Viewer3D
http://www.mathworks.com/matlabcentral/fileexchange/21993-viewer3d
[3] Image3
http://www.mathworks.com/matlabcentral/fileexchange/21881-image3
[4] Surface2Volume
http://www.mathworks.com/matlabcentral/fileexchange/8772-surface2volume
[5] SliceOMatic
http://www.mathworks.com/matlabcentral/fileexchange/764
Note that if you are familiar with VTK, you can try this:
[6] matVTK
http://www.cir.meduniwien.ac.at/matvtk/
I am currently sticking with [5] SliceOMatic for its simplicity and ease of use. However, by default, rendering 3D is quite slow in Matlab. Turning on openGL would give faster rendering. (http://www.mathworks.com/help/techdoc/ref/opengl.html) Or simply put, set(gcf, 'Renderer', 'OpenGL').
Part 2 - Interpolating pixels in between the slices
To interpolate pixels in between the slices, you need to specify an interpolation method (some of the above toolkits have this capability / flexibility. Otherwise, to give you a head start, some examples for interpolation are bicubic, spline, polynomial etc..(you can work this out by looking up on google or google/scholar for interpolation methods much more specific to your problem domain).
Part 3 - 3D Pre-processing
Looking at your procedures, you process the volumetric data by processing each of the 2D images first. In many advanced algorithms, or in true 3D processing, what you can do is to process the volumetric data in 3D domain first (simply put, you take the 26 neighbors or more in to account first.). Once this step is done, you can simply output the volumetric data into a stack of 2D images for cross-sectional viewing or supply to one of the aforementioned toolkits for 3D viewing or output to third party 3D viewing applications.
I have followed the above concepts for my own medical imaging research projects and the above finding is based on my research experience documented here (with latest revisions).
MATLAB generally plots volumetric data using a 3d array. The data points are spatially evenly separated along each axis. If there are sites in the 3d array for which you do not have data for, usually they are assigned the NaN value and the various plotting functions can generally handle this in a reasonable way (i.e. will generally behave as you intended).
If you load the slices into the 3d array such that adjacent points in the z-direction of the data are also adjacent in the 3rd dimension of the array then you should be fine.
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