I want to create a C++ code with the OpenCV4 library that convert a fisheye image to an equirectangular image. I'm using as a test a fisheye image of 1400*1400 pixels loading from a file on my Computer:
The build works well but when I try to execute the code, I get a
Segmentation fault: 11
error. I'm working on a MacOSX with Xcode and I use Terminal "ITerm2" to build and execute my code.
I us the method described on this blog to find the corresponding points of the fisheye image in the equirectangular image: http://www.kscottz.com/dewarped-panoramic-images-from-a-raspberrypi-camera-module/
The method can be described by this:
.
Thanks for any help.
#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;
}
If you want to convert a fisheye or dual fisheye video to equirectangular, right-click the clip in the 360 Video > 360 Video Conversion, and choose the corresponding option. If you want to adjust any conversion settings, adjust the controls and click OK.
I finally found an alternative code that works, the outpout image looks like this :
The code is available below :
#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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With