使用MATLAB来可视化三维点云上的法向量

下面展示一种在三维点云上可视化法向量的方法,将单位向量映射到RGB立方体上相应的RGB颜色。用于将三维点云或网格数据上的法向矢量可视化为彩色,而不是法向量箭头因为有时很难看清楚箭头的指向。
对于点云中的一个点可以表达如下:

quiver3(x,y,z,u,v,w)

x,y,z是点的3个坐标量,u,v,w是矢量分量。在球体上,点的颜色值反映法线方向。demo如下:

clc
subdiv = 500;
[X,Y,Z] = sphere(subdiv-1);
Normals = [X(:), Y(:), Z(:)]; 
mappedRGB = Sphere2RGBCube(Normals);
%可视化
figure('color','w');
axes('color','w');
hold on
scatter3(X(:),Y(:),Z(:),50,mappedRGB,'.');
% surf(X,Y,Z,'cdata', reshape(mappedRGB, [subdiv, subdiv, 3]), 'edgecolor','none');  
view(3);
axis off
daspect([1,1,1]);

结果
在这里插入图片描述
在左上角,您可以看到RGB立方体。在左下角,可以看到带有贴图颜色的单位球体。两者都包含一个小的红点,可以使用键盘箭头键移动,右侧可以看到红色点的颜色和相应的RGB值。

函数说明

Sphere2RGBCube函数为不精确版本,它创建一个更平滑的颜色映射,将标准化向量v(表示单位sphere上的点)转换为其相应的rgb 立方体上的值,对于为零矢量输出为NaN。

function [ RGB ] = Sphere2RGBCube( V )

if size(V,2) > 3
    V = V';
    transposeglag = true;
else 
    transposeglag = false; 
end
RGB = zeros(size(V));
V = V./repmat((sqrt(sum(V.^2,2))),1,3); %make sure V is normalized
%Map from unit cube to RGB Cube 
RGB = 0.5*V+0.5;
RGB(all(isnan(V),2),:)=nan; % zero vectors are mapped to black
if transposeglag
    RGB = RGB';
end
end

Sphere2RGBCube_accurate为精确版本,在立方体平面上生成RGB颜色,在绘制球体时,颜色映射将更加尖锐。

function [ RGB ] = Sphere2RGBCube_accurate( V )

if size(V,2) > 3
    V = V';
    transposeglag = true;
else 
    transposeglag = false; 
end
RGB = zeros(size(V));
V = V./repmat((sqrt(sum(V.^2,2))),1,3); %make sure V is normalized
%Map unit sphere to unit cube
x = V(:,1);
y = V(:,2);
z = V(:,3);
absx = abs(x);
absy = abs(y);
absz = abs(z);
%Map left and right cube planes  : y=+-1
leftright = and(absy>=absx, absy>=absz);
RGB(leftright,1) = (1 ./ absy(leftright)).*x(leftright); 
RGB(leftright,3) = (1 ./ absy(leftright)).*z(leftright);
RGB(and(leftright , y > 0),2) = 1;
RGB(and(leftright , y < 0),2) = -1;
%Map front and back cube planes  : x=+-1
frontback = and(absx >= absy , absx >= absz);
RGB(frontback,2) = (1 ./ absx(frontback)).*y(frontback); 
RGB(frontback,3) = (1 ./ absx(frontback)).*z(frontback);
RGB(and(frontback , x > 0),1) = 1;
RGB(and(frontback , x < 0),1) = -1;
%Map top and bottom cube planes  : z=+-1
topbottom = and(absz >= absx , absz >= absy);
RGB(topbottom,1) = (1 ./ absz(topbottom)).*x(topbottom); 
RGB(topbottom,2) = (1 ./ absz(topbottom)).*y(topbottom);
RGB(and(topbottom , z > 0),3) = 1;
RGB(and(topbottom , z < 0),3) = -1;         
%Map from unit cube to RGB Cube 
RGB = 0.5*RGB+0.5;
RGB(all(isnan(V),2),:)=nan; % zero vectors are mapped to black
if transposeglag
    RGB = RGB';
end
end

TestSphere2CubeMapping,其将单位向量转换为单位球面上相应的RGB值颜色来展示法向量。

function TestSphere2CubeMapping()

clear all
clc
global  Phi Teta ax1 ax2 ax3
 Phi = 0;
 Teta = 0;
 
