栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

视觉培训8 OpenCV相机标定

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

视觉培训8 OpenCV相机标定

基于OpenCV的相机标定

目录

任务

相机标定的目标

查找棋盘的2D坐标

查找棋盘角点

优化棋盘角点

校准相机

采集图片

标定图片


任务

标定一个相机,标定完后使用cv::undistort方法去除相机的畸变。

相机标定的目标

输入:具有已知二维图像坐标和三维世界坐标的点的图像集合。

输出:3×3相机内参矩阵,每幅图像的旋转和平移。

查找棋盘的2D坐标

查找棋盘角点

OpenCV中的findChessboardCorners内置函数

bool findChessboardCorners(InputArray image, Size patternSize, OutputArray corners, int flags = CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE )

参数:

        image: 8位灰度或彩色图像

        pattenSize: 每个棋盘行和列的内角点数( patternSize = cvSize (points_per_row, points_per_colum) = cvSize(columns,rows))

        corners: 检测到的角点的输出数组

        flags: 各种操作标志

输出:

        是否检测到角点

优化棋盘角点

cornersubix函数

void cornerSubPix(InputArray image, InputOutputArray corners, Size winSize, Size zeroZone, TermCriteria criteria)

参数:

        image: 输入图像

        corners: 输入角的初始坐标和为输出提供的精确坐标

        WinSize: 搜索窗口边长的一半

        zeroZone: 搜索区域中间零区大小的一半,在该零区上不进行下式求和。它有时用于避免自相关矩阵的可能奇点。(-1,-1)的值表示没有这样的大小

        criteria: 角点精化迭代过程的终止准则。也就是说,在criteria.maxCount迭代之后或在某些迭代中角位置移动小于criteria.epsilon时,角位置求精过程停止

校准相机

calibrateCamera函数

double calibrateCamera(InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints, Size imageSize, InputOutputArray cameraMatrix, InputOutputArray distCoeffs, OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs)

参数:

        objectPoints: 三维图像点的矢量

        imagePoints: 二维图像点的矢量

        imageSize: 图像大小

        cameraMatrix: 内参矩阵

        distCoeffs: 透镜畸变系数

        rvecs: 用于表达旋转的3×1矢量。矢量的方向指定旋转轴,矢量的大小指定旋转角度

        tvecs: 用于表达位移的3×1矢量,与rvecs类似

采集图片

这里我用平板来当棋盘

#include "opencv2/opencv.hpp"
#include 
#include 

using namespace cv;
using namespace std;

int main()
{
    VideoCapture inputVideo(0);
    if (!inputVideo.isOpened())
    {
        cout << "Could not open the input video " << endl;
        return -1;
    }
    Mat frame;
    string imgname;
    int f = 1;
    while (1)
    {
        inputVideo >> frame;
        if (frame.empty()) break;
        imshow("Camera", frame);
        char key = waitKey(1);
        if (key == 'c' || key == 'C')break; //按c结束
        if (key == 'q' || key == 'Q') //按q截取图片
        {
            imgname = to_string(f++) + ".jpg"; //以数字.jpg的格式保存图片
            imwrite(imgname, frame);
        }
    }
    cout << "Finished writing" << endl;
    return 0;
}

浅浅地拍了几张

 大概就是这样hhh

标定图片
#include 
#include 
#include 

using namespace std;
using namespace cv;

// 定义棋盘格的尺寸
int CHECKERBOARD[2]{7, 10};

int main()
{
    // 创建矢量以存储每个棋盘图像的三维点矢量
    std::vector> objpoints;

    // 创建矢量以存储每个棋盘图像的二维点矢量
    std::vector> imgpoints;

    // 为三维点定义世界坐标系
    std::vector objp;
    for (int i{0}; i < CHECKERBOARD[1]; i++)
    {
        for (int j{0}; j < CHECKERBOARD[0]; j++)
        {
            objp.push_back(cv::Point3f(j, i, 0));
        }
    }

    // 提取存储在给定目录中的单个图像的路径
    std::vector images;

    // 包含棋盘图像的文件夹的路径
    std::string path = "C:/Users/86139/Documents/OpenCV/build/Debug/*.jpg";

    // 使用glob函数读取所有图像的路径
    cv::glob(path, images);

    cv::Mat frame, gray;

    // 存储检测到的棋盘转角像素坐标的矢量
    std::vector corner_pts;
    bool success;

    // 循环读取图像
    for (int i{0}; i < images.size(); i++)
    {
        frame = cv::imread(images[i]);
        if (frame.empty())
        {
            continue;
        }
        if (i == 40)
        {
            int b = 1;
        }
        cout << "the current image is " << i << "th" << endl;
        cv::cvtColor(frame, gray, cv::COLOR_BGR2GRAY);

        // 寻找角点
        // 如果在图像中找到所需数量的角,则success = true
        success = cv::findChessboardCorners(gray, cv::Size(CHECKERBOARD[0], CHECKERBOARD[1]), corner_pts, CALIB_CB_ADAPTIVE_THRESH | CALIB_CB_FAST_CHECK | CALIB_CB_NORMALIZE_IMAGE);

        // 如果检测到所需数量的角点,我们将细化像素坐标并将其显示在棋盘图像上
        if (success)
        {
            cv::TermCriteria criteria(TermCriteria::EPS | TermCriteria::Type::MAX_ITER, 30, 0.001);

            // 为给定的二维点细化像素坐标
            cv::cornerSubPix(gray, corner_pts, cv::Size(11, 11), cv::Size(-1, -1), criteria);

            // 在棋盘上显示检测到的角点
            cv::drawChessboardCorners(frame, cv::Size(CHECKERBOARD[0], CHECKERBOARD[1]), corner_pts, success);

            objpoints.push_back(objp);
            imgpoints.push_back(corner_pts);
        }
    }

    cv::destroyAllWindows();

    cv::Mat cameraMatrix, distCoeffs, R, T;

    // 通过传递已知3D点(objpoints)的值和检测到的角点(imgpoints)的相应像素坐标来执行相机校准
    cv::calibrateCamera(objpoints, imgpoints, cv::Size(gray.rows, gray.cols), cameraMatrix, distCoeffs, R, T);

    // 内参矩阵
    std::cout << "cameraMatrix : " << cameraMatrix << std::endl;
    // 透镜畸变系数
    std::cout << "distCoeffs : " << distCoeffs << std::endl;
    // rvecs
    std::cout << "Rotation vector : " << R << std::endl;
    // tvecs
    std::cout << "Translation vector : " << T << std::endl;

    // 当摄像头打开时,实时矫正图片,并实时输出;
    VideoCapture capture(0);
    Mat original, undistorted;

    while(capture.isOpened()){
        capture >> original;
        undistort(original, undistorted, cameraMatrix,distCoeffs);
        imshow("original", original);
        waitKey(30);
        imshow("undistorted", undistorted);
        waitKey(30);
    }

    return 0;
}

因为电脑的摄像头质量太好了其实根本不需要矫正,导致图像差不多

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1034004.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号