对齐已捕获的rgb和深度图像

时间:2016-03-10 07:09:18

标签: matlab image-processing kinect image-registration

我正在尝试使用MATLAB对齐两个图像 - 一个rgb和另一个深度。请注意,我已经检查了几个地方 - 例如herehere需要kinect设备,here here表示校准需要相机参数。我还建议使用EPIPOLAR GEOMETRY来匹配这两个图像,虽然我不知道如何。我引用的数据集在rgb-d-t face dataset中给出。一个这样的例子如下所示:

image

基本上已经提供了基本上意味着指定感兴趣的面部区域的边界框的基本事实,并且我仅使用它们来裁剪面部区域。 matlab代码如下所示:

I = imread('1.jpg');
I1 = imcrop(I,[218,198,158,122]);
I2 = imcrop(I,[243,209,140,108]);
figure, subplot(1,2,1),imshow(I1);
subplot(1,2,2),imshow(I2);

两个裁剪的图像rgb和深度如下所示:cropped_images

我们可以通过哪种方式注册/分配图像。我接受了提示 here其中基本的sobel算子已用于rgb和深度图像以生成边缘图,然后需要生成关键点以用于匹配目的。这里生成两个图像的边缘图。

edge_map

然而它们非常嘈杂,我认为我们不能为这些图像进行关键点匹配。

有人可以在matlab中建议一些算法来做同样的事吗?

2 个答案:

答案 0 :(得分:3)

<强>序言

这个答案基于我以前的答案:

