将全画幅鱼眼图像数学地转换为等距矩形图像

4
我想将全幅鱼眼图像转换为等距矩形,以便于拼接成全景图。我已经使用了Hugin和libpano实现了这一目的,它们效果很好。下面的图像是由Hugin转换而成的。我想知道可以通过哪些数学方程来实现这样或类似的转换。 原始图像: Full-Frame FishEye 转换后的图像: Converted Image
1个回答

5

使用这个链接作为参考,我成功地将图像转换得接近hugin生成的图像。但仍需要进行亚像素采样以获得更好的图像质量。

 #include <iostream>
 #include <sstream>
 #include <time.h>
 #include <stdio.h>
 #include <opencv2/core/core.hpp>
 #include <opencv2/imgproc/imgproc.hpp>
 #include <opencv2/calib3d/calib3d.hpp>
 #include <opencv2/highgui/highgui.hpp>
 using namespace std;
 using namespace cv;
 #define PI 3.1415926536
 Point2f getInputPoint(int x, int y,int srcwidth, int srcheight)
 {
    Point2f pfish;
    float theta,phi,r;
    Point3f psph;
    //float FOV = PI;
    float FOV =(float)PI/180 * 150;
    float FOV2 = (float)PI/180 * 120;;
    float width = srcwidth;
    float height = srcheight;
    theta = PI * (x / width - 0.5); // -pi to pi
    phi = PI * (y / height - 0.5);  // -pi/2 to pi/2
    psph.x = cos(phi) * sin(theta);
    psph.y = cos(phi) * cos(theta);
    psph.z = sin(phi);
    theta = atan2(psph.z,psph.x);
    phi = atan2(sqrt(psph.x*psph.x+psph.z*psph.z),psph.y);
    r = width * phi / FOV;
    float r2 = height * phi / FOV2;
    pfish.x = 0.5 * width + r * cos(theta);
    pfish.y = 0.5 * height + r2 * sin(theta);
    return pfish;
}
int main(int argc, char **argv)
{
    if(argc< 3)
        return 0;
    Mat orignalImage = imread(argv[1]);
    if(orignalImage.empty())
    {
        cout<<"Empty image\n";
        return 0;
    }
    Mat outImage(orignalImage.rows,orignalImage.cols,CV_8UC3);
        //getInputPoint(0,5,10,10);
    namedWindow("result",CV_WINDOW_NORMAL);
    for(int i=0; i<outImage.cols; i++)
    {
        for(int j=0; j<outImage.rows; j++)
        {

            Point2f inP =  getInputPoint(i,j,orignalImage.cols,orignalImage.rows);
            //cout<<"in "<<i<<","<<j<<endl;
            //cout<<"out "<<inP.x<<","<<inP.y<<endl;
            Point inP2((int)inP.x,(int)inP.y);
            if(inP2.x >= orignalImage.cols || inP2.y >= orignalImage.rows)
                continue;
            if(inP2.x < 0 || inP2.y < 0)
                continue;
            Vec3b color = orignalImage.at<Vec3b>(inP2);
            outImage.at<Vec3b>(Point(i,j)) = color;

        }
    }

    imshow("result",outImage);
    imwrite(argv[2],outImage);


}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接