IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> 标定相机函数演示 -> 正文阅读

[人工智能]标定相机函数演示

calibrateCamera函数的实际用法

????标定相机参数之前,要拍10张以上标定板图片并成功提取标定板中的角点之后才可以进行标定相机的内外参数

????代码如下

//计算标定数据
void QGuiCalib3d::btnCalcCalibData_clicked()
{
  int ImgTotal = m_vcImagePointsSeq.size();
  if (ImgTotal < 11)
  {
    QMessageBox msgBox;
    msgBox.setText("图片数量不够12张");
    msgBox.setIcon(QMessageBox::Warning);
    msgBox.setWindowIcon(QIcon(":/OpenCVTestSf/ico/opencv-logo.ico"));
    msgBox.exec();
    return;
  }
  m_boardSize.width = ui.lineEditBoardCol->text().toInt();
  m_boardSize.height = ui.lineEditBoardRow->text().toInt();
  m_squareSize.width = ui.lineEditSquareWidth->text().toInt();
  m_squareSize.height = ui.lineEditSquareHeight->text().toInt();
  //在指定的文件夹中写入到指定的文件
  QString qsFilepath = QCoreApplication::applicationDirPath() + "/Calibration/";
  QDir* pFolder = new QDir;
  bool bExist = pFolder->exists(qsFilepath);//文件夹是否存在
  if (!bExist)
    pFolder->mkdir(qsFilepath);//创建文件夹
  QDateTime* datatime = new QDateTime(QDateTime::currentDateTime());
  QString strTime = datatime->toString("yyyy_MM_dd hh_mm_ss ");
  string filepath = qsFilepath.toStdString();
  string fileTime = strTime.toStdString();
  string filexmlname = "CalibrationCalibData.yaml";
  string fileName = filepath + fileTime + filexmlname;
  FileStorage fwriteCalibData(fileName, FileStorage::WRITE);//以写入的模式打开文件
  vector<vector<Point3f>> objectPoints;
  int i, j, t;
  for (t = 0; t < ImgTotal; t++)
  {
    vector<Point3f> tempPointSet;
    for (i = 0; i < m_boardSize.height; i++)
    {
      for (j = 0; j < m_boardSize.width; j++)
      {
        Point3f realPoint;
        // 假设标定板放在世界坐标系中z=0的平面上
        realPoint.x = (float)i * m_squareSize.width;
        realPoint.y = (float)j * m_squareSize.height;
        realPoint.z = 0;
        tempPointSet.push_back(realPoint);
      }
    }
    objectPoints.push_back(tempPointSet);//每张标定板图的所有坐标
  }

  fwriteCalibData << "worldPoints"
    << "{"
    << "objectPoints" << objectPoints
    << "}";
  vector<Mat> vcRotateMat;// 每幅图像的旋转向量 
  vector<Mat> vcMoveMat;// 每幅图像的平移向量 
  try
  {
    /*开始标定 返回值是重投影的总的均方根误差*/
    double res = calibrateCamera(
      objectPoints,//世界坐标系中的三维点
      m_vcImagePointsSeq,//为每一个内角点对应的图像坐标点
      m_imageSize,//为图像的像素尺寸大小,在计算相机的内参和畸变矩阵时需要使用到该参数
      m_cameraMatrix,//为相机的内参矩阵
      m_distCoeffs,//为畸变矩阵
      vcRotateMat,//为旋转向量
      vcMoveMat,//为位移向量
      0);//为标定时所采用的算法
  }
  catch (cv::Exception& e)
  {
    const char* err_msg = e.what();
    QMessageBox msgBox;
    msgBox.setText(err_msg);
    msgBox.setIcon(QMessageBox::Warning);
    msgBox.setWindowIcon(QIcon(":/OpenCVTestSf/ico/opencv-logo.ico"));
    msgBox.exec();
    return;
  }

  // 每幅图像中角点的数量  
  vector<int> pointCounts;
  for (i = 0; i < ImgTotal; i++)
  {
    // 初始化每幅图像中的角点数量,假定每幅图像中都可以看到完整的标定板
    pointCounts.push_back(m_boardSize.width * m_boardSize.height);
    fwriteCalibData << "pointCounts"
      << "{"
      << "num" << i 
      << "count" << m_boardSize
      << "point" << objectPoints[i]
      << "RotateMat" << vcRotateMat[i]
      << "MoveMat" << vcMoveMat[i]
      << "}";
  }

  double totalErr = 0.0; // 所有图像的平均误差的总和 
  for (i = 0; i < ImgTotal; i++)
  {
    // 保存重新计算得到的投影点
    vector<Point2f> newPoints; 
    //对空间的三维点进行重新投影计算,得到新的投影点 
    projectPoints(
      objectPoints[i],    //世界坐标系中的三维点
      vcRotateMat[i],      //旋转向量
      vcMoveMat[i],      //平移向量
      m_cameraMatrix,      //相机内参
      m_distCoeffs,      //相机外参
      newPoints);      //计算出的新的投影点
    // 计算新的投影点和旧的投影点之间的误差
    Mat tempImagePointMat = Mat(1, m_vcImagePointsSeq[i].size(), CV_32FC2);
    Mat imagePoints2Mat = Mat(1, newPoints.size(), CV_32FC2);
    for (int j = 0; j < (int)m_vcImagePointsSeq[i].size(); j++)
    {
      float fx = newPoints[j].x;
      float fy = newPoints[j].y;
      imagePoints2Mat.at<Vec2f>(0, j) = Vec2f(fx, fy);
      float imgx = m_vcImagePointsSeq[i][j].x;
      float imgy = m_vcImagePointsSeq[i][j].y;
      tempImagePointMat.at<Vec2f>(0, j) = Vec2f(imgx, imgy);
    }    
    double err = norm(imagePoints2Mat, tempImagePointMat, NORM_L2);// 每幅图像的平均误差
    double err1 = err / pointCounts[i];
    totalErr += err1;
    fwriteCalibData << "imgpoints"
      << "{"
      << "imgnum" << i
      << "newx" << newPoints
      << "oldx" << m_vcImagePointsSeq[i]
      << "normerr" << err
      << "err" << err1
      << "totalerr" << totalErr
      << "}";
  }
  double rAverErr = totalErr / ImgTotal;
  fwriteCalibData << "AverErr" << rAverErr;
  QString szText1;
  szText1.sprintf("标定平均误差 %.3f \n", rAverErr);
  vector<double> vcCamera;
  vcCamera.clear();
  vector<double> vcCoeff;
  vcCoeff.clear();
  //获得的内参参数
  QString szText2 = "内参参数:\n";
  for (int i = 0; i < m_cameraMatrix.rows; i++)
  {
    for (int j = 0; j < m_cameraMatrix.cols; j++)
    {
      double value = m_cameraMatrix.at<double>(i, j);
      QString temp = QString("%1  ").arg(value);
      szText2.append(temp);
      vcCamera.push_back(value);
    }
    szText2.append("\n");
  }
  //畸变系数
  QString szText3 = "畸变系数:\n";
  for (int i = 0; i < m_distCoeffs.rows; i++)
  {
    fwriteCalibData << "i" << i;
    for (int j = 0; j < m_distCoeffs.cols; j++)
    {
      double value = m_distCoeffs.at<double>(i, j);
      QString temp = QString("%1  ").arg(value);
      szText3.append(temp);
      vcCoeff.push_back(value);
    }
    szText3.append("\n");
  }
  //保存每幅图像的旋转矩阵
  vector<Mat> rotationMatrix;
  rotationMatrix.clear();
  for (int i = 0; i < ImgTotal; i++)
  {
    Mat matric = Mat(3, 3, CV_32FC1, Scalar::all(0));
    rotationMatrix.push_back(matric);
  }
  for (int i = 0; i < ImgTotal; i++)
  {
    // 将旋转向量转换为相对应的旋转矩阵
    Rodrigues(vcRotateMat[i], rotationMatrix[i]);
  }
  fwriteCalibData << "cameraData"
    << "{"
    << "cameraMatrix" << m_cameraMatrix
    << "distCoeffs" << m_distCoeffs
    << "vcRotateMat" << vcRotateMat
    << "rotationMatrix" << rotationMatrix
    << "}";
  fwriteCalibData.release();//关闭文件
  QString readStr;
  readStr.append(szText1);
  readStr.append(szText2);
  readStr.append(szText3);
  ui.textBrowser->clear();
  ui.textBrowser->setText(readStr);
}

我这里取的是不低于11张标定板图片的角点数据

图片

图片

欢迎关注公众号《Qt学视觉》?

?

?

  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2022-01-08 14:00:00  更:2022-01-08 14:00:32 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 22:39:42-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码