Понимание функции undistort OpenCV

Я ищу, чтобы отменить искажение изображения, используя коэффициенты искажения, которые я рассчитал для моей камеры, без изменения матрицы камеры. Это именно то, что undistort() делает, но я хотел нарисовать вывод на большее изображение холста.

когда я попытался это:

Mat drawtransform = getOptimalNewCameraMatrix(cameraMatrix, distCoeffs, size, 1.0, size * 2);
undistort(inputimage, undistorted, cameraMatrix, distCoeffs, drawtransform);

он по-прежнему выписывал изображение того же размера, но только верхнюю левую четверть неискаженного результата. как говорится в документации, undistort пишет в a изображение одинакового размера.

довольно очевидно, что я могу просто скопировать и переосмыслить слегка измененную версию undistort() но у меня возникли некоторые проблемы с пониманием того, что он делает. Вот источник:

void cv::undistort( InputArray _src, OutputArray _dst, InputArray _cameraMatrix,
                    InputArray _distCoeffs, InputArray _newCameraMatrix )
{
    Mat src = _src.getMat(), cameraMatrix = _cameraMatrix.getMat();
    Mat distCoeffs = _distCoeffs.getMat(), newCameraMatrix = _newCameraMatrix.getMat();

    _dst.create( src.size(), src.type() );
    Mat dst = _dst.getMat();

    CV_Assert( dst.data != src.data );

    int stripe_size0 = std::min(std::max(1, (1 << 12) / std::max(src.cols, 1)), src.rows);
    Mat map1(stripe_size0, src.cols, CV_16SC2), map2(stripe_size0, src.cols, CV_16UC1);

    Mat_<double> A, Ar, I = Mat_<double>::eye(3,3);

    cameraMatrix.convertTo(A, CV_64F);
    if( distCoeffs.data )
        distCoeffs = Mat_<double>(distCoeffs);
    else
    {
        distCoeffs.create(5, 1, CV_64F);
        distCoeffs = 0.;
    }

    if( newCameraMatrix.data )
        newCameraMatrix.convertTo(Ar, CV_64F);
    else
        A.copyTo(Ar);

    double v0 = Ar(1, 2);
    for( int y = 0; y < src.rows; y += stripe_size0 )
    {
        int stripe_size = std::min( stripe_size0, src.rows - y );
        Ar(1, 2) = v0 - y;
        Mat map1_part = map1.rowRange(0, stripe_size),
            map2_part = map2.rowRange(0, stripe_size),
            dst_part = dst.rowRange(y, y + stripe_size);

        initUndistortRectifyMap( A, distCoeffs, I, Ar, Size(src.cols, stripe_size),
                                 map1_part.type(), map1_part, map2_part );
        remap( src, dst_part, map1_part, map2_part, INTER_LINEAR, BORDER_CONSTANT );
    }
}

около половины строк здесь предназначены для проверки здравомыслия и инициализации входных параметров. Что меня смущает, так это то, что происходит с map1 и map2. Эти имена, к сожалению, менее описательны, чем большинство. Я должен отсутствовать некоторые объяснение, возможно, оно спрятано на какой-то странице введения или под doc для другой функции.

map1 - двухканальная короткая целочисленная матрица со знаком и map2 - это беззнаковая короткая целочисленная матрица, обе имеют размерность (высота, Макс (4096/width, 1)). Вопрос в том, почему? Что будут содержать эти карты? В чем смысл и цель этого раздевания? В чем смысл и назначение странного измерения полос?

2 ответов


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

первая карта используется для вычисления преобразования координаты x в каждой позиции пикселя,вторая-для преобразования координаты Y.


возможно, вы захотите прочитать описание функции перекодировки. Карта представляет расположение пикселей X, Y в исходном изображении для каждого пикселя в целевом изображении. Map1_part-это каждое местоположение X в источнике, а Map2_part-каждое местоположение Y в источнике.

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

изменить:

кроме того, если вы хотите просто масштабировать изображения для большего размера можно просто изменить размер изображения.

double scaleX = 2.0;
double scaleY = 2.0;
cv::Mat undistortedScaled;

cv::resize(undistorted, undistortedScaled, cv::Size(0,0), scaleX, scaleY);