[db:标题]
摘要:这个东西是我接触的第一个非2D方面的算法,到目前为止其实也没有完全搞定,不过可能短时间内也无法突破。先把能搞定的搞定吧。 这个东西也有一大堆参考资料,不过呢,搜来搜去其实也就那些同样的东西,个人觉得就属这个文章最经典,既有说明,也有图片,还
这个东西是我接触的第一个非2D方面的算法,到目前为止其实也没有完全搞定,不过可能短时间内也无法突破。先把能搞定的搞定吧。
这个东西也有一大堆参考资料,不过呢,搜来搜去其实也就那些同样的东西,个人觉得就属这个文章最经典,既有说明,也有图片,还有代码:
Photometric Stereo Chaman Singh Verma and Mon-Ju Wu
https://pages.cs.wisc.edu/~csverma/CS766_09/Stereo/stereo.html
另外,github上也应该有一些参考的资料吧,我主要参考的是https://github.com/chaochaojnu这个中国小哥的博客。
目前为止,我只实现了提取Albedo、Normal Map和Normal Vectors三个结果。
从硬件上讲,这算法应该需要一个固定位置的相机(应该是要和目标垂直吧),以及至少3个以上的平行光源,一般实际上可能需要至少4个以上的光源吧,然后每个光源单独打光,单独拍一张图片,共得到N个不同的图片,然后根据这个N个图片,合成一个结果图以及得到额外的梯度和高度信息。
在Halcon中,有对应的photometric_stereo算子实现该功能,该算子除了要提供N个图片,还需要提供Slants和Tilts两个参数,你去看他们的英语翻译,其实都是倾斜角,个人理解Tilts就是光源在XY平面投影时和X轴的夹角,而Slants就是光源和XY平面的夹角。
在我刚刚提供的两个链接里,他们都不是直接提供Slants和Tilts,而是直接利用标准物体在对应光源下拍照,得到几幅标准图像,然后由标准图像的像素值推算出对应的归一化光源向量,这个方法也是不错了,省去了相机和光源位置的标定。
有了这些参数,就可以进行算法的执行了,对于Normal Map的获取,在Photometric Stereo这个文章里有一大堆推导,开始看不懂,慢慢的又觉得懂了,然后又有点懵逼,接着折腾又似乎清晰了。
其实不用管那么多,我们看看Photometric Stereo给出的NormalMap.m代码里的细节吧:
for i = 1:nrows
for j = 1:ncols
if( maskImage(i,j) )
for im = 1:numImages
I(im) = double(grayimages(i,j,im));
end
[NP,R,fail] = PixelNormal(I, lightMatrix);
surfNormals(i,j,1) = NP(1);
surfNormals(i,j,2) = NP(2);
surfNormals(i,j,3) = NP(3);
albedo(i,j) = R;
end
end
end
这里的surfNormals就是对应上图中的Normal Vectors,albedo就是反射率图。
lightMatrix是多个光源的向量,I是多个图对应的像素值,这里的关键在于PixelNormal函数。
unction [N,R, fail] = PixelNormal(I, L)
fail = 0;
I = I';
LT = L';
A = LT*L;
b = LT*I;
g = inv(A)*b;
R = norm(g);
N = g/R;
if( norm(I) < 1.0E-06)
fprintf( ' Warning: Pixel intensity is zero \n' );
N(1) = 0.0;
N(2) = 0.0;
N(3) = 0.0;
R = 0.0;
fail = 1;
end
end
仔细看这个函数,其实就是上面工时最后一部分的直接实现,什么转置、乘积、求逆、归一化等等。
这个M代码要稍微修改才可以运行,我尝试了下只是运行获取Normal Map这一块,4个500*500的大小的灰度图,需要大概2s的时间,这个时间其实对于工程项目本身来说是没有任何意义的。
