关于opencv&c++图片矫正后棋盘周围环境扭曲的现象的原因和解决方法

关于opencv&c++图片矫正后棋盘周围环境扭曲的现象的原因和解决方法。矫正了一张图片,棋盘格内无扭曲,周围环境出现扭曲。
原图:

img


矫正后

img

// CheckerBoardDemo.cpp : 定义控制台应用程序的入口点。
//

//#include 
#include 
#include
#include
using namespace cv;
using namespace std;

Mat image, img_gray;
int BOARDSIZE[2]{ 5,7 };//棋盘格每行每列角点个数
int main()
{
    vector> objpoints_img;//保存棋盘格上角点的三维坐标
    vector obj_world_pts;//三维世界坐标
    vector> images_points;//保存所有角点
    vector img_corner_points;//保存每张图检测到的角点
    vector<String> images_path;//创建容器存放读取图像路径

    string image_path = "E:\\vs\\相机标定\\*.jpg";//待处理图路径    F:/Works/C++/openCV/opencv study/Revise/Revise/Project1/
    glob(image_path, images_path);//读取指定文件夹下图像

    //转世界坐标系
    for (int i = 0; i < BOARDSIZE[1]; i++)
    {
        for (int j = 0; j < BOARDSIZE[0]; j++)
        {
            obj_world_pts.push_back(Point3f(j, i, 0));
        }
    }

    for (int i = 0; i < images_path.size(); i++)
    {
        image = imread(images_path[i]);
        cvtColor(image, img_gray, COLOR_BGR2GRAY);
        //检测角点
        bool found_success = findChessboardCorners(img_gray, Size(BOARDSIZE[0], BOARDSIZE[1]),
            img_corner_points,
            CALIB_CB_ADAPTIVE_THRESH | CALIB_CB_FAST_CHECK | CALIB_CB_NORMALIZE_IMAGE);

        //显示角点
        if (found_success)
        {
            //迭代终止条件
            TermCriteria criteria(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 30, 0.001);

            //进一步提取亚像素角点
            cornerSubPix(img_gray, img_corner_points, Size(11, 11),
                Size(-1, -1), criteria);

            //绘制角点
            drawChessboardCorners(image, Size(BOARDSIZE[0], BOARDSIZE[1]), img_corner_points,
                found_success);

            objpoints_img.push_back(obj_world_pts);//从世界坐标系到相机坐标系
            images_points.push_back(img_corner_points);
        }
        //char *output = "image";
        char text[] = "image";
        char* output = text;
        imshow(output, image);
        waitKey(200);

    }

    /*
    计算内参和畸变系数等
    */

    Mat cameraMatrix, distCoeffs, R, T;//内参矩阵,畸变系数,旋转量,偏移量
    calibrateCamera(objpoints_img, images_points, img_gray.size(),
        cameraMatrix, distCoeffs, R, T);

    cout << "cameraMatrix:" << endl;
    cout << cameraMatrix << endl;

    cout << "*****************************" << endl;
    cout << "distCoeffs:" << endl;
    cout << distCoeffs << endl;
    cout << "*****************************" << endl;

    cout << "Rotation vector:" << endl;
    cout << R << endl;

    cout << "*****************************" << endl;
    cout << "Translation vector:" << endl;
    cout << T << endl;


        Mat src, dst;
        src = imread("E:\\vs\\相机标定\\1.jpg");  //F:/Works/C++/openCV/opencv study/Revise/image/2.jpg
        undistort(src, dst, cameraMatrix, distCoeffs);

        char texts[] = "image_dst";
        char* dst_output = texts;
        //char *dst_output = "image_dst";
        namedWindow("out", CV_WINDOW_FREERATIO);
        imshow("out", dst);
        waitKey(0);
        //imwrite("F:/Works/C++/openCV/opencv study/Revise/image/3.jpg", dst);

        destroyAllWindows();//销毁显示窗口

        system("pause");
      
    
    return 0;
}


该回答引用GPTᴼᴾᴱᴺᴬᴵ
这个现象可能是因为棋盘周围的环境并不是完全平整的,而且在图像畸变校正之前并没有对其进行处理。这种情况下,校正后图像中的棋盘格会出现扭曲,因为在矫正时算法会假设环境是平整的。
-
要解决这个问题,可以在进行图像畸变校正之前,对图像进行透视变换,以使棋盘周围的环境看起来更加平整。透视变换可以通过寻找图像中的四个角点,并将它们映射到一个平面上来实现。在进行透视变换之后,可以再应用图像畸变校正算法来进一步提高校正的精度。
-
以下是示例代码,其中包括透视变换和图像畸变校正两个步骤:

// 透视变换
vector<Point2f> src_points, dst_points;
src_points.push_back(Point2f(0, 0)); // 左上角
src_points.push_back(Point2f(image.cols - 1, 0)); // 右上角
src_points.push_back(Point2f(0, image.rows - 1)); // 左下角
src_points.push_back(Point2f(image.cols - 1, image.rows - 1)); // 右下角
// 你需要调整的四个点的位置
dst_points.push_back(Point2f(0, 0));
dst_points.push_back(Point2f(image.cols - 1, 0));
dst_points.push_back(Point2f(0, image.rows - 1));
dst_points.push_back(Point2f(image.cols - 1, image.rows - 1));
Mat M = getPerspectiveTransform(src_points, dst_points);
Mat corrected_image;
warpPerspective(image, corrected_image, M, image.size());

// 图像畸变校正
Mat cameraMatrix, distCoeffs;
// 进行相机标定,并获得相机内参和畸变系数
calibrateCamera(objpoints_img, images_points, img_gray.size(),
    cameraMatrix, distCoeffs, R, T);
Mat undistorted_image;
undistort(corrected_image, undistorted_image, cameraMatrix, distCoeffs);

// 显示结果
imshow("Undistorted Image", undistorted_image);
waitKey();