【发布时间】:2016-04-11 04:35:23
【问题描述】:
正如标题所说,我想通过使用相邻像素的叉积来计算给定深度图像的表面法线。我想为此使用 Opencv 并避免使用 PCL,但是我并不真正了解该过程,因为我在该主题上的知识非常有限。因此,如果有人可以提供一些提示,我将不胜感激。这里提一下,除了深度图和对应的rgb图,我没有其他信息,所以没有K相机矩阵信息。
因此,假设我们有以下深度图像:
我想在对应点找到具有对应深度值的法线向量,如下图所示:
如何使用相邻像素的叉积来做到这一点?如果法线不是很准确,我不介意。
谢谢。
更新:
好的,我试图按照@timday 的回答将他的代码移植到 Opencv。使用以下代码:
Mat depth = <my_depth_image> of type CV_32FC1
Mat normals(depth.size(), CV_32FC3);
for(int x = 0; x < depth.rows; ++x)
{
for(int y = 0; y < depth.cols; ++y)
{
float dzdx = (depth.at<float>(x+1, y) - depth.at<float>(x-1, y)) / 2.0;
float dzdy = (depth.at<float>(x, y+1) - depth.at<float>(x, y-1)) / 2.0;
Vec3f d(-dzdx, -dzdy, 1.0f);
Vec3f n = normalize(d);
normals.at<Vec3f>(x, y) = n;
}
}
imshow("depth", depth / 255);
imshow("normals", normals);
我得到了正确的以下结果(我必须将 double 替换为 float 和 Vecd 到 Vecf,但我不知道为什么会有所不同):
【问题讨论】:
-
取决于当您转储矢量图像时 OpenCV 会做什么。看起来您的 XYZ 没有映射到 RGB,并且如果没有缩放,正/负分量范围可能无法很好地映射到 0-255 像素值。这就是为什么我的代码还包含一个简单的着色模型来从法线生成灰度图像。
-
嗨@timday我不认为这是一个Opencv问题,因为如果我将法线从Matlab脚本加载到Opencv和
imshow()它们,那么与上面的图像相比,我会得到一个很好的图像. -
您可能会发现this 很有用。
-
@dhanushka 非常有趣的链接。谢谢。
-
感谢您的更新。一个小的修正是,在大多数情况下,访问 cv::Mat (y,x) 而图像点是 cv::Point(x,y,z)。因此,您的行中的“x”不匹配?保持循环命名相同,正常应该是 'Vec3f d(-dzdy, -dzdx, 1.0f);'。
标签: c++ opencv depth normals cross-product