最近在处理一个数据库,该数据库有kinectv2设备采集,分为rgb图,红外infraded图和深度depth图,但是该数据库没有对深度图和rgb图片进行对齐,都是裸数据,即rgb为1080x1920,depth为424x512.在网上查阅了资料,有人说可以直接利用kinect的sdk进行求解,但是我没有做这个实验,第一是因为自己并不熟悉C++,还要安装kinect sdk和opencv库;第二,我觉得就算安装了可能也用不了,因为不知道kinect相机的一些参数(这个是我自己得猜想可能不对,没有验证,如果有小伙伴做了这一步工作的话可能告知一下),所以,我就没有接着往下做.而是采用matlab进行对齐。
相机参数link分为外参和内参,内参指的是center和焦距,kinect一般都是一样的,这个参数差不多。
对于rgb摄像头,intrinsic参数(IntrinsicRGB的文件)为:
1034.3,0,0
1.6609,1034.3,0
970.63,529.07,1
对于红外摄像头,intrinsic参数(InvIntrinsicIR的文件)为:
0.0027132,0,-0
-1.8517e-05,0.0026991,-0
-0.69724,-0.54233,1
这两个intrinsic参数矩阵不用修改!!!
旋转平移矩阵(TransformationD-C)为:
0.99994,-0.0090793,0.0073288,52
0.009138,0.99992,-0.0079812,-10
-0.0072615,0.0080413,0.99995,1
37.331,-42.241,-88.088,1
前三行三列表示的是旋转矩阵,可以理解成两个相机之间的角度,最后一列表示的是平移矩阵,最后一行没有用到。
值得一提的是,因为我没有这个数据库采集用的kinect设备,所以我并不知道实际的参数,所以参数都是在github上找的,对于红外摄像头和rgb摄像头的intrinsic参数,我并没有任何修改(因为内参基本一样),而对于transformD-C的4*4矩阵,我做了一些微调,是它能够更好的对齐(因为不同kinect的摄像头外参不一样),如果发现depth和color之间转换后的图片不平行,那么要对旋转角度进行调整(一般不用调);如果发现depth和color之间需要平移才能完全对齐,那么就调整平移矩阵,也就是TransformationD-C的最后一列。如果你的数据库还提供这些参数,那么你完全可以用你自己的参数,不需要自己调。
代码总共分为了5个文件,分别为
main_script.m,alignImage.m,IntrinsicRGB,InvIntrinsicIR,TransformationD-C。直接运行main_script.m脚本就可以了。
,IntrinsicRGB,InvIntrinsicIR,TransformationD-C存放就是上面说的三个矩阵参数。
由于自己懒得上传,而且也没想赚积分,就直接贴在这里了。
main_script.m代码为:
[colorizedDepth,coord] = alignImage('05.png','05.jpg','IntrinsicRGB','InvIntrinsicIR','TransformationD-C');%‘05.png’和'05.jpg'分别为424*512的深度图和对应的1080*1920的rgb图
%save computed data
imwrite(colorizedDepth,'Colorized_Depth.png');
figure,imshow(colorizedDepth);
alignImage.m代码为:
function [colorizedDepth, coordinateFrame,binaryDepth] = alignImage(depthImg, rgbImg, intrinsicRGB, intrinsicIR, transformMat)
%read images
depthImg_raw = imread(depthImg);
rgbImg_raw = imread(rgbImg);
intrinsicRGB = load(intrinsicRGB);
intrinsicIR = load(intrinsicIR);
transformMat = load(transformMat);
intrinsicIR = inv(intrinsicIR);
%generate camera parameter object
RGBcamPar = cameraParameters('IntrinsicMatrix',intrinsicRGB);
IRcamPar = cameraParameters('IntrinsicMatrix',intrinsicIR);
%undistort images first if there's any skew or lense distortion
depthImg = undistortImage(depthImg_raw,IRcamPar);
rgbImg = undistortImage(rgbImg_raw, RGBcamPar);
%get focal length and optical centers out of intrinsic matrices
fx_d = IRcamPar.FocalLength(1);
fy_d = IRcamPar.FocalLength(2);
cx_d = IRcamPar.PrincipalPoint(1);
cy_d = IRcamPar.PrincipalPoint(2);
fx_c = RGBcamPar.FocalLength(1);
fy_c = RGBcamPar.FocalLength(2);
cx_c = RGBcamPar.PrincipalPoint(1);
cy_c = RGBcamPar.PrincipalPoint(2);
depthHeight = size(depthImg,1);
depthWidth = size(depthImg,2);
rgbHeight = size(rgbImg,1);
rgbWidth = size(rgbImg,2);
%colorizedDepth_6layer image has X,Y,Z,R,G,B values in its layers
colorizedDepth_6layer = zeros(depthHeight,depthWidth,6);
binaryDepth = zeros(depthHeight,depthWidth,3);
for v = 1:(depthHeight)
for u = 1:(depthWidth)
%apply intrinsics
z = single(depthImg(v,u));
x = single((u - cx_d)*z)/fx_d;
y = single((v - cy_d)*z)/fy_d;
%apply extrinsic
transformed = (transformMat * [x;y;z;1])';
colorizedDepth_6layer(v,u,1) = transformed(1);
colorizedDepth_6layer(v,u,2) = transformed(2);
colorizedDepth_6layer(v,u,3) = transformed(3);
end
end
coordinateFrame = colorizedDepth_6layer(:,:,1:3);
for v = 1 : (depthHeight)
for u = 1 : (depthWidth)
% Apply RGB intrinsics
x = (colorizedDepth_6layer(v,u,1) * fx_c / colorizedDepth_6layer(v,u,3)) + cx_c;
y = (colorizedDepth_6layer(v,u,2) * fy_c / colorizedDepth_6layer(v,u,3)) + cy_c;
% "x" and "y" are indices into the RGB frame, but they may contain
% invalid values (which correspond to the parts of the scene not visible
% to the RGB camera.
% Do we have a valid index?
if (x > rgbWidth || y > rgbHeight ||...
x < 1 || y < 1 ||...
isnan(x) || isnan(y))
continue;
end
% Need some kind of interpolation. I just did it the lazy way
x = round(x);
y = round(y);
colorizedDepth_6layer(v,u,4) = uint8(rgbImg(y, x, 1));
colorizedDepth_6layer(v,u,5) = uint8(rgbImg(y, x, 2));
colorizedDepth_6layer(v,u,6) = uint8(rgbImg(y, x, 3));
end
end
colorizedDepth = uint8(colorizedDepth_6layer(:,:,4:6));
end
这个是我对齐后的结果,由于数据库是从别人那里拿来的,为了保护别人的隐私,我将他的脸给划掉了,但还是可以看出depth和color能很好的对齐。