深度图像上的表面法线

ask*_*uch 6 c++ opencv computer-vision

如何在不使用点云库(PCL)的情况下估计深度图像上的点I(i,j)的表面法线(像素值以mm为单位)?我已经研究过(1)(2)(3),但是我正在寻找使用C ++标准库或openCV对每个像素的表面法线进行简单估计。

在此处输入图片说明

Pho*_*ton 5

您需要知道相机的固有参数,以便还可以知道相同单位(mm)的像素之间的距离。像素之间的距离显然在距相机一定距离(即中心像素的值)时正确

如果相机矩阵为K,则通常为:

    f  0  cx
K=  0  f  cy
    0  0   1
Run Code Online (Sandbox Code Playgroud)

然后,取像素坐标(x,y),然后使用以下方法定义从相机原点到像素的射线(在相机世界坐标空间中):

              x
P = inv(K) *  y
              1
Run Code Online (Sandbox Code Playgroud)

取决于图像中的距离是Z轴上的投影还是到中心的欧几里得距离,您都需要对向量P进行归一化,以使其大小等于您想要的像素的距离,或者确保P的z分量就是这个距离。对于围绕帧中心的像素,此像素应接近相同。

如果对附近的像素(例如,左右)进行相同的操作,则以mm为单位得到Pl和Pr,然后找到(P1-Pr)的范数,该范数是相邻像素之间的距离(以mm为单位)的两倍。

然后,您可以计算X和Y中的梯度

gx = (Pi+1,j - Pi-1,j) / (2*pixel_size)
Run Code Online (Sandbox Code Playgroud)

然后,将两个梯度作为方向向量:

ax = atan(gx),  ay=atan(gy)


     | cos ax    0    sin ax |   |1|
dx = |    0      1       0   | * |0|
     | -sin ax   0    cos ax |   |0|

     |    1      0       0   |   |0|
dy = |    0   cos ay -sin ay | * |1|
     |    0   sin ay  cos ay |   |0|

N = cross(dx,dy);
Run Code Online (Sandbox Code Playgroud)

您可能需要通过查看特定的梯度并查看dx,dy指向预期方向的方式来查看符号是否有意义。您可能需要对一个/一个/两个角度都使用负值,对N个向量使用相同的值。