opencvC++学习22像素重映射(cv::remap)

什么是像素重映射

简单点说就是把输入图像中各个像素按照一定的规则映射到另外一张图像的对应位置上去,形成一张新的图像。


API:

Remap(
InputArray src,// 输入图像
OutputArray dst,// 输出图像
InputArray  map1,// x 映射表 CV_32FC1/CV_32FC2
InputArray map2,// y 映射表
int interpolation,// 选择的插值方法,常见线性插值,可选择立方等
int borderMode,// BORDER_CONSTANT
const Scalar borderValue// color 

)

代码:

#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;

Mat src, dst, map_x, map_y;
const char* OUTPUT_TITLE = "remap demo";
int index = 0;
void update_map(void);

int main()
{
    src = imread("D:/opencvSRC/test.jpg");
    if (!src.data) {
        printf("could not load image...\n");
        return -1;
    }
    char input_win[] = "input image";
    namedWindow(input_win, CV_WINDOW_AUTOSIZE);
    namedWindow(OUTPUT_TITLE, CV_WINDOW_AUTOSIZE);
    imshow(input_win, src);

    map_x.create(src.size(), CV_32FC1);
    map_y.create(src.size(), CV_32FC1);

    int c = 0;
    while (true) {
        c = waitKey(500);
        printf("c == %d\n", c);
        if ((char)c == 27) {
            break;
        }
        index = c % 4;
        update_map();
        remap(src, dst, map_x, map_y, INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 255, 255));
        imshow(OUTPUT_TITLE, dst);
    }

    waitKey(0);

    return 0;
}

void update_map(void)
{
    for (int row = 0; row < src.rows; row++) {
        for (int col = 0; col < src.cols; col++) {
            switch (index) {
            case 0:
                if (col > (src.cols * 0.25) && col <= (src.cols*0.75) && row > (src.rows*0.25) && row <= (src.rows*0.75)) {
                    map_x.at<float>(row, col) = 2 * (col - (src.cols*0.25));
                    map_y.at<float>(row, col) = 2 * (row - (src.rows*0.25));
                }
                else {
                    map_x.at<float>(row, col) = 0;
                    map_y.at<float>(row, col) = 0;
                }
                break;
            case 1:
                map_x.at<float>(row, col) = (src.cols - col - 1);
                map_y.at<float>(row, col) = row;
                break;
            case 2:
                map_x.at<float>(row, col) = col;
                map_y.at<float>(row, col) = (src.rows - row - 1);
                break;
            case 3:
                map_x.at<float>(row, col) = (src.cols - col - 1);
                map_y.at<float>(row, col) = (src.rows - row - 1);
                break;
            }

        }
    }
}

效果:


