首页 文章

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

提问于
浏览
4

我试图使用MATLAB将两个图像 - 一个rgb和另一个深度对齐 . 请注意,我已经为此检查了几个地方 - 例如需要kinect设备的hereherehere 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
.

然而它们是如此嘈杂,以至于我认为我们不能为这些图像进行关键点匹配 .

Can anybody suggest some algorithms in matlab to do the same ?

2 回答

  • 3

    prologue

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

    我手动裁剪您的输入图像,所以我分离颜色和深度图像(因为我的程序需要它们分开 . 这可能会导致较小的偏移量变化几个像素 . 另外因为我没有深度(深度图像是 8bit 仅由于灰度 RGB )然后我使用的深度精度非常差,请参阅:

    depth

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

    • determine FOV for both images

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

    FOV

    • form a point cloud or mesh

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

    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
            }
        }
    

    其中 **xyz 是我的点 Cloud 2D阵列分配的深度图像分辨率 . pictureDIP 的图像类,所以这里有一些相关成员:

    • xs,ys 是以像素为单位的图像分辨率

    • p[ys][xs] 是图像直接像素访问作为 DWORD dd; BYTE db[4]; 的并集,所以我可以分别访问单个32位变量或每个颜色通道的颜色 .

    • rgb2bgr(DWORD col) 只需将颜色通道从 RGB 重新排序到 BGR .

    • render it

    我使用 OpenGL 这样代码:

    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();
    

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

    colors

    • align it

    如果您注意到我将 ofsx,ofsy 变量添加到 copy_images() . 这是相机之间的偏移 . 我通过 1 像素在箭头按键上更改它们,然后调用 copy_images 并渲染结果 . 这样我就可以非常快速地手动找到偏移:

    align

    如您所见,偏移在x轴上为 +17 像素,在y轴上为 +4 像素 . 这里侧视图可以更好地看到深度:

    side

    希望它有点帮助

  • 1

    好吧,我在阅读了很多博客之后尝试过这样做 . 我仍然不确定我是否正确 . 如果发现有问题,请随时发表评论 . 为此,我使用了一个mathworks fex提交,可以在这里找到:ginputc 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图像的边缘,然后使用阈值来获得边缘图 . 我将主要使用梯度幅度 . 这给了我两个图像:

    rgb_edge

    depth_edge

    第2步

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

    enter image description here

    第3步

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

    matched_inlier image

    Recovered Image

    difference with original

    difference with restored

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

相关问题