使用OpenCV4将鱼眼图像转换为全景图像的C ++算法

8
我想使用OpenCV4库创建一个C ++代码,将鱼眼图像转换为全景图像。 我正在使用1400 * 1400像素的鱼眼图像进行测试,并从计算机文件中加载:

fishey image

构建工作正常,但是当我尝试执行代码时,出现以下错误:

Segmentation fault: 11

我在MacOSX上使用Xcode,并使用终端“ITerm2”来构建和执行我的代码。
我使用此博客中描述的方法,在全景图像中查找鱼眼图像的对应点: http://www.kscottz.com/dewarped-panoramic-images-from-a-raspberrypi-camera-module/ 该方法可以通过以下方式描述:

picture.

感谢任何帮助。
#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>
#include <string.h>

using namespace cv;
using namespace std;

const string PATH_IMAGE = "/Users/Kenza/Desktop/Xcode_cpp_opencv/Projection/Projection/Images/img1.jpg";
const double PI = 3.141592653589793;
const int ESC = 27;

int main() {

    cout << "********** READ AND DISPLAY THE FISHEYE (=INPUT) IMAGE **********" << endl;
    Mat fisheyeImage;

    fisheyeImage = imread(PATH_IMAGE, IMREAD_COLOR);
    namedWindow("Fisheye Image", WINDOW_AUTOSIZE);
    imshow("Fisheye Image", fisheyeImage);

    while (waitKey(0) != ESC) {
        //wait until the key ESC is pressed
    }

    destroyWindow("Fisheye Image");

    cout << "********** CREATE AND LOAD PARAMETERS FOR THE FISHEYE (=INPUT) AND THE EQUIRECTANGULAR IMAGE (=OUTPOUT) **********" << endl;
    int Hf, Wf; //Height and Width of the fisheye image (= input)
    double R, Cfx, Cfy; //Radius and Center coordinates for the fisheye image
    int He, We; //Height and Width of the equirectangular image (= outpout)

    Hf = fisheyeImage.size().height;
    Wf = fisheyeImage.size().width;
    R = Hf / 2; //The fisheye image is a square of 1400x1400 pixels containing a circle so the radius is half of the width or height size
    Cfx = Wf / 2; //The fisheye image is a square so the center in x is located at half the distance of the width
    Cfy = Hf / 2; //The fisheye image is a square so the center in y is located at half the distance of the height

    He = R;
    We = 2 * PI*R;

    cout << "********** MAPPING : FINDING THE COORDINATES (Xf,Yf) IN THE FISHEYE IMAGE THAT CORRESPOND TO THE COORDINATE (Xe,Fe) IN THE EQUIRECTANGULAR IMAGE **********" << endl;
    Mat mapXf; //Contains all the Xf values of the fisheye image which correspond to each Xe and Ye in the equirectangular image
    Mat mapYf; //Contains all the Yf values of the fisheye image which correspond to each Xe and Ye in the equirectangular image

    mapXf.zeros(Size(We, He), CV_32FC1); //Initialize mapXf with zeros
    mapYf.zeros(Size(We, He), CV_32FC1); //Initialize mapYf with zeros

    double r, theta; //Polar coordinates for the fisheye image
    double Xf, Yf; //Cartesian coordinates for the fisheye image

    for (int Ye = 0; Ye < ((int)He); Ye++) { //For each value of Ye in the equirectangular image...
        for (int Xe = 0; Xe < ((int)We); We++) { //For each value of Xe in the equirectangular image..
            r = Ye / He * R; //We find the value of r in the fisheye image
            theta = Xe / We * 2.0*PI; //We find the value of theta in the fisheye image
            Xf = Cfx + r * sin(theta); //We get with r and theta the value of Xf
            Yf = Cfy + r * cos(theta); //We get with r and theta the value of Yf
            mapXf.at<int>(Ye, Xe) = Xf; //We fill the mapping for Xf
            mapYf.at<float>(Ye, Xe) = Yf; //We fill the mapping for Yf
        }
    }

    cout << "********** FISHEYE TO EQUIRECTANGULAR **********" << endl;
    Mat equirectangularImage;
    equirectangularImage.zeros(Size(We, He), CV_32FC1); //Initialize the equirectangular image with zeros
    remap(fisheyeImage, equirectangularImage, mapXf, mapYf, INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 0));

    namedWindow("Equirectangular Image", WINDOW_AUTOSIZE);
    imshow(" Cartesienne", equirectangularImage);

    while (waitKey(0) != ESC) {
        //wait until the key ESC is pressed
    }

    destroyWindow("Equirectangular Image");

    return 0;
}

