MATLAB画出点云法向量之后,向量朝向不一致该如何解决,如何让向量箭头一致都朝左边指。

MATLAB画出点云中一下点的法向量之后,向量朝向不一致该如何解决,想让向量箭头都朝左边指,下面是我画出的图:

img


下面是我的代码:
(其中p.txt和q.txt两个文件我上传到了百度网盘:
链接:https://pan.baidu.com/s/1RSkgnOPen9C-Kvx_YxL45g
提取码:p2q2)

load q.txt
load p.txt
%MYNORMALVECTOR 采用PCA算法求取交点矩阵的每个点的法向量。
%Input: 
%      q是Nx3的矩阵,包含交点的三维坐标信息[X,Y,Z]。
%      p是Nx3的矩阵,包含点云的三维坐标信息[X,Y,Z]。
%Output:
%      n是Nx3的矩阵,对应q中每一点的单位法向量。

N = size(q,1);
n = zeros(N,3); % 存放法线的矩阵
% 寻找每个点K近邻的索引
k = 200; % k近邻
[NeiborIndex,~] = knnsearch(p,q,'Distance','euclidean','NSMethod','kdtree','K',k);
for i=1:N
    % 当前点邻域点集的索引
    IndexOfCurrentNeibors = NeiborIndex(i,:);
    % 当前点邻域点集
    CurrentNeighbors = p(IndexOfCurrentNeibors,:);
    PtCent = mean(CurrentNeighbors); %得到局部点云平均值,便于计算法向量长度和方向    
    % PCA法计算法向量
    B = CurrentNeighbors - repmat(PtCent,k,1); % 去中心化点集矩阵
    PtCov = transpose(B)*B; %协方差矩阵
    % 求特征值、特征向量。 
    % D是对应的特征值对角矩阵,V是特征向量
    % (因为协方差矩阵为实对称矩阵,故特征向量为单位正交向量)
    [V,D] = eig(PtCov); 
    % d0为最小特征值  idx为特征值的列数索引。
    [~, idx] = min(diag(D)); % diag():创建对角矩阵或获取矩阵的对角元素
    n(i,:) = V(:,idx)';   % 最小特征值对应的特征向量为法矢,即单位法向量  
    % 朝向统一
    n1 = n(i,:);
    n2 = q(i,:);
    if dot(n1,n2)<0 % 如果这个向量与法向量的数量积为负数(反向)
        n(i,:) = -n(i,:);  % 法向量取反向
    end
end
ptCloud = pointCloud(q);
figure()
pcshow(ptCloud);
hold on 
quiver3(q(:,1),q(:,2),q(:,3),n(:,1),n(:,2),n(:,3));


你好,改成大家相邻之间法向量一致就行了

load q.txt
load p.txt
%MYNORMALVECTOR 采用PCA算法求取交点矩阵的每个点的法向量。
%Input: 
%      q是Nx3的矩阵,包含交点的三维坐标信息[X,Y,Z]。
%      p是Nx3的矩阵,包含点云的三维坐标信息[X,Y,Z]。
%Output:
%      n是Nx3的矩阵,对应q中每一点的单位法向量。
N = size(q,1);
n = zeros(N,3); % 存放法线的矩阵
% 寻找每个点K近邻的索引
k = 200; % k近邻
[NeiborIndex,~] = knnsearch(p,q,'Distance','euclidean','NSMethod','kdtree','K',k);
for i=1:N
    % 当前点邻域点集的索引
    IndexOfCurrentNeibors = NeiborIndex(i,:);
    % 当前点邻域点集
    CurrentNeighbors = p(IndexOfCurrentNeibors,:);
    PtCent = mean(CurrentNeighbors); %得到局部点云平均值,便于计算法向量长度和方向    
    % PCA法计算法向量
    B = CurrentNeighbors - repmat(PtCent,k,1); % 去中心化点集矩阵
    PtCov = transpose(B)*B; %协方差矩阵
    % 求特征值、特征向量。 
    % D是对应的特征值对角矩阵,V是特征向量
    % (因为协方差矩阵为实对称矩阵,故特征向量为单位正交向量)
    [V,D] = eig(PtCov); 
    % d0为最小特征值  idx为特征值的列数索引。
    [~, idx] = min(diag(D)); % diag():创建对角矩阵或获取矩阵的对角元素
    n(i,:) = V(:,idx)';   % 最小特征值对应的特征向量为法矢,即单位法向量  
    % 朝向统一
    % 改成两个相邻的向量方向要一致
    if(i>1)
        n1 = n(i,:);
        n2 = n(i-1,:);
        if(dot(n1,n2)<0)% 如果这个向量与法向量的数量积为负数(反向)
            n(i,:) = -n(i,:);  % 法向量取反向
        end
    end
end
ptCloud = pointCloud(q);
figure()
pcshow(ptCloud);
hold on 
quiver3(q(:,1),q(:,2),q(:,3),n(:,1),n(:,2),n(:,3));

img

如果都朝左边指向,程序中朝向统一的代码就需要修改:
原程序第31至36行改为以下程序试试


% 朝向统一
    if n(i,1) > 0  % 如果x方向法向量为正,则反向
        n(i,1) = -n(i,1);  % 法向量取反向
    end