三角测量点问题

时间:2018-12-03 07:21:06

标签: c++ opencv opencv3.0

我正在使用Qt5和计算机视觉库OpenCV3设计带有很多控件的用户界面。为了更好地解释问题,我创建了一个小型工作应用程序,该应用程序完全复制了我过去几天一直在尝试解决的问题。 在使用黑白相机和彩色相机获取校准文件.yml(包含在Bitbucket的cam_calib文件夹中)之后,我试图使用OpenCV库中的三角测量功能来计算两个点的距离。

在这里,我创建了一个Bitbucket,以下载我编写的最小应用程序作为示例。该应用程序很小,但是我必须附加库,该库具有取决于应用程序的所有相机功能。 git clone https://ERaggi@bitbucket.org/ERaggi/matchingqtopencv.git

正如您在下面的第一个屏幕中看到的那样,我具有左右QGraphicsView。现在理所当然的是,我的图形驱动程序在最近几天无法正常工作(这解释了为什么图像以左侧的非常奇怪的方式显示),用户界面有时似乎工作正常,有时完全关闭。我注意到这种行为是由于点击发生在何处:

第一张图像是设置后的结果:1)搜索区域(设置区域大小),2)QComboBox中的Point选项,最后3)单击左侧的随机点查看

enter image description here

在第二张图像中,我执行相同的操作,但是我单击图像中的其他点,但始终在左视图中。

enter image description here

因此,我要概述的步骤是

1)上传黑白相机的校准图像(左视图),并上传我以黑白方式转换的右相机的彩色图像(右视图)。

2)我将搜索区域(.ui上的“设置区域大小”)设置为始终为奇数,因为它表示一个矩阵nxn,它将在图像B中的同一像素行上进行搜索(右)。

3)搜索由红色正方形表示,可以在屏幕截图中看到。那个正方形正在移动并计算每个像素的最小误差向量,一旦存在对应关系,到达行尾后,它将返回找到最小误差的位置。 找到的红场被提取并按照libCam文件的 stereocal.cpp 处理,保存在桌面文件夹中,并显示在此处:

///Write cropped match regions
void StereoCal::cropMatches(int xa, int ya, int xb, int yb){
    cv::Point ptA=cv::Point(xa, ya);
    cv::Point ptB=cv::Point(xb, yb);
    cv::Size sz;
    sz.height=regionSize;
    sz.width=regionSize;

    cv::Mat regionA, regionB;
    cv::getRectSubPix(currentImages.getA().get8Bitmap(),sz,ptA,regionA);
    cv::getRectSubPix(currentImages.getB().get8Bitmap(),sz,ptB,regionB);
    std::string path = "/home/emanuele/Desktop/croppedMatches/";
    std::string outA = path+"cropA.tiff";
    std::string outB = path+"cropB.tiff";
    cv::imwrite(outA,regionA);
    cv::imwrite(outB,regionB);
}

该错误是在libCam库的 stereocal.cpp 文件中计算的。参见下文,我该怎么做:

double StereoCal::getError(int xa, int ya, int xb, int yb){
    double error=0.0;
    Image aT,bT;
    cv::Mat a,b;
    aT=currentImages.getA();
    if(aT.getBitmap().channels() > 2) {
        aT.toGrey();
    }
    aT.getBitmap().convertTo(a, CV_32F);
    bT=currentImages.getB();
    if(bT.getBitmap().channels() > 2) {
        bT.toGrey();
    }
    bT.getBitmap().convertTo(b, CV_32F);
        for (int kx = -km; kx <= km; kx++){
            for(int ky = -km; ky <= km; ky++){
                error += std::pow((a.at<float>(ya+kx,xa+ky)-b.at<float>(yb+kx,xb+ky)),2);
            }
        }
    return error;
}

所以问题是:在单击左图后,在右图上进行搜索,我找到了第一个点的第一个深度(Z)坐标(因此计算了三角剖分)。为了可视化,我计算了从观察者到棕点的黑线:

enter image description here

第二次单击后,在进行新搜索时,将从“ XYZ坐标凸轮A”提取的第一组坐标将移动到“ XYZ先前凸轮A”上。正方形到达终点后,将发布第二个坐标(从观察者到我单击的第二点的黑线之间的距离):

enter image description here

从技术上使用毕达哥拉(Pithagora)定理,我应该获得如下所示的结果向量,相关的代码可以在文件 windowingdialog.cpp 中找到:

void windowingDialog::refreshDistance3D()
{
    double ax = ui->leftCoordX->text().toDouble();
    double ay = ui->leftCoordY->text().toDouble();
    double az = ui->leftCoordDepth->text().toDouble();
    double bx = ui->pp_ax->text().toDouble();
    double by = ui->pp_ay->text().toDouble();
    double bz = ui->pp_az->text().toDouble();

    double distance = sqrt(pow(bx-ax, 2) + pow(by-ay, 2) + pow(bz-az, 2));

    ui->distAB->setText(QString("%1").arg(distance));
}

enter image description here

但是我得到了一个非常奇怪的计算结果,即 9182.13 mm(此应用中的距离以毫米为单位)。有时候,它似乎运作良好,但似乎很大程度上取决于第二次点击发生的位置。从上方图像和下方结果的最终详细图像中,可以从用户界面“距离拖曳点”上的标签中看到结果,在第二个搜索点之后获得一些负坐标:

enter image description here

我不知道发生了什么。我遵循了triangulation documentation from OpenCV,而我使用的代码如下:

cv::Vec3d StereoCal::triangulatePoints(std::vector<cv::Point2f> a, std::vector<cv::Point2f> b){
    cv::Mat triangulatedPts;
    cv::triangulatePoints(P1, P2, a, b, triangulatedPts);
    cv::Vec3d coords3D;
// this loop will give us xyz divided by the conversion factor
    for(int i=0; i<triangulatedPts.size().width;i++){
        cv::Vec4d triangCoords =  triangulatedPts.col(i);
        for (unsigned int j = 0; j < 3; j++) {
            coords3D[j] = triangCoords[j] / triangCoords[3];
            std::cout<<coords3D[j] <<std::endl; // depth is shown here
        }
    }
    return(coords3D);
}

如果有人可以看看正在发生的事情,那就太好了,因为我已经为此努力了几天。很抱歉提供冗长的解释,但我想确保正确解释问题和遵循的步骤。 请为我指出如何解决此问题的正确方向。

0 个答案:

没有答案