figure('numbertitle','off','name','Sphere to RGB Cube Visualizatoin','KeyPressFcn',@KeyboardCB,'color','w','renderer','zbuffer')
ax1 = axes('outerposition',[0 0 0.5 0.5]);
title('Mapped color sphere');
setviewparams()
axis off
ax3 = axes('outerposition',[0 0.5 0.5 0.5]);
title('RGB cube');
setviewparams()
axis off
ax2 = axes('outerposition',[0.5 0 0.5 1]);
title('Color indicator');
daspect([1,1,1]);
xlim([-1,1]);
ylim([-1,1]);
zlim([-1,1]);
axis off
  set(gcf,'currentaxes',ax1);
  DrawingCB();
end
function DrawingCB()
% 绘制 
global  Phi Teta ax1 ax2 ax3
hold all
 testVec = [ sind(Teta)*cosd(Phi), sind(Teta)*sind(Phi), cosd(Teta) ]; % This is the vector on the sphere to be mapped to a color
 scatter3( testVec(1),testVec(2),testVec(3), 100, 'r', '.'); % pointer on sphere
  
 [ RGB ] = Sphere2RGBCube_accurate( testVec ); % convert the color
 
 % 可视化球体
 set(gcf,'currentaxes',ax1);
 [X,Y,Z] = sphere(30);
 Spherecolor = Sphere2RGBCube( [X(:),Y(:),Z(:)] ); % convert all of sphere points to RGB color space 
sphere_h=surf(X,Y,Z,'cdata',reshape(Spherecolor,[size(X,1),size(X,2),3]),'edgecolor','none','facecolor','interp');
 view([45, 35.264]);
 
 %可视化立方体
 set(gcf,'currentaxes',ax3);
 cube_hh=drawCube ( );
 hold on
 scatter3( RGB(1)*2-1,RGB(2)*2-1,RGB(3)*2-1,  100, 'r', '.'); %Pointer on cube
view([45, 35.264]);
 
%可视化法向量
%quiver3(0,0,0,testVec(1),testVec(2),testVec(3));
%quiver3(0,0,0,RGB(1)*2-1,RGB(2)*2-1,RGB(3)*2-1);
%可视化颜色反馈指示器
set(gcf,'currentaxes',ax2);
patch([-1 -1 1 1]*0.5,[-1 1 1 -1]*0.5,RGB,'edgecolor','none');
text(0.5,0.5,{['R = ' num2str(RGB(1),'%2.3f')]; ['G = ' num2str(RGB(2),'%2.3f')]; ['B = ' num2str(RGB(3),'%2.3f')] },'fontunits','normalized',...
    'fontsize',0.05,'units','normalized','horizontalalignment','center');
set(gcf,'currentaxes',ax1);
end

drawCube绘制立方体

function cube=drawCube (  )
%drawcube draws a cube around (0,0,0) with edge length of 1 and return the cubes
%graphic handle
%INPUT: None
%OUTPUT: cube - a handle of the patches drawn
%Initialize cube parameters
FV.vertices= [0 0 0; 0 1 0; 1 1 0; 1 0 0;0 0 1; 0 1 1; 1 1 1; 1 0 1]*2 -1;
FV.faces = [1 2 3 4; 2 3 7 6; 3 4 8 7;4 1 5 8; 1 2 6 5;5 6 7 8];
%Define patches color
cdata =[0 0 0; 0 1 0; 1 1 0; 1 0 0;0 0 1; 0 1 1; 1 1 1; 1 0 1];
cube = patch('vertices',FV.vertices,'faces',FV.faces,'facevertexcdata',cdata,'facecolor','interp');
set(cube,'edgecolor','none','facevertexalphadata',0.2);
end

KeyboardCB箭头移动键盘响应

function [  ] = KeyboardCB(hObject,event)
global  Phi Teta ax1 ax2 ax3
switch event.Key
    case 'leftarrow'
        Phi=Phi-5;
    case 'rightarrow'
        Phi=Phi+5;
    case 'uparrow'
        Teta=Teta-5;
    case 'downarrow'
        Teta=Teta+5;
end
cla(ax1);
cla(ax2);
cla(ax3);
DrawingCB();
end
function [] = setviewparams()
% set the view parameters
daspect([1,1,1]);
xlim([-1,1]);
ylim([-1,1]);
zlim([-1,1]);
end
  • 1
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值