Converting 3D to 2D cloud of points
6 次查看(过去 30 天)
显示 更早的评论
Alfonso
2018-6-30
I am trying to convert a set of data which is a cloud of points from 3D to 2D, I am using this code:
% Function from 3D to 2D
function [D,R,T]=dimred(X)
T = repmat(mean(X),[size(X,1),1]);
XX = X-T;
[R,N]=eig(XX'*XX);
D=XX*R;
D=D(:,2:end);
Q=[zeros(size(D,2),1) eye(size(D,2))];
R=Q*R';
return
% 3D to 2D
[nodes_2D,R,T]=dimred(newnodes1) % R = rot matrix, T = Translation matrix
The data correctly converts to 2D, in this case, looking at the image the 3D points are rotated to the left, but for a different cloud of points it rotates it to the right. My question is the next, is there any way of forcing to apply the rotation always in the same direction? (without manually reversing the 2D red plot).
I have attached the figure and the .mat containing the cloud of points in 3D.
Thank you for any help.
10 个评论
Walter Roberson
2018-6-30
I notice you use the eigenvectors as returned. Any scalar multiple of an eigenvector acts the same way, including negative multiples. As I do not see any code in there to explicitly normalize, I wonder if the difficulty you are facing is that some of your eigenvectors just happen to be coming out with the negative of the sign you are expecting for the purposes of rotation ?
Alfonso
2018-6-30
编辑:Alfonso
2018-6-30
Hello Walter, you are right, the eigenvectors are in SOME cases coming up with the opposite sign that I want them to, and I don't know why this happens, it seems that depending on the initial 3D data, it gets flattened to the left or to the right. My objective is to always get the same "2D view" of my 3D cloud of points (always flattened to the right for example).
These are the 2 only possibilities of 2D result from the 3D blue data. Currently for this dataset, I obtain the red 2D plot, but I want the magenta one which I have been able to plot reversing the R (rotation matrix). The problem as I said, is that the result obtained (red or magenta) changes for each 3D dataset, so I don't know how to detect before seeing the plots if the rotation has been the one I want (magenta) or not.
I hope my explanation does not look too messy,
Thank you
Walter Roberson
2018-6-30
编辑:Walter Roberson
2018-6-30
Can you divide each eigenvector by its first non-zero element, so that the leading entries are all 0 or positive ?
Alfonso
2018-6-30
For this 3D dataset using the code I posted I get the following:
% R = Eigenvalues
R =
0.0600 0.3950 -0.9167
0.4589 0.8047 0.3768
% N = Right Eigenvectors
N =
1.0e+05 *
0.0000 0 0
0 2.4094 0
0 0 3.1734
So right eigenvectors result in 0/+ when dividing by the 1st element, did you mean this or am I getting confused?
I also uploaded the .mat file with the 3D data in the initial post.
Walter Roberson
2018-6-30
I meant like
for K = 1 : size(R,2)
firstR = find(R(:,K),1,'first');
R(:,K) = R(:,K) ./ firstR;
end
... Of course there are ways to vectorize this, but it is simply not worth the trouble.
Alfonso
2018-6-30
In order for the division to be +/0 all values of each column in R should have the same sign, this never or rarely happens as I have seen for other 3D datasets.
Walter Roberson
2018-6-30
Perhaps it is only one particular one of the dimensions that needs to be positive and you can divide by the sign of that particular dimension?
Note: your comments are reversed above, R is the eigenvectors and diag(N) are the eigenvalues.
Alfonso
2018-6-30
When I try to transform from 3D to 2D several datasets, in some of them I get the correct 2D view but the ones I don't get correctly are always reversed in Y. So if for example I do this:
R(:,2) = R(:,2) * -1;
And then transform to 2D, I obtain the correct 2D view (in the case the first result was the wrong view).
Maybe the sign of one of the values of the eigenvector corresponding to Y axis determines if it is flattened to the right or left, I have to take a look, but could this be?
Walter Roberson
2018-6-30
for K = 1 : size(R,2)
s = sign(R(2,K));
R(:,K) = R(:,K) .* s;
end
You need to transform the entire eigenvector.
Alfonso
2018-7-1
Hello Walter, it does not seem to work. For a 3D dataset 1 it flattens it to the left side, whereas for a 3D dataset 2 of the same plane as dataset 1 it flattens it to the right (same behaviour I had).
3D dataset1:
3D dataset2:
采纳的回答
Matt J
2018-6-30
编辑:Matt J
2018-6-30
normal=null(XX);
normal=normal(:,end)*sign(normal(1,end));
rotaxis=-cross([0,0,1].',normal);
theta=asind(norm(rotaxis));
[D,R,~] = AxelRot(XX.', theta, rotaxis, []);
11 个评论
Alfonso
2018-6-30
编辑:Alfonso
2018-6-30
Hello Matt, as you are using XX I assume the code you wrote must go inside the function I posted after: XX = X-T?
I have tried this:
X = newnodes1;
T = repmat(mean(X),[size(X,1),1]);
XX = X-T;
normal=null(XX);
normal=normal(:,end)*sign(normal(1,end));
rotaxis=-cross([0,0,1].',normal);
theta=asind(norm(rotaxis));
[2D_data,R,~] = AxelRot(XX.', theta, rotaxis, []);
but the transformation from 3D to 2D does nor perform correctly, surely I am misunderstanding something.
Matt J
2018-6-30
编辑:Matt J
2018-6-30
"2D_data" is not a valid Matlab variable name. That will surely throw an error.
Try this,
X = newnodes1;
T = repmat(mean(X),[size(X,1),1]);
XX = X-T;
normal=null(XX);
normal=normal(:,end);
rotaxis=cross(normal,[0,0,1].');
s=-sign(mean(sign(rotaxis(1:2)))); %decide which way is "left"
rotaxis=s*rotaxis;
theta=acosd(s*normal(3));
[D,R,~] = AxelRot(XX.', theta, rotaxis, []);
D=D(1:2,:).';
Alfonso
2018-7-1
编辑:Alfonso
2018-7-1
Hello Matt, I am testing it with all my 3D datasets right now. If I have understood correctly, if I mantain the sign of 's' as, say +, it will always force the rotation to go the same way, so the 3D data will always flatten in this direction (what is what I'm looking for),
I'll let you know when I finish testing the datasets,
Thank you.
Alfonso
2018-7-1
编辑:Alfonso
2018-7-1
Works perfectly as I want to with the 3D dataset I initially posted and also work right for 3D datasets that belong to the same plane as the initial dataset, but I have tried with a different 3D cloud of points that belong to another plane and all values in the resulting 2D data are NaN, do you know what might be the problem?
Seems to me maybe the problem is in here (I am not sure)
s=-sign(mean(sign(rotaxis(1:2))));
rotaxis(1:2)=
0.0000
-0.4472
% So the sign will be the mean between 1 and -1, which is 0
rotaxis=s*rotaxis; % will give [0;0;0]
also warning messages appear:
Warning: Matrix is singular, close to singular or badly scaled. Results may be inaccurate. RCOND = NaN.
> In AxelRot (line 94)
> In AxelRot (line 63)
I have attached the 3D dataset,
Thank you.
Matt J
2018-7-1
编辑:Matt J
2018-7-1
You need to give us a more precise and general definition of "rotate to the left". Which way is "left", in general, if the 3D orientation of the cloud can be arbitrary? Perhaps this?
normal=null(XX);
normal=normal(:,end);
rotaxis=cross(normal,[0,0,1].');
[~,idx]=max(abs(rotaxis));
s=-sign(rotaxis(idx)); %decide which way is "left"
Alfonso
2018-7-1
I will try this code. In order to understand what I mean, I have attached two figures, one represents que 3D data converted to 2D rotated to the "left" and the other figure is rotated to the "right". Manually rotate the figures and that way I think you will know what I mean by left/right.
Thank you.
Matt J
2018-7-1
编辑:Matt J
2018-7-1
OK, well see if you like my last implementation.
However, your attached .fig files don't clear up the ambiguity. Your notions of "right" and "left" appear to depend arbitrarily on the plot camera angle. For example, if we were to rotate the plot perspective 180 degrees about the z-axis, so that we were viewing the original blue points from the opposite side, then left would become right and right would become left.
To put it another way, suppose your blue points lay entirely in the xz-plane. I know you want the points rotated clockwise all the time about a consistent axis, and I know that axis is either the positive x-axis or the negative x-axis, but which one is it? Similarly, what about if the data is in the yz-plane. Do we rotate clockwise about y or about -y?
Alfonso
2018-7-1
编辑:Alfonso
2018-7-1
Yes, it is quite ambiguous, but it's hard to explain. Look at this view, I want the the 2D data to be like the 3D data in this view. The result is the magenta plot, which is like if you pushed the top part of the blue plot with your hand about 90º. This is the 2D "view" I am looking for for all my 3D datasets.
I have tried your new code and seems to work right. I have 3 type of 3D data planes, for one I get the 2D view I want with - sign for the second one with + sign, and the third one is a horizontal plane so I just put the angle of rotation to 0 and I get the correct view.
I will test it with more 3D datasets of this 3 planes to see if for all datasets of the same plane it satisfies the same sign (-/+), but at the moment it looks like it works just as I wanted.
for example this is what I should get (a general sign for all datasets of the same plane):
All 3D datasets of plane1: correct view with sign -
All 3D datasets of plane2: correct view with sign +
Alfonso
2018-7-4
Hello Matt, with a few modifications I think I finally got it to work right. Thank you for your help.
更多回答(0 个)
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Point Cloud Processing 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!发生错误
由于页面发生更改,无法完成操作。请重新加载页面以查看其更新后的状态。
您也可以从以下列表中选择网站:
如何获得最佳网站性能
选择中国网站(中文或英文)以获得最佳网站性能。其他 MathWorks 国家/地区网站并未针对您所在位置的访问进行优化。
美洲
- América Latina (Español)
- Canada (English)
- United States (English)
欧洲
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom(English)
亚太
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)