Получение данных калибровки камеры

Поэтому мне нужна помощь с OpenCV в C++

По сути, у меня есть камера, которая имеет некоторые радиальные искажения, и я могу деисторировать ее, используя предоставленные примеры / образцы в OpenCV.

Но в настоящее время я должен калибровать камеру каждый раз, когда программа запускается. Но пример генерирует файл XML по правильной причине... Чтобы использовать эти значения...

Моя проблема в том, что я не уверен, какие значения и как использовать эти значения из файла XML, чтобы снять искажение камеры без необходимости повторной калибровки.

Я попытался найти примеры такого использования в Интернете, но по какой-то причине ничего не связалось с моей проблемой...

Предположительно, мы должны быть в состоянии взять значения из выходного XML-файла и использовать их непосредственно в программе, чтобы нам не приходилось каждый раз перекалибровать камеру.

Но в настоящее время это именно то, что делает моя программа:/

Я действительно надеюсь, что кто-то может помочь мне с этим

Большое спасибо:)

2 ответа

Решение

Хорошо, поэтому я смог извлечь 4 вещи, которые, по моему мнению, были необходимы, из выходного XML-файла. По сути, я создал новый класс с именем CalibSet и просто извлек данные из файла xml через "tfs [" "] >> xxx;" внизу кода.

class CalibSet
{
public:
    Size Boardsize;              // The size of the board -> Number of items by width and height
    Size image;                 // image size
    String calibtime;
    Mat CamMat;                 // camera matrix
    Mat DistCoeff;              // distortion coefficient
    Mat PViewReprojErr;         // per view reprojection error
    float SqSize;            // The size of a square in your defined unit (point, millimeter,etc).
    float avg_reproj_error;
    int NrFrames;                // The number of frames to use from the input for calibration
    int Flags;
    bool imagePoints;            // Write detected feature points
    bool ExtrinsicParams;        // Write extrinsic parameters
    bool GridPoints;              // Write refined 3D target grid points
    bool fisheyemodel;             // use fisheye camera model for calibration

    void write(FileStorage& fs) const                        //Write serialization for this class
    {
        fs << "{"
            <<"nr_of_frames" << NrFrames
            <<"image_width" << image.width
            <<"image_height" << image.height
            <<"board_width" << Boardsize.width
            <<"board_height" << Boardsize.height
            <<"square_size" << SqSize
            <<"flags" << Flags
            <<"fisheye_model" << fisheyemodel
            <<"camera_matrix" << CamMat
            <<"distortion_coefficients" << DistCoeff
            <<"avg_reprojection_error" << avg_reproj_error
            <<"per_view_reprojection_errors" << PViewReprojErr
            <<"extrinsic_parameters" << ExtrinsicParams
            << "}";
    }

    void read(const FileNode& node)                          //Read serialization for this class
    {
        node["calibration_time"] >> calibtime;
        node["nr_of_frames"] >> NrFrames;
        node["image_width"] >> image.width;
        node["image_height"] >> image.height;
        node["board_width"] >> Boardsize.width;
        node["board_height"] >> Boardsize.height;
        node["square_size"] >> SqSize;
        node["flags"] >> Flags;
        node["fisheye_model"] >> fisheyemodel;
        node["camera_matrix"] >> CamMat;
        node["distortion_coefficients"] >> DistCoeff;
        node["avg_reprojection_error"] >> avg_reproj_error;
        node["per_view_reprojection_errors"] >> PViewReprojErr;
        node["extrinsic_parameters"] >> ExtrinsicParams;
    }
};

CalibSet CS;
FileStorage tfs(inputCalibFile, FileStorage::READ);     // Read the settings
if (!tfs.isOpened())
{
    cout << "Could not open the calibration file: \"" << inputCalibFile << "\"" << endl;
        return -1;
}
tfs["camera_matrix"] >> CS.CamMat;
tfs["distortion_coefficients"] >> CS.DistCoeff;
tfs["image_width"] >> CS.image.width;
tfs["image_height"] >> CS.image.height;
tfs.release();                                         // close Settings file

И после этого я использую функцию "неискажать", чтобы исправить живые кадры камеры, которые я сохранил в кадре, и поместить исправленное изображение в кадр.

flip(frame, frame, -1);     // flip image vertically so that it's not upside down
cv::undistort(frame, rframe, CS.CamMat, CS.DistCoeff);
flip(rframe, rframe, +1);   // flip image horizontally 

Важно удостовериться, что ориентация фотографий, снятых для выборки, точно такая же, как и в дальнейшем (включая зеркальное отражение по вертикали или горизонтали), иначе изображение по-прежнему будет искажено после использования "неискаженного изображения".

После этого я могу получить неискаженное изображение, как и предполагалось, НО частота кадров чрезвычайно низкая (около 10-20 кадров в секунду), и я буду признателен за любую помощь в оптимизации процесса, если это возможно; чтобы обеспечить более высокую частоту кадров из прямой трансляции камеры

Во-первых, вы должны создать матрицу камеры со значениями матрицы камеры из файла XML.

    Mat cameraMatrix = new Mat(new Size(3,3), CvType.CV_64FC1);
    cameraMatrix.put(0,0,3275.907);
    cameraMatrix.put(0,1,0);
    cameraMatrix.put(0,2,2069.153);
    cameraMatrix.put(1,0,0);
    cameraMatrix.put(1,1,3270.752);
    cameraMatrix.put(1,2,1139.271);
    cameraMatrix.put(2,0,0);
    cameraMatrix.put(2,1,0);
    cameraMatrix.put(2,2,1);

Во-вторых, создайте матрицу искажений с помощью Distortion_Coefficients из файла XML.

    Mat distortionMatrix = new Mat(new Size(4,1), CvType.CV_64FC1);
    distortionMatrix.put(0,0,-0.006934);
    distortionMatrix.put(0,1,-0.047680);
    distortionMatrix.put(0,2,0.002173);
    distortionMatrix.put(0,3,0.002580);

Наконец, используйте метод OpenCV.

    Mat map1 = new Mat();
    Mat map2 = new Mat();
    Mat temp = new Mat();
    Imgproc.initUndistortRectifyMap(cameraMatrix, distortionMatrix, temp, cameraMatrix, src.size(), CvType.CV_32FC1, map1, map2);

И вы можете получить две матрицы map1, map2, которые используют для искажения. Если вы получаете эти две матрицы, вам не нужно каждый раз калибровать заново. Просто используйте переназначение, и искажение будет сделано.

Imgproc.remap(mat, undistortPicture, map1, map2, Imgproc.INTER_LINEAR);

обратитесь по этой ссылке.

Другие вопросы по тегам