OpenCV calibrateCamera () возвращает слишком высокую ошибку перепроецирования (C ++) - PullRequest
1 голос
/ 28 мая 2020

Я пытался откалибровать камеру Iphone 11 Pro, и функция openCV calibrateCamera () возвращает ошибку более 1,2+ (то же самое для computeReprojectionErrors () ниже). Я хочу, чтобы они были ниже 0,5, потому что после этого я делаю карту несоответствия, и мне нужно, чтобы она была плавной. Как его минимизировать? Вот мой код, и я сделал 90 изображений платы под разными углами, которые хранятся в ../chess_image. Вот код: github.com/markilebyak/opencv.git

Также здесь: 4shared.com/folder/PSDaeTcI/opencv.html это 36 изображений из тех 90, которые я использовал, и 34 в оттенках серого с обнаружил строки из тех 36.

void createKnownBoardPosition(Size &boardSize, float squareEdgeLength, vector<Point3f>& corners) {
    for (int i = 0; i < boardSize.height; i++) {
        for (int j = 0; j < boardSize.width; j++) {
            corners.emplace_back((float)j * squareEdgeLength, (float)i * squareEdgeLength, 0.0f);
        }
    }
}



void process_images(std::string &path_to_directory, Size &chessboard_size, vector<vector<Point2f>>& allFoundCorners) {
//    Function to iterate through images
//    taken for camera calibration
    vector<String> filenames;
    cv::glob(path_to_directory, filenames);
    vector<Point2f> pointBuffer;
    int counter = 0;
    for (const auto & filename : filenames) {
        if (filename != "../chess_images/.DS_Store"){
            Mat im = imread(filename);
            std::cout << filename << std::endl;
            Mat gray_im;
            cvtColor(im, gray_im, COLOR_BGR2GRAY);
            bool found = findChessboardCorners(gray_im, chessboard_size, pointBuffer,
                                               CALIB_CB_ADAPTIVE_THRESH | CALIB_CB_NORMALIZE_IMAGE);
            if (found) {
                counter++;
                TermCriteria criteria = TermCriteria( TermCriteria::EPS + TermCriteria::MAX_ITER,
                        30,0.0001 );
                Size winSize = Size( 11, 11);
                Size zeroZone = Size( -1, -1 );
                //cornerSubPix is the algorithm focused on relocating the points. it receives the image, the corners
                // a window size, zeroZone and the actual criteria. The window size is the search area.
                cornerSubPix(gray_im, pointBuffer, winSize, zeroZone, criteria );
                drawChessboardCorners( gray_im, chessboard_size, Mat(pointBuffer), found );
                string nametext = "../drawn_chessboard/" + to_string(counter) + ".jpg";
                imwrite(nametext, gray_im);
                allFoundCorners.push_back(pointBuffer);
            }
        }
    }
    std::cout << "Images used: " << counter << std::endl;
}


double computeReprojectionErrors( const vector<vector<Point3f> >& objectPoints,
                                         const vector<vector<Point2f> >& imagePoints,
                                         const vector<Mat>& rvecs, const vector<Mat>& tvecs,
                                         const Mat& cameraMatrix , const Mat& distCoeffs,
                                         vector<float>& perViewErrors, bool fisheye) {
    vector<Point2f> imagePoints2;
    size_t totalPoints = 0;
    double totalErr = 0, err;
    perViewErrors.resize(objectPoints.size());
    for(size_t i = 0; i < objectPoints.size(); ++i )
    {
        if (fisheye)
        {
            fisheye::projectPoints(objectPoints[i], imagePoints2, rvecs[i], tvecs[i], cameraMatrix,
                                   distCoeffs);
        }
        else
        {
            projectPoints(objectPoints[i], rvecs[i], tvecs[i], cameraMatrix, distCoeffs, imagePoints2);
        }
        err = norm(imagePoints[i], imagePoints2, NORM_L2);
        size_t n = objectPoints[i].size();
        perViewErrors[i] = (float) std::sqrt(err*err/n);
        totalErr        += err*err;
        totalPoints     += n;
    }
    return std::sqrt(totalErr/totalPoints);
}


void calibration_process(Size &boardSize, float &squareEdgeLength, Mat& cameraMatrix, Mat& distortionCoefficients,
                         std::string &path_to_directory) {

    vector<vector<Point2f>> checkerboardImageSpacePoints;
    process_images(path_to_directory, boardSize, checkerboardImageSpacePoints);

    vector<vector<Point3f>> worldSpaceCornerPoints(1);
    createKnownBoardPosition(boardSize, squareEdgeLength, worldSpaceCornerPoints[0]);
    worldSpaceCornerPoints.resize(checkerboardImageSpacePoints.size(), worldSpaceCornerPoints[0]);
    //rotation and translation vectors (rVectors, tVectors)
    vector<Mat> rVectors, tVectors;
    distortionCoefficients = Mat::zeros(8, 1, CV_64F);
    calibrateCamera(worldSpaceCornerPoints, checkerboardImageSpacePoints, boardSize, cameraMatrix,
                                 distortionCoefficients, rVectors, tVectors, CALIB_FIX_K5 + CALIB_FIX_INTRINSIC);
    vector<float> perViewErrors;
    double rep_error = computeReprojectionErrors(worldSpaceCornerPoints, checkerboardImageSpacePoints, rVectors, tVectors, cameraMatrix,
            distortionCoefficients, perViewErrors, false);
    std::cout << "Reprojection Error: " << rep_error << std::endl;
}


int main() {
    Mat cameraMatrix, distortionCoefficient;
    Size chessboardDimensions = Size(6, 9);
    float calibrationSquareDimension = 0.03f;
    std::string path = "../chess_images";
    calibration_process(chessboardDimensions, calibrationSquareDimension, cameraMatrix,
                        distortionCoefficient, path);
    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...