OpenCV开发笔记(八十一):通过棋盘格使用鱼眼方式标定相机内参矩阵矫正摄像头图像

时间:2024-10-25 10:54:49

前言

  对于广角摄像头通过相机图片可以识别出棋盘角点计算相机内参矩阵,通过畸变校准可以得到较好的效果,但是鱼眼摄像头通过这种方式获得周围四周的图像效果并不是很好。所以,鱼眼摄像头在校准上与普通摄像头有一些区别。
  本篇通过一张图片来识别计算得到相机内参矩阵,并鱼眼矫正的方式矫正图像畸形。

 

Demo

  鱼眼方式畸变校准效果
  在这里插入图片描述
  普通畸变校准效果
  在这里插入图片描述

 

校准实例

  注意:这里demo只使用了可识别的两张基本相似的棋盘图作为计算,鱼眼畸变矫正,若是区别大,那么校准的时候会因为计算误差超限而奔溃。

步骤一:初始化图片列表

  

QStringList list;
list.append("D:/qtProject/openCVDemo/openCVDemo/modules/openCVManager/images/34.png");
list.append("D:/qtProject/openCVDemo/openCVDemo/modules/openCVManager/images/35.png");
int chessboardColCornerCount = 8;
int chessboardRowCornerCount = 11;

步骤二:循环识别图片棋盘格并且将其世界坐标和识别的角点放入列表

  
  

std::vector<std::vector<cv::Point3f>> vectorObjectPoint;
std::vector<std::vector<cv::Point2f>> vectorImagePoint;
cv::Mat grayMat;
cv::Mat srcMat;
for(int n = 0; n < list.size(); n++)
{
    QString str = list.at(n);
    std::string srcFilePath = str.toStdString();
    // 步骤一:读取文件
    cv::Mat mat = cv::imread(srcFilePath);
    LOG << mat.cols << mat.rows;
#if 1
    srcMat = cv::Mat(mat.rows * 2, mat.cols * 2, CV_8UC3);
    cv::Mat matRoi = srcMat(cv::Rect(mat.cols / 2, mat.rows / 2, mat.cols, mat.rows));
    cv::addWeighted(mat, 1.0f, matRoi, 0, 0, matRoi);
#else
    srcMat = mat.clone();
#endif
    // 步骤二:缩放,太大了缩放下(可省略)
    cv::resize(srcMat, srcMat, cv::Size(srcMat.cols / 2, srcMat.rows / 2));
    cv::Mat srcMat2 = srcMat.clone();
    cv::Mat srcMat3 = srcMat.clone();
    // 步骤三:灰度化
    cv::cvtColor(srcMat, grayMat, cv::COLOR_BGR2GRAY);
    cv::imshow("grayMat", grayMat);
    // 步骤四:检测角点
    std::vector<cv::Point2f> vectorPoint2fCorners;
    bool patternWasFound = false;
    patternWasFound = cv::findChessboardCorners(grayMat,
                                             cv::Size(chessboardColCornerCount,
                                                    chessboardRowCornerCount),
                                             vectorPoint2fCorners,
                                             cv::CALIB_CB_ADAPTIVE_THRESH |
                                             cv::CALIB_CB_FAST_CHECK |
                                             cv::CALIB_CB_NORMALIZE_IMAGE);
    if(!patternWasFound)
    {
        LOG << "not find ChessboardCorners:" << chessboardColCornerCount << chessboardRowCornerCount;
        continue;
    }
    /*
    enum { CALIB_CB_ADAPTIVE_THRESH = 1,    // 使用自适应阈值将图像转化成二值图像
          CALIB_CB_NORMALIZE_IMAGE = 2,    // 归一化图像灰度系数(用直方图均衡化或者自适应阈值)
          CALIB_CB_FILTER_QUADS    = 4,    // 在轮廓提取阶段,使用附加条件排除错误的假设
          CALIB_CB_FAST_CHECK      = 8     // 快速检测
         };
    */
    cvui::printf(srcMat, 0, 0, 1.0, 0xFF0000, "found = %s", patternWasFound ? "true" : "false");
    cvui::printf(srcMat, 0, 24