我手动裁剪您的输入图像,因此我将颜色和深度图像分开(因为我的程序需要将它们分开。这可能会导致较小的偏移量变化几个像素。而且因为我没有深度(深度图像是{{1} }仅由于灰度 RGB ),我使用的深度精度非常差,请参阅:

depth

所以我的结果受到所有这些负面影响。无论如何,这是你需要做的:

  1. 确定两张图片的视野

    因此,在两个图像上都可以看到一些可测量的特征。尺寸越大,结果越准确。例如,我选择这些:

    FOV

  2. 形成点云或网格

    我使用深度图像作为参考,因此我的点云处于 FOV 。由于我没有距离而是8bit值,而是通过乘以常数将其转换为某个距离。所以我扫描整个深度图像,对于每个像素,我在点云阵列中创建点。然后将dept像素坐标转换为彩色图像 FOV 并复制其颜色。这样的事情(在 C ++ 中):

    8bit

    其中picture rgb,zed; // your input images struct pnt3d { float pos[3]; DWORD rgb; pnt3d(){}; pnt3d(pnt3d& a){ *this=a; }; ~pnt3d(){}; pnt3d* operator = (const pnt3d *a) { *this=*a; return this; }; /*pnt3d* operator = (const pnt3d &a) { ...copy... return this; };*/ }; pnt3d **xyz=NULL; int xs,ys,ofsx=0,ofsy=0; void copy_images() { int x,y,x0,y0; float xx,yy; pnt3d *p; for (y=0;y<ys;y++) for (x=0;x<xs;x++) { p=&xyz[y][x]; // copy point from depth image p->pos[0]=2.000*((float(x)/float(xs))-0.5); p->pos[1]=2.000*((float(y)/float(ys))-0.5)*(float(ys)/float(xs)); p->pos[2]=10.0*float(DWORD(zed.p[y][x].db[0]))/255.0; // convert dept image x,y to color image space (FOV correction) xx=float(x)-(0.5*float(xs)); yy=float(y)-(0.5*float(ys)); xx*=98.0/108.0; yy*=106.0/119.0; xx+=0.5*float(rgb.xs); yy+=0.5*float(rgb.ys); x0=xx; x0+=ofsx; y0=yy; y0+=ofsy; // copy color from rgb image if in range p->rgb=0x00000000; // black if ((x0>=0)&&(x0<rgb.xs)) if ((y0>=0)&&(y0<rgb.ys)) p->rgb=rgb2bgr(rgb.p[y0][x0].dd); // OpenGL has reverse RGBorder then my image } } 是我的点云2D阵列分配了深度图像分辨率。 **xyz DIP 的图片类,所以这里有一些相关成员:

    • picture是以像素为单位的图像分辨率
    • xs,ys是图像直接像素访问作为p[ys][xs]的并集,因此我可以分别访问单个32位变量或每个颜色通道的颜色。
    • DWORD dd; BYTE db[4];只需将颜色通道从 RGB 重新排序为 BGR
  3. 渲染

    我使用 OpenGL ,所以这里是代码:

    rgb2bgr(DWORD col)

    您需要添加粗略的 OpenGL 初始化和相机设置等。这里是未对齐的结果:

    colors

  4. 对齐

    如果您发现我已将 glBegin(GL_QUADS); for (int y0=0,y1=1;y1<ys;y0++,y1++) for (int x0=0,x1=1;x1<xs;x0++,x1++) { float z,z0,z1; z=xyz[y0][x0].pos[2]; z0=z; z1=z0; z=xyz[y0][x1].pos[2]; if (z0>z) z0=z; if (z1<z) z1=z; z=xyz[y1][x0].pos[2]; if (z0>z) z0=z; if (z1<z) z1=z; z=xyz[y1][x1].pos[2]; if (z0>z) z0=z; if (z1<z) z1=z; if (z0 <=0.01) continue; if (z1 >=3.90) continue; // 3.972 pre vsetko nad .=3.95m a 4.000 ak nechyti vobec nic if (z1-z0>=0.10) continue; glColor4ubv((BYTE* )&xyz[y0][x0].rgb); glVertex3fv((float*)&xyz[y0][x0].pos); glColor4ubv((BYTE* )&xyz[y0][x1].rgb); glVertex3fv((float*)&xyz[y0][x1].pos); glColor4ubv((BYTE* )&xyz[y1][x1].rgb); glVertex3fv((float*)&xyz[y1][x1].pos); glColor4ubv((BYTE* )&xyz[y1][x0].rgb); glVertex3fv((float*)&xyz[y1][x0].pos); } glEnd(); 个变量添加到ofsx,ofsy。这是相机之间的偏移。我按copy_images()像素按箭头按键更改它们,然后调用1并渲染结果。这样我就可以非常快速地手动找到偏移量:

    align

    如您所见,偏移是x轴的copy_images像素和y轴的+17像素。这里侧视图可以更好地看到深度:

    side

  5. 希望它有点帮助

答案 1 :(得分:1)

好吧,我在阅读了很多博客之后尝试过这样做。我仍然不确定我是否正确。如果发现有问题,请随时发表评论。为此我使用了mathworks fex提交,可以在这里找到:native SDK function。

matlab代码如下:

clc; clear all; close all;

% no of keypoint 
N = 7; 

I  = imread('2.jpg');
I = rgb2gray(I);
[Gx, Gy] = imgradientxy(I, 'Sobel');
[Gmag, ~] = imgradient(Gx, Gy);
figure, imshow(Gmag, [ ]), title('Gradient magnitude')
I = Gmag;

[x,y] = ginputc(N, 'Color' , 'r');
matchedpoint1 = [x y];

J = imread('2.png');
[Gx, Gy] = imgradientxy(J, 'Sobel');
[Gmag, ~] = imgradient(Gx, Gy);
figure, imshow(Gmag, [ ]), title('Gradient magnitude')
J = Gmag;

[x, y] = ginputc(N, 'Color' , 'r');
matchedpoint2 = [x y];    

[tform,inlierPtsDistorted,inlierPtsOriginal] = estimateGeometricTransform(matchedpoint2,matchedpoint1,'similarity');
figure; showMatchedFeatures(J,I,inlierPtsOriginal,inlierPtsDistorted);
title('Matched inlier points');

I = imread('2.jpg'); J = imread('2.png');
I = rgb2gray(I);
outputView = imref2d(size(I));
Ir = imwarp(J,tform,'OutputView',outputView);
figure; imshow(Ir, []);
title('Recovered image');    

figure,imshowpair(I,J,'diff'),title('Difference with original');
figure,imshowpair(I,Ir,'diff'),title('Difference with restored');

第1步

我使用sobel边缘检测器提取深度和rgb图像的边缘,然后使用阈值来获取边缘图。我将主要使用梯度幅度。这给了我两个图像:

ginputc rgb_edge

第2步

接下来,我使用ginputginputc函数标记两个图像上的关键点。点之间的对应关系是由我预先确定的。我尝试使用SURF功能,但它们在深度图像上效果不佳。

depth_edge

第3步

使用estimategeometrictransform获取转换矩阵tform,然后使用此矩阵恢复移动图像的原始位置。下一组图片讲述了这个故事。

enter image description here

matched_inlier image

Recovered Image

difference with original

当然,我仍然相信如果更明智地完成任一图像中的关键点选择,结果可以进一步改善。我也认为@Specktre方法更好。我只是注意到我在答案中使用了一个单独的图像对,而不是问题。这两个图像都来自同一个数据集difference with restored