In this post I am demonstrating how 360 degree image can convert panoramic image using OpenCV C++.
Using the equation of circle we can find co-ordinate on circumference of a circle for given radius and arcLength;
where n = 0,1,2........,arcLength
Using above equation we can find each points inside the circle and corresponding points in panoramic output. The algorithm simply can explain like, first we took the outer perimeter of the input 360 degree image, then starch and straiten the image and then place in output image top row. Then we will come inner circle by decremented radius by 1 and take all points in the circle do the same stitching and straiten and the place on second row of output image. This will continue till the centre points and finally we will get the output unwrapped image. Here the width of the output image will be the arc-length and height will be the radius of input 360 image. The following code will give more idea about the algorithm.
Using the equation of circle we can find co-ordinate on circumference of a circle for given radius and arcLength;
Px = centX + radius * cos( 2𝜋*(x/ arcLength));
Py = centY + radius * sin( 2𝜋*(x/ arcLength));
where n = 0,1,2........,arcLength
Using above equation we can find each points inside the circle and corresponding points in panoramic output. The algorithm simply can explain like, first we took the outer perimeter of the input 360 degree image, then starch and straiten the image and then place in output image top row. Then we will come inner circle by decremented radius by 1 and take all points in the circle do the same stitching and straiten and the place on second row of output image. This will continue till the centre points and finally we will get the output unwrapped image. Here the width of the output image will be the arc-length and height will be the radius of input 360 image. The following code will give more idea about the algorithm.
Load Input image
Mat src = imread("img/pan9.jpg", IMREAD_COLOR);
Calculate Output Image Size
double radius = src.rows/2; // radius will be the half height of input image
double arcLength = 2.0*CV_PI*radius; // arcLength will be the width of the output image
Mat dst(radius,arcLength,CV_8UC3,Scalar::all(0));
cv::Point cent(src.cols/2, src.rows/2);
The actual Unwrap Code
Here we will iterate through each points in output image and find corresponding points in input image, take that points and place it on output image. If the output image seems inverted just reverse the order destination points. See the commented code below.
for(double y=0; y < radius; y++){
for(double x=0; x < arcLength; x++){
int xT = (int)round((double)cent.x + (y) * cos( 2*CV_PI*(x/ arcLength)));
int yT = (int)round((double)cent.y + (y) * sin( 2*CV_PI*(x/ arcLength)));
dst.at < Vec3b >(Point(x,radius-y-1)) = src.at < Vec3b > (Point(xT,yT));
//dst.at < Vec3b >(Point(x,y)) = src.at < Vec3b >(Point(xT,yT)); //if image is inverted use this
}
}
Display and Save the result
imwrite("wunwrapped.jpg",dst);
imshow("src",src);
imshow("dst",dst);
waitKey();
Result
Input 1
Output 1
Input 2
Output 2
Full Code
//Load image and create output image
Mat src = imread("img/pan9.jpg", IMREAD_COLOR);
double radius = src.rows/2;
double arcLength = 2.0*CV_PI*radius;
Mat dst(radius,arcLength,CV_8UC3,Scalar::all(0));
cv::Point cent(src.cols/2, src.rows/2);
//Unwrap image
for(double y=0; y < radius; y++){
for(double x=0; x < arcLength; x++){
int xT = (int)round((double)cent.x + (y) * cos( 2*CV_PI*(x/ arcLength)));
int yT = (int)round((double)cent.y + (y) * sin( 2*CV_PI*(x/ arcLength)));
dst.at < Vec3b > (Point(x,radius-y-1)) = src.at < Vec3b > (Point(xT,yT));
//dst.at < Vec3b >(Point(x,y)) = src.at < Vec3b >(Point(xT,yT)); //if image is inverted use this
}
}
//Display and save result.
imwrite("wunwrapped.jpg",dst);
imshow("src",src);
imshow("dst",dst);
waitKey();
No comments:
Post a Comment