首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >校正全景(等长方形)图像

校正全景(等长方形)图像
EN

Stack Overflow用户
提问于 2019-06-21 17:21:48
回答 1查看 524关注 0票数 1

我正在校正WV-SFV481 (Panasonic)相机拍摄的全景(等矩形)格式的图像。

有关图像的示例,请参阅手册文件(第1.3- 2节全景):https://bizpartner.panasonic.net/public/sites/all/modules/panasonic/mypdfurl/pdf.js/web/viewer.html?file=/public/system/files/files/fields/field_file/psd/2017/09/20/PGQP1885UAC1_WV-SFV481_OI_en_1505871868.0502.pdf

我已经使用棋盘图像(全景格式)通过OpenCV校准了参数,遵循以下教程:https://medium.com/@kennethjiang/calibrate-fisheye-lens-using-opencv-part-2-13990f1b157f但是校正结果很差( OpenCV模块不支持全景格式)。

是否有支持全景图像校正的OpenCV模块或方法?

EN

回答 1

Stack Overflow用户

发布于 2019-11-12 21:05:13

虽然有点笨拙,但您可以通过cv::remap将柱形(等长方形全景)图像转换为直线(经典)。下面是C++代码:

代码语言:javascript
复制
using namespace cv;
const float PI = 3.1415927;

// Create 2 channel matrix with where values at I(x,y) = (x,y). This
// is to circumvent missing backward warping of CylindricalWarper
Mat createIndexMap(Size sz, Rect roi) {
    int nRows = roi.y + roi.height;
    int nCols = roi.x + roi.width;
    Mat res = Mat(Size(nCols, nRows), CV_32FC2);
    int i, j;
    float* p;
    for (i = 0; i < nRows; i++) {
        p = res.ptr<float>(i);
        for (j = 0; j < nCols; j++) {
            p[2 * j] = (float)j / nCols * sz.width;
            p[2 * j + 1] = (float)i / nRows * sz.height;
        }
    }
    return res;
}

// Create dewarp maps for transformation from cylindrical to rectilinear projection.
void createDewarpMaps(Size image_size, Size warped_size, Mat* map_x, Mat* map_y) {
    float warper_scale = image_size.width/ PI; // this assumes FOV 180 degrees

    Mat k = (Mat_<float>(3, 3) << 1, 0, image_size.width / (2.0 * warper_scale), 0, 1, image_size.height / (2.0 * warper_scale), 0, 0, 1 / warper_scale);
    Mat r = Mat::eye(3, 3, CV_32F);
    Ptr<WarperCreator> warper_creator;
    warper_creator = makePtr<CylindricalWarper>();
    Ptr<detail::RotationWarper> warper = warper_creator->create(static_cast<float>(warper_scale));
    Rect roi = warper->warpRoi(warped_size, k, r);
    roi.x = 0;
    roi.y = 0;
    Mat indexes = createIndexMap(warped_size, roi);
    Mat maps;
    warper->warpBackward(indexes, k, r, InterpolationFlags::INTER_CUBIC, BorderTypes::BORDER_REPLICATE, warped_size, maps);
    Mat map_array[2];
    split(maps, map_array);
    *map_x = map_array[0];
    *map_y = map_array[1];
}

// Draw dewarped image with center x
void dewarp(Mat frame, int center_x, Size dst_size, Mat* map_x, Mat* map_y) {
    int left_x = center_x - dst_size.width / 2;

    Rect roi(left_x, 0, dst_size.width, dst_size.height);
    Mat roi_mat = frame(roi);
    Mat dewarped_frame, rotated_frame;
    cv::remap(roi_mat, dewarped_frame, *map_x, *map_y, INTER_CUBIC, BORDER_CONSTANT, Scalar(255, 0, 0));
    imshow("dewarped", dewarped_frame);
}

int main(int argc, char** argv) {
    namedWindow("original", cv::WINDOW_NORMAL);
    namedWindow("dewarped", cv::WINDOW_AUTOSIZE);
    if (argc < 2) {
        cerr << "Provide path to image as an argument!\n";
        exit(-1);
    }
    shared_ptr<Mat> map_x = make_unique<Mat>();
    shared_ptr<Mat> map_y = make_unique<Mat>();
    Mat frame = imread(argv[1]);
    cv::resize(frame, frame, Size(), .5, .5);
    circle(frame, Point(frame.cols / 2, frame.rows / 2), 6, Scalar(255, 255, 0), -1);
    Size dst_size = frame.size();
    dst_size.width /= 2;
    createDewarpMaps(frame.size(), dst_size, map_x.get(), map_y.get());
    int x = frame.size().width /2 ;
    dewarp(frame, x, dst_size, map_x.get(), map_y.get());
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56700469

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档