对于使用四个摄像头进行标定和去畸变,您可以按照以下步骤进行操作: 1. 拍摄标定图像:使用每个摄像头拍摄至少10张不同角度和位置的棋盘格标定图像,并将这些图像保存在单独的文件夹中。 2. 标定:使用 OpenCV 的 `calibrateCamera()` 函数对每个摄像头进行单独标定。该函数将返回相机矩阵、畸变系数和旋转/平移向量,这些值将用于去畸变。 3. 合并标定结果:使用 `stereoCalibrate()` 函数将每个摄像头的相机矩阵和畸变系数合并为一个矩阵和系数。 4. 去畸变:使用 `initUndistortRectifyMap()` 和 `remap()` 函数将图像去畸变。这两个函数将使用相机矩阵、畸变系数和旋转/平移向量来计算一个畸变矫正映射,然后将该映射应用于输入图像。 以下是示例代码,其中 `calibrateCamera()` 和 `stereoCalibrate()` 函数的参数会根据您的实际情况进行调整: ```cpp // 定义标定图像的大小 Size boardSize = Size(9, 6); // 定义棋盘格的大小 float squareSize = 0.025; // 单位为米 // 定义标定图像的路径 vector<string> imagePaths1 = {"path/to/camera1/images"}; vector<string> imagePaths2 = {"path/to/camera2/images"}; vector<string> imagePaths3 = {"path/to/camera3/images"}; vector<string> imagePaths4 = {"path/to/camera4/images"}; // 定义标定图像的数量 int imageCount = 10; // 定义标定参数 vector<vector<Point3f>> objectPoints; vector<vector<Point2f>> imagePoints1, imagePoints2, imagePoints3, imagePoints4; Mat cameraMatrix1, cameraMatrix2, cameraMatrix3, cameraMatrix4, distCoeffs1, distCoeffs2, distCoeffs3, distCoeffs4; vector<Mat> rvecs1, tvecs1, rvecs2, tvecs2, rvecs3, tvecs3, rvecs4, tvecs4; // 对每个摄像头进行单独标定 for (int i = 0; i < imageCount; i++) { // 读取标定图像 Mat image1 = imread(imagePaths1[i]); Mat image2 = imread(imagePaths2[i]); Mat image3 = imread(imagePaths3[i]); Mat image4 = imread(imagePaths4[i]); // 检测棋盘格角点 vector<Point2f> corners1, corners2, corners3, corners4; bool found1 = findChessboardCorners(image1, boardSize, corners1); bool found2 = findChessboardCorners(image2, boardSize, corners2); bool found3 = findChessboardCorners(image3, boardSize, corners3); bool found4 = findChessboardCorners(image4, boardSize, corners4); if (found1 && found2 && found3 && found4) { // 亚像素精度角点检测 cornerSubPix(image1, corners1, Size(11, 11), Size(-1, -1), TermCriteria(TermCriteria::EPS + TermCriteria::MAX_ITER, 30, 0.1)); cornerSubPix(image2, corners2, Size(11, 11), Size(-1, -1), TermCriteria(TermCriteria::EPS + TermCriteria::MAX_ITER, 30, 0.1)); cornerSubPix(image3, corners3, Size(11, 11), Size(-1, -1), TermCriteria(TermCriteria::EPS + TermCriteria::MAX_ITER, 30, 0.1)); cornerSubPix(image4, corners4, Size(11, 11), Size(-1, -1), TermCriteria(TermCriteria::EPS + TermCriteria::MAX_ITER, 30, 0.1)); // 保存角点坐标 vector<Point3f> objectCorners; for (int j = 0; j < boardSize.height; j++) { for (int k = 0; k < boardSize.width; k++) { objectCorners.push_back(Point3f(j * squareSize, k * squareSize, 0)); } } objectPoints.push_back(objectCorners); imagePoints1.push_back(corners1); imagePoints2.push_back(corners2); imagePoints3.push_back(corners3); imagePoints4.push_back(corners4); } } // 对每个摄像头进行单独标定 calibrateCamera(objectPoints, imagePoints1, imagePaths1[0].size(), cameraMatrix1, distCoeffs1, rvecs1, tvecs1); calibrateCamera(objectPoints, imagePoints2, imagePaths2[0].size(), cameraMatrix2, distCoeffs2, rvecs2, tvecs2); calibrateCamera(objectPoints, imagePoints3, imagePaths3[0].size(), cameraMatrix3, distCoeffs3, rvecs3, tvecs3); calibrateCamera(objectPoints, imagePoints4, imagePaths4[0].size(), cameraMatrix4, distCoeffs4, rvecs4, tvecs4); // 合并标定结果 vector<vector<Point3f>> objectPointsAll(imagePoints1.size(), objectPoints[0]); Mat R, T, E, F; stereoCalibrate(objectPointsAll, imagePoints1, imagePoints2, cameraMatrix1, distCoeffs1, cameraMatrix2, distCoeffs2, imagePaths1[0].size(), R, T, E, F); // 保存相机参数 FileStorage fs("calibration.xml", FileStorage::WRITE); fs << "cameraMatrix1" << cameraMatrix1; fs << "distCoeffs1" << distCoeffs1; fs << "cameraMatrix2" << cameraMatrix2; fs << "distCoeffs2" << distCoeffs2; fs << "cameraMatrix3" << cameraMatrix3; fs << "distCoeffs3" << distCoeffs3; fs << "cameraMatrix4" << cameraMatrix4; fs << "distCoeffs4" << distCoeffs4; fs << "R" << R; fs << "T" << T; fs.release(); // 加载相机参数 FileStorage fs("calibration.xml", FileStorage::READ); fs["cameraMatrix1"] >> cameraMatrix1; fs["distCoeffs1"] >> distCoeffs1; fs["cameraMatrix2"] >> cameraMatrix2; fs["distCoeffs2"] >> distCoeffs2; fs["cameraMatrix3"] >> cameraMatrix3; fs["distCoeffs3"] >> distCoeffs3; fs["cameraMatrix4"] >> cameraMatrix4; fs["distCoeffs4"] >> distCoeffs4; fs["R"] >> R; fs["T"] >> T; fs.release(); // 初始化畸变矫正映射 Mat map1x, map1y, map2x, map2y, map3x, map3y, map4x, map4y; initUndistortRectifyMap(cameraMatrix1, distCoeffs1, R, cameraMatrix1, imagePaths1[0].size(), CV_32FC1, map1x, map1y); initUndistortRectifyMap(cameraMatrix2, distCoeffs2, R, cameraMatrix2, imagePaths2[0].size(), CV_32FC1, map2x, map2y); initUndistortRectifyMap(cameraMatrix3, distCoeffs3, R, cameraMatrix3, imagePaths3[0].size(), CV_32FC1, map3x, map3y); initUndistortRectifyMap(cameraMatrix4, distCoeffs4, R, cameraMatrix4, imagePaths4[0].size(), CV_32FC1, map4x, map4y); // 去畸变 Mat image1 = imread("path/to/image1"); Mat image2 = imread("path/to/image2"); Mat image3 = imread("path/to/image3"); Mat image4 = imread("path/to/image4"); Mat undistorted1, undistorted2, undistorted3, undistorted4; remap(image1, undistorted1, map1x, map1y, INTER_LINEAR); remap(image2, undistorted2, map2x, map2y, INTER_LINEAR); remap(image3, undistorted3, map3x, map3y, INTER_LINEAR); remap(image4, undistorted4, map4x, map4y, INTER_LINEAR); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值