九点标定 opencv 方式实现 手眼标定

opencv获取中心点位置代码:

Mat SrcMat(nImgWidth, nImgHeight, CV_8UC3);
    UCharToMat(pSrcImg, nImgHeight, nImgWidth, 24, SrcMat);

    Mat grayMat;
    cvtColor(SrcMat, grayMat, COLOR_BGR2GRAY);
    Mat binMat = cv::Mat::zeros(SrcMat.size(), CV_8UC1);
    MYThresHold(grayMat.data, binMat.data, SrcMat.cols, SrcMat.rows, params.nGrayMin, params.nGrayMax);

    vector<vector<Point> > contours;
    vector<Vec4i> hierarchy;
    findContours(binMat, contours, hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
    for (size_t i = 0; i < contours.size(); ++i) {
        double fArea = contourArea(contours[i]);
        if (fArea < params.nAreaMin || fArea > params.nAreaMax) {
            continue;
        }
        Moments mm = moments(contours[i], false);
        Point2f pnt = Point2f(mm.m10 / mm.m00, mm.m01 / mm.m00);//计算中心点
        ptCenter.push_back(pnt);
    }

获取手眼坐标变换系数:

    Mat warpMat = estimateAffine2D(points_camera, points_robot);//仿射变换
    double rms = 0;
    if (warpMat.cols == 3 && warpMat.rows == 2)
    {
        double A = warpMat.ptr<double>(0)[0];
        double B = warpMat.ptr<double>(0)[1];
        double C = warpMat.ptr<double>(0)[2];
        double D = warpMat.ptr<double>(1)[0];
        double E = warpMat.ptr<double>(1)[1];
        double F = warpMat.ptr<double>(1)[2];
        /*****************************************************RMS误差***********************************************/
        double sumX = 0, sumY = 0;
        for (int i = 0; i < 9; i++)
        {
            Point2f pt;
            pt.x = A * points_camera[i].x + B * points_camera[i].y + C;
            pt.y = D * points_camera[i].x + E * points_camera[i].y + F;
            sumX += pow(points_robot[i].x - pt.x, 2);
            sumY += pow(points_robot[i].y - pt.y, 2);
        }
        rms = sqrt(sumX / 9) + sqrt(sumY / 9);
    }
    for (int k = 0; k < 3; k++)
    {
        for (int i = 0; i < 9; i++)
        {
            /**********************************************对X操作**********************************************************/
            points_robot[i].x += 0.01;
            double curr = RMS_Add(points_camera, points_robot);
            if (curr < rms)
            {
                while (curr < rms)
                {
                    points_robot[i].x += 0.01;
                    rms = curr;
                    curr = RMS_Add(points_camera, points_robot);
                }
                points_robot[i].x -= 0.01;
            }
            else
            {
                points_robot[i].x -= 0.02;
                curr = RMS_Add(points_camera, points_robot);
                while (curr < rms)
                {
                    points_robot[i].x -= 0.01;
                    rms = curr;
                    curr = RMS_Add(points_camera, points_robot);
                }
                points_robot[i].x += 0.01;
            }
            /**********************************************对Y操作**********************************************************/
            points_robot[i].y += 0.01;
            curr = RMS_Add(points_camera, points_robot);
            if (curr < rms)
            {
                while (curr < rms)
                {
                    points_robot[i].y += 0.01;
                    rms = curr;
                    curr = RMS_Add(points_camera, points_robot);
                }
                points_robot[i].y -= 0.01;
            }
            else
            {
                points_robot[i].y -= 0.02;
                curr = RMS_Add(points_camera, points_robot);
                while (curr < rms)
                {
                    points_robot[i].y -= 0.01;
                    rms = curr;
                    curr = RMS_Add(points_camera, points_robot);
                }
                points_robot[i].y += 0.01;
            }
        }
    }
    Mat warp = estimateAffine2D(points_camera, points_robot);//仿射变换
    return warp;

最后,图像上得坐标转变为机械坐标:

ptR.x = _stCalibrateParams.A * ptI.x + _stCalibrateParams.B * ptI.y + _stCalibrateParams.C;
    ptR.y = _stCalibrateParams.D * ptI.x + _stCalibrateParams.E * ptI.y + _stCalibrateParams.F;

代码连接:https://download.csdn.net/download/weixin_42789529/88441518

推荐一个好用课堂管理小程序,欢迎扫码使用:
在这里插入图片描述

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: OpenCV中的9点标定算法是一种用于计算相机的内外参数的方法。它根据相机的一组已知的图像点和相应的物理世界点,通过构建相机的投影矩阵来计算相机的内参矩阵和外参矩阵。以下是该算法的步骤: 1. 收集一组至少9个已知的图像点和相应的物理世界点。这些图像点和物理世界点之间应该具有已知的对应关系。 2. 根据收集到的图像点和物理世界点,使用cv2.findHomography()函数计算单应性矩阵。单应性矩阵可以将物理世界点映射到图像坐标系。 3. 将单应性矩阵分解为相机的旋转矩阵和平移矩阵。根据这两个矩阵可以计算相机的外参矩阵。 4. 使用cv2.calibrateCamera函数计算相机的内参矩阵、畸变系数和旋转平移矩阵。该函数将输入所有的图像点和物理世界点,并根据9点标定算法进行计算。 5. 根据计算得到的内外参数,可以进行相机校正和图像修正等操作。 9点标定算法通过使用最小二乘法来最小化图像点和重投影点之间的误差,从而得到最佳的相机参数估计。该算法在相机标定中广泛应用,可以用于计算相机的焦距、主点和畸变系数等重要参数,为计算机视觉应用提供支持。 ### 回答2: OpenCV 9点标定算法是一种计算机视觉中常用的摄像机标定方法,用于确定摄像机的内外参数。该算法基于摄像机的几何特性和投影原理,通过将物体上的9个已知的二维点与其对应的三维点进行匹配,求解摄像机的内外参数矩阵。 具体步骤如下: 1. 收集标定棋盘图像。在不同的角度和位置下,拍摄多张包含标定棋盘的图像。 2. 检测角点。使用OpenCV提供的角点检测算法,找到每张图像中标定棋盘上的角点。 3. 提取角点。将每张图像中检测到的角点坐标保存下来,与标定棋盘上真实的三维坐标进行对应。 4. 根据已知的内外参数,计算像平面到物体平面的投影矩阵。 5. 使用求解器进行标定。将所有图像中的像素坐标与物体平面上的三维坐标进行匹配,使用OpenCV的求解器对内外参数矩阵进行求解。 6. 评估标定结果。使用重投影误差等指标评估标定结果的准确性。 7. 保存标定结果。将求解得到的摄像机内外参数矩阵保存下来,以备后续使用。 总的来说,OpenCV 9点标定算法通过收集多个不同角度和位置下的标定图像,找到图像中的角点,并与真实的三维坐标进行对应,最终通过求解器计算出摄像机的内外参数矩阵,用于后续的图像处理、目标检测等计算机视觉任务。 ### 回答3: OpenCV中的9点标定算法是用于相机姿态估计和相机校正的一种方法。该算法使用了至少9个已知空间点和它们在图像中的对应点来计算相机的内参矩阵和外参矩阵。 首先,我们需要准备一个已知的3D棋盘格形状,并将其固定在一个平面上。然后,我们需要采集不同位置和角度下棋盘格在图像中的对应点。为了增加精度,我们最好采集至少10个不同角度下的图像。 接下来,我们将使用OpenCV的`findChessboardCorners`函数来检测图像中的棋盘格角点,并使用`cornerSubPix`函数进行子像素精确化。然后,我们使用`calibrateCamera`函数来计算摄像机的内参矩阵和畸变系数。 最后,我们使用`solvePnP`函数来计算相机在3D空间中的姿态。这个函数将根据9个或更多的已知3D点和它们在图像中的对应点,计算相机的旋转向量和平移向量。 使用这些计算得到的内参矩阵和外参矩阵,我们可以校正畸变图像,获得准确的图像尺寸和坐标。此外,我们还可以使用相机的外参矩阵来估计相机在三维空间中的位置和朝向。 总的来说,OpenCV的9点标定算法是一种常用的相机校正和姿态估计方法,可以用于计算相机的内参矩阵和外参矩阵,以及校正畸变图像并估计相机在三维空间中的位置和姿态。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值