I have (x,y,z) coordinates with measured values called (w) corresponding to these (x,y,z) coordinates. I want to produce a heat map for the measured value (w) in 3D. Is there anyway to do that.
Before answering, I tried to know more about the dimensions of your cube in order to understand what type of solutions might exist. Unfortunately, since this is not specified at this stage, answers might not be applicable, nevertheless let's shoot for some:
you are trying to plot a 3D cube, in which a 4th dimensional "color" corresponds to your "w" values. The "inside" of this cube will therefore not be visible in a 3D object (even with transparency, the inside "heatmaps" will not be visualizable). If this part is still confusing, think of a 6 by 6 rubik's cube : the colors of the mini-cubes "inside" are not visible, and even if the outer colors were semi-transparent the inner colors wouldn't render in a way that would be interpretable.
a first solution, depending on the dimensions and their meaning, would be to choose a dimension and show cross-sectional heatmaps. For example, for a housing market study, if x measures the size of the house, y measures the proximity to a city, and z measures the number of rooms (say with modalities 1,2,3,4,5,6), and w is the price, it could make sense to plot six 2D heatmaps with the x and y axes, one heatmap for each of the "room" modalities.
another solution, if we stay with this example but now z represents the year of purchase from, say, 1921 to 2020, then we can again show yearly cross-sections, but this time in a video which shows the evolution of the heatmap. It is fairly easy to export a Matlab video from successive heatmaps, and you could pause for example a tenth of a second for each year in which case this example would lead to a 10-second video (100 years).
Happy visualizing!
Related
I am writing a program that captures real time images from a scene by two calibrated cameras (so the internal parameters of the cameras are known to us). Using two view geometry, I can find the essential matrix and use OpenCV or MATLAB to find the relative position and orientation of one camera with respect to another. Having the essential matrix, it is shown in Hartley and Zisserman's Multiple View Geometry that one can reconstruct the scene using triangulation up to scale. Now I want to use a reference length to determine the scale of reconstruction and resolve ambiguity.
I know the height of the front wall and I want to use it for determining the scale of reconstruction to measure other objects and their dimensions or their distance from the center of my first camera. How can it be done in practice?
Thanks in advance.
Edit: To add more information, I have already done linear trianglation (minimizing the algebraic error) but I am not sure if it is any useful because there is still a scale ambiguity that I don't know how to get rid of it. My ultimate goal is to recognize an object (like a Pepsi can) and separate it in a rectangular area (which is going to be written as a separate module by someone else) and then find the distance of each pixel in this rectangular area, i.e. the region of interest, to the camera. Then the distance from the camera to the object will be the minimum of the distances from the camera to the 3D coordinates of the pixels in the region of interest.
Might be a bit late, but at least for someone struggling with the same staff.
As far as I remember it is actually linear problem. You got essential matrix, which gives you rotation matrix and normalized translation vector specifying relative position of cameras. If you followed Hartley and Zissermanm you probably chose one of the cameras as origin of world coordinate system. Meaning all your triangulated points are in normalized distance from this origin. What is important is, that the direction of every triangulated point is correct.
If you have some reference in the scene (lets say height of the wall), then you just have to find this reference (2 points are enough - so opposite ends of the wall) and calculate "normalization coefficient" (sorry for terminology) as
coeff = realWorldDistanceOf2Points / distanceOfTriangulatedPoints
Once you have this coeff, just mulptiply all your triangulated points with it and you got real world points.
Example:
you know that opposite corners of the wall are 5m from each other. you find these corners in both images, triangulate them (lets call triangulated points c1 and c2), calculate their distance in the "normalized" world as ||c1 - c2|| and get the
coeff = 5 / ||c1 - c2||
and you get real 3d world points as triangulatedPoint*coeff.
Maybe easier option is to have both cameras in fixed relative position and calibrate them together by stereoCalibrate openCV/Matlab function (there is actually pretty nice GUI in Matlab for that) - it returns not just intrinsic params, but also extrinsic. But I don't know if this is your case.
Say we are creating a calibration lookup table for a device, shown in the plot below. The theta represents different phase values, and the r represents different magnitude values. The calibration setpoints are shown in blue circles, and are taken at every N degrees of phase and N values of magnitude. For every setpoint, we measure the actual device output and obtain the red coordinates, which describe the resulting phase and magnitude. Thus for every blue setpoint, we observe the device outputting red points.
The question now is, I want to set the device to a value of the green circle with orange ring. How do I calculate what the setpoint should be (green circle) to set the device to in order to obtain green/orange on the output?
The issue I am having is that for every 2D setpoint (mag, phase), the resultant data is 2D (mag, phase). In addition, magnitude and phase are not independent variables (fixing phase and changing only magnitude, the resulting phase output does change).
So what basic math/logic should I use to perform the necessary interpolation?
How about treating this like a registration problem. For example, you could use an affine transformation as the model between the measured and calibrated points? For each cell (i.e., the 4 blue points in your figure) compute a least squares estimate of the affine transformation between the blue and red points. Then for new points apply the corresponding transformation to get the green point you want. Here and here are some SO questions that discuss this. In addition, you might consider estimating and applying the transformation directly in magnitude/phase space.
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 implementing the algorithm for Photometric Stereo where I have already calculated the normals from a set of images with different light directions.
How can I plot the normal vector field in matlab? I have a matrix of normals of size (N x 3).
I'm afraid you have left out a step. You need to retrieve the depth map from the surface normals, and then you can start plotting. To see how to do this, you can check out section 4 of the following paper:
http://www.wisdom.weizmann.ac.il/~vision/photostereo/Photometric%20Stereo%20with%20General%20Unknown%20Lighting%20-%20BasriJacobsKemelmacher_ijcv06.pdf
There are other resources on the web too; I don't know of any built-in function in any Matlab library, but I don't have the Computer Vision toolbox, so who knows?
I suspect you are looking for quiver3.
You need to present normals field, as an gradient field, then you can,use quiver function. And in gradient field previously normalized triple {pn,qn,rn}, the data is presented in such a way , as to rend the third component of it always equal to one (at least in theory). I mean with rn=1, or should I now say, that now : R=1, and you actually need only {P,Q} coomponents to present contents of gradient field with ordinary 2D quiver function. Thus, gradient vector is something quite different and distinct from normals field, because: P=pn/sqrt(pn^2+qn^2+rn^2) , and Q=qn/(pn^2+qn^2+rn^2) POINTWISELY saying.
However you don't bother with double for loops, run over X,Y directions, cause POINTWISELY, correctly rendered calculations for gradient field from normals, is the following: P=pn./(pn.^2 + qn.^2 + rn.^2).^(1/2);, and so on.
You can see as well: http://www.mathworks.com/matlabcentral/fileexchange/authors/126090/
You need to present normals field, as an gradient field, then you can use a Matlab's quiver function. And in gradient field, the previously normalized triple {pn,qn,rn}, of the data, is presented in such a way, as to rend the third component of it always equal to one (at least in theory).
I mean with rn = 1, or should I now say, that now with: some R=1, you actually need only {P,Q} coomponents to present contents of gradient field with ordinary 2D quiver function. Thus, gradient vector is something quite different and distinct from normals field, because:
P=pn/sqrt(pn^2+qn^2+rn^2) , and Q=qn/(pn^2+qn^2+rn^2) POINTWISELY saying.
However you don't bother with double for loops, which would be run over X, Y directions, cause POINTWISELY, correctly rendered calculations for gradient field from normals, are the following:
P=pn./(pn.^2 + qn.^2 + rn.^2).^(1/2); , and: Q=qn./(pn.^2 + qn.^2 + rn.^2);
You can see as well:
http://www.mathworks.com/matlabcentral/fileexchange/authors/126090/
Briefly saying, the gradient field always represents slopes on X, Y directions, while descending exactly one height unit alongside Z axis on the 3D surface retrieved with for instance Photometric Stereo algorithm. That is why the third component in quiver function visualization is always equal to one (i.e. R = 1), and practically irrelevant.
I have posted, last month, some codes, on THE simplest Photometric Stereo methods, on Mathworks Web pages, due to some span of time available to tide it all up, I mean my own so far produced codes in Matlab...
I have N 3D observations taken from an optical motion capture system in XYZ form.
The motion that was captured was just a simple circle arc, derived from a rigid body with fixed axis of rotation.
I used the princomp function in matlab to get all marker points on the same plane i.e. the plane on which the motion has been done.
(See a pic representing 3D data on the plane that was found, below)
What i want to do after the previous step is to look the fitted data on the plane that was found and get the curve of the captured motion in 2D.
In the princomp how to, it is said that
The first two coordinates of the principal component scores give the
projection of each point onto the plane, in the coordinate system of
the plane.
(from "Fitting an Orthogonal Regression Using Principal Components Analysis" article on mathworks help site)
So i thought that if i just plot those pc scores -plot(score(:,1),score(:,2))- i'll get the motion curve. Instead what i got is this.
(See a pic representing curve data in 2D derived from pc scores, below)
The 2d curve seems stretched and nonlinear (different y values for same x values) when it shouldn't be. The curve that i am looking for, should be interpolated by just using simple polynomial (polyfit) or circle fit in matlab.
Is this happening because the plane that was found looks like rhombus relative to the original coordinate system and the pc axes are rotated with respect to the basis of plane in such way that produce this stretch?
Then i thought that, this is happening because of the different coordinate systems of optical system and Matlab. Optical system's (ie cameras) co.sys. is XZY oriented and Matlab's default (i think) co.sys is XYZ oriented. I transformed my data to correspond to Matlab's co.sys through a rotation matrix, run again princomp but i got the same stretch in the 2D curve (the new curve just had different orientation now).
Somewhere else i read that
Principal Components Analysis chooses the first PCA axis as that line
that goes through the centroid, but also minimizes the square of the
distance of each point to that line. Thus, in some sense, the line is
as close to all of the data as possible. Equivalently, the line goes
through the maximum variation in the data. The second PCA axis also
must go through the centroid, and also goes through the maximum
variation in the data, but with a certain constraint: It must be
completely uncorrelated (i.e. at right angles, or "orthogonal") to PCA
axis 1.
I know that i am missing something but i have a problem understanding why i get a stretched curve. What i have to do so i can get the curve right?
Thanks in advance.
EDIT: Here is a sample data file (3 columns XYZ coords for 2 markers)
w w w.sendspace.com/file/2hiezc