4

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

图片

基本事实基本上意味着已经提供了指定感兴趣的面部区域的边界框,我只使用它们来裁剪面部区域。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 和深度如下所示:裁剪图像


有什么方法可以注册/对齐图像。我从 这里得到了提示,在 rgb 和深度图像上都使用了基本的 sobel 算子来生成边缘图,然后需要生成关键点来进行匹配。两个图像的边缘图都是在这里生成的。

edge_map.

但是它们太吵了,我认为我们无法对这些图像进行关键点匹配。

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

4

2 回答 2

3

序幕

这个答案是基于我之前的答案:

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

深度

所以我的结果受到了这一切的负面影响。无论如何,这是您需要做的:

  1. 确定两个图像的 FOV

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

    视场

  2. 形成点云或网格

    我使用深度图像作为参考,所以我的点云在它的FOV中。因为我没有距离而是8bit值,所以我通过乘以常数将其转换为某个距离。因此,我扫描整个深度图像,并为每个像素在点云阵列中创建点。然后将 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我的点云二维数组在哪里分配了 t 深度图像分辨率。这是我的DIPpicture图像类,所以这里有一些相关成员:

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

    我为此使用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初始化和相机设置等。这里是未对齐的结果:

    颜色

  4. 对齐它

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

    对齐

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

    边

希望它有点帮助

于 2016-03-10T10:36:39.657 回答
1

好吧,在阅读了很多博客和所有内容之后,我已经尝试过这样做。我仍然不确定我这样做是否正确。如果发现有问题,请随时发表评论。为此,我使用了可以在此处找到的 mathworks fex 提交:ginputc函数。

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步

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

在此处输入图像描述

第 3 步

使用estimategeometrictransform得到变换矩阵tform,然后使用该矩阵恢复移动图像的原始位置。下一组图像讲述了这个故事。

匹配的内部图像

恢复的图像

与原版的区别

与恢复的区别

当然,我仍然相信,如果任一图像中的关键点选择更加明智,结果可以进一步改善。我也认为@Specktre 方法更好。我只是注意到,与问题相比,我在答案中使用了单独的图像对。两张图片都来自同一个数据集,可在此处找到vap rgb-dt dataset

于 2016-03-12T17:12:43.350 回答