3
使用调试器来查看问题所在是个好主意。 - BartekPL
@BartekPL,感谢您的回复。我使用调试器发现Mat.zeros()函数没有像我想象的那样设置Mat对象的维度,所以我用以下代码进行替换: mapXf.create(He, We, CV_32FC1); mapYf.create(He, We, CV_32FC1); equirectangularImage.create(He, We, CV_32FC1); - KenZone51
我还注意到在for循环中犯了一个错误,我的代码中将We++写成了We++, 因此我进行了替换:for (int Ye = 0; Ye < ((int)He); Ye++) { for (int Xe = 0; Xe < ((int)We); Xe++)现在我的问题是,在程序的末尾,包含等距图像(输出图像)的窗口为空白。我不知道我是否使用了正确的方式访问像素并映射它们。 - KenZone51
1个回答

5

我最终找到了一个可行的替代代码,输出的图像看起来像这样:在此输入图片描述

以下是可用代码:

#include <iostream>
#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;

const double PI = 3.141592653589793;
const string PATH_IMAGE =   "/Users/Kenza/Desktop/Xcode_cpp_opencv/PaulBourke/PaulBourke/Images/img1.jpg";
const int ESC = 27;

//Find the corresponding fisheye outpout point corresponding to an input cartesian point
Point2f findFisheye(int Xe, int Ye, double R, double Cfx, double Cfy, double He, double We){
    Point2f fisheyePoint;
    double theta, r, Xf, Yf; //Polar coordinates

    r = Ye/He*R;
    theta = Xe/We*2.0*PI;
    Xf = Cfx+r*sin(theta);
    Yf = Cfy+r*cos(theta);
    fisheyePoint.x = Xf;
    fisheyePoint.y = Yf;

    return fisheyePoint;
}

int main(int argc, char** argv){

    Mat fisheyeImage, equirectangularImage;

    fisheyeImage = imread(PATH_IMAGE, IMREAD_COLOR);
    namedWindow("Fisheye Image", WINDOW_AUTOSIZE);
    imshow("Fisheye Image", fisheyeImage);


    while(waitKey(0) != ESC) {
    //wait until the key ESC is pressed
    }

    //destroyWindow("Fisheye Image");

    int Hf, Wf, He, We;
    double R, Cfx, Cfy;

    Hf = fisheyeImage.size().height;
    Wf = fisheyeImage.size().width;
    R = Hf/2; //The fisheye image is a square of 1400x1400 pixels containing a circle so the radius is half of the width or height size
    Cfx = Wf/2; //The fisheye image is a square so the center in x is located at half the distance of the width
    Cfy = Hf/2; //The fisheye image is a square so the center in y is located at half the distance of the height

    He = (int)R;
    We = (int)2*PI*R;

    equirectangularImage.create(He, We, fisheyeImage.type());

    for (int Xe = 0; Xe <equirectangularImage.size().width; Xe++){
        for (int Ye = 0; Ye <equirectangularImage.size().height; Ye++){

            equirectangularImage.at<Vec3b>(Point(Xe, Ye)) =    fisheyeImage.at<Vec3b>(findFisheye(Xe, Ye, R, Cfx, Cfy, He, We));
        }
    }

    namedWindow("Equirectangular Image", WINDOW_AUTOSIZE);
    imshow("Equirectangular Image",equirectangularImage);

    while(waitKey(0) != ESC) {
    //wait until the key ESC is pressed
    }

    //destroyWindow("Fisheye Image");

    imwrite("equirectangularImage.jpg", equirectangularImage);

    return 0;
}

这张最终的图片与拍摄时实际距离和大小更接近还是更远? - M.K

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