我有一个equirectangular缝合的全景图像,我想用球面投影显示。我之前使用openCV' s imshow
按原样显示图像(带有equirectangular投影),但图像的顶部和底部部分扭曲(与任何equirectangular投影一样)我想要摆脱这种扭曲。
我在openCV中找到了SphericalWarper,可以帮助我做到这一点。但我在理解如何使用warp
时遇到了一些问题。
现在,我的代码中出现扭曲的部分看起来像这样:
Mat panorama;
Mat K = Mat::zeros(3, 3, CV_32F);
Mat R = Mat::eye(3, 3, CV_32F);
detail::SphericalWarper warper = detail::SphericalWarper(1.0f);
warper.warp(imgBgr, K, R, INTER_LINEAR, BORDER_DEFAULT,panorama);
imshow("Display frame", panorama);
waitKey(0);
我的源图片imgBgr
看起来像这样(不完全是我的,只是一个例子):
目前,我得到的输出图像panorama
看起来像是没有任何镜头的图像传感器的图像:
我想这是有道理的,因为目前我的相机内部矩阵是全零的3x3矩阵。所以我的问题是:相机内在矩阵应该包含什么?我有摄像机的相机内部参数,这些参数拍摄的图像被缝合以产生我的源equirectangular图像(imgBgr
),但我不确定warper
是否需要这些相同的参数。我只想用球形投影来查看我的源图像,这样就不再存在由等角投影引起的失真。我希望输出图像与Google街景类似。
答案 0 :(得分:0)
我坚持同样的问题,但是在经过一些实验之后我才走出了洞。内在矩阵看起来像:
fx, 0, cx,
0, fy, cy,
0, 0, 1
其中f(x,y)是比例因子,c(x,y)是中心偏移。您可以使用代码中的所有参数进行演绎:
#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/stitching/warpers.hpp>
using namespace std;
using namespace cv;
// Calculates rotation matrix given euler angles.
Mat eulerAnglesToRotationMatrix(Vec3f &theta)
{
// Calculate rotation about x axis
Mat R_x = (Mat_<float>(3,3) <<
1, 0, 0,
0, cosf(theta[0]), -sinf(theta[0]),
0, sinf(theta[0]), cosf(theta[0])
);
// Calculate rotation about y axis
Mat R_y = (Mat_<float>(3,3) <<
cosf(theta[1]), 0, sinf(theta[1]),
0, 1, 0,
-sinf(theta[1]), 0, cosf(theta[1])
);
// Calculate rotation about z axis
Mat R_z = (Mat_<float>(3,3) <<
cosf(theta[2]), -sinf(theta[2]), 0,
sinf(theta[2]), cosf(theta[2]), 0,
0, 0, 1);
// Combined rotation matrix
Mat R = R_z * R_y * R_x;
return R;
}
int main(int argc, const char * argv[]) {
// insert code here...
std::cout << "Hello, World!\n";
Mat origImg = imread("..path to file..");
imshow("src", origImg);
float scale = 100.0;
float fx = 100, fy = 100, cx = 500, cy = 300;
Vec3f rot = {};
while (true) {
cout << "•" << endl;
cout << "Fx: " << fx << "; Fy: " << fy << endl;
cout << "Cx: " << fx << "; Cy: " << fy << endl;
cout << "Scale: " << scale << endl;
cout << "Ang: " << rot << endl;
detail::SphericalWarper wrap(scale);
Mat K = (Mat_<float>(3,3) <<
fx, 0, cx,
0, fy, cy,
0, 0, 1);
Mat R = eulerAnglesToRotationMatrix(rot);
Mat dst;
wrap.warp(origImg, K, R, INTER_LINEAR, BORDER_CONSTANT, dst);
imshow("dst", dst);
cout << dst.size() << endl;
char c = waitKey();
if (c == 'q') break;
else if (c == 'a') fx += 10;
else if (c == 'z') fx -= 10;
else if (c == 's') fy += 10;
else if (c == 'x') fy -= 10;
else if (c == 'd') scale += 10;
else if (c == 'c') scale -= 10;
else if (c == 'f') rot[0] += 0.1;
else if (c == 'v') rot[0] -= 0.1;
else if (c == 'g') rot[1] += 0.1;
else if (c == 'b') rot[1] -= 0.1;
else if (c == 'h') rot[2] += 0.1;
else if (c == 'n') rot[2] -= 0.1;
}
return 0;
}