我正在校正WV-SFV481(松下)相机拍摄的全景(矩形)图像。
有关图像示例,请参见手册文件(第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模块或方法支持对全景图像进行校正?
答案 0 :(得分:0)
虽然有点笨重,但您可以通过cv :: remap将圆柱(等边矩形全景)图像转换为直线(经典)图像。这是C ++代码:
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());
}