我正在尝试找到一种方法来拼接来自两个鱼眼相机的两个图像。但我不知道如何纠正原始图像。我试图用opencv3.0中的类鱼眼来做这个,但它有很大的视图丢失,所以我没有足够的信息在下一步缝合。那么有什么想法可以解决这个问题吗?如果你能告诉我一个具体的策略,我很幸运。非常感谢你!
答案 0 :(得分:0)
使用此link作为参考。我能够纠正图像的鱼变形。这是一个示例代码
#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
#define CHANNELS 3
#define BORDER_TO_USE BORDER_REFLECT
/*
#define OUT_WIDTH 1920
#define OUT_HEIGHT 1513
*/
Point2f getInputPoint(int x, int y,int srcwidth, int srcheight,int hFov,int vFov)
{
Point2f pfish;
float theta,phi,r;
Point3f psph;
//float FOV = PI;
float FOV =(float)PI/180 * hFov;
float FOV2 = (float)PI/180 * vFov;
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;
}
void getMatColorValue(Mat src,const int& x, const int& y,
int& val1, int& val2, int& val3)
{
if (x < 0 || x >= src.cols || y < 0 || y >= src.rows)
{
val1 = 0;
val2 = 0;
val3 = 0;
}
else
{
val1 = src.ptr(y)[x * CHANNELS];
val2 = src.ptr(y)[x * CHANNELS + 1];
val3 = src.ptr(y)[x * CHANNELS + 2];
}
}
Vec3b BilinearInterpolation(Point2f inP,Mat src)
{
// Bilinear interpolation
int tXi = floor(inP.x);
int tYi = floor(inP.y);
float dX = inP.x - tXi; // differential
float dY = inP.y - tYi;
int rgbValues[4][3];
int val1,val2,val3;
getMatColorValue(src, tXi, tYi, rgbValues[0][0], rgbValues[0][1], rgbValues[0][2]);
getMatColorValue(src, tXi+1, tYi, rgbValues[1][0], rgbValues[1][1], rgbValues[1][2]);
getMatColorValue(src, tXi, tYi+1, rgbValues[2][0], rgbValues[2][1], rgbValues[2][2]);
getMatColorValue(src, tXi+1, tYi+1, rgbValues[3][0], rgbValues[3][1], rgbValues[3][2]);
float x;
// Update val1
x = rgbValues[0][0] * (1-dX) * (1-dY) +
rgbValues[1][0] * (dX) * (1-dY) +
rgbValues[2][0] * (1-dX) * (dY) +
rgbValues[3][0] * (dX) * (dY);
if (x < 0)
val1 = 0;
else if (x > (unsigned char)(-1))
val1 = (unsigned char)(-1);
else
val1 = x;
// Update val2
x = rgbValues[0][1] * (1-dX) * (1-dY) +
rgbValues[1][1] * (dX) * (1-dY) +
rgbValues[2][1] * (1-dX) * (dY) +
rgbValues[3][1] * (dX) * (dY);
if (x < 0)
val2 = 0;
else if (x > (unsigned char)(-1))
val2 = (unsigned char)(-1);
else
val2 = x;
// Update val3
x = rgbValues[0][2] * (1-dX) * (1-dY) +
rgbValues[1][2] * (dX) * (1-dY) +
rgbValues[2][2] * (1-dX) * (dY) +
rgbValues[3][2] * (dX) * (dY);
if (x < 0)
val3 = 0;
else if (x > (unsigned char)(-1))
val3 = (unsigned char)(-1);
else
val3 = x;
Vec3b color;
color.val[0] = val1;
color.val[1] = val2;
color.val[2] = val3;
return color;
}
/*Vec3b getColorSubpix(const cv::Mat& img, cv::Point2f pt)
{
int x = (int)pt.x;
int y = (int)pt.y;
int x0 = cv::borderInterpolate(x, img.cols, BORDER_TO_USE);
int x1 = cv::borderInterpolate(x + 1, img.cols, BORDER_TO_USE);
int y0 = cv::borderInterpolate(y, img.rows, BORDER_TO_USE);
int y1 = cv::borderInterpolate(y + 1, img.rows, BORDER_TO_USE);
float a = pt.x - (float)x;
float c = pt.y - (float)y;
uchar b = (uchar)cvRound((img.at<cv::Vec3b>(y0, x0)[0] * (1.f - a) + img.at<cv::Vec3b>(y0, x1)[0] * a) * (1.f - c)
+ (img.at<cv::Vec3b>(y1, x0)[0] * (1.f - a) + img.at<cv::Vec3b>(y1, x1)[0] * a) * c);
uchar g = (uchar)cvRound((img.at<cv::Vec3b>(y0, x0)[1] * (1.f - a) + img.at<cv::Vec3b>(y0, x1)[1] * a) * (1.f - c)
+ (img.at<cv::Vec3b>(y1, x0)[1] * (1.f - a) + img.at<cv::Vec3b>(y1, x1)[1] * a) * c);
uchar r = (uchar)cvRound((img.at<cv::Vec3b>(y0, x0)[2] * (1.f - a) + img.at<cv::Vec3b>(y0, x1)[2] * a) * (1.f - c)
+ (img.at<cv::Vec3b>(y1, x0)[2] * (1.f - a) + img.at<cv::Vec3b>(y1, x1)[2] * a) * c);
return cv::Vec3b(b, g, r);
}*/
void CropBlackArea(Mat image,int &top,int &bottom)
{
Mat slider;
Mat gray;
cvtColor(image,gray,CV_BGR2GRAY);
int i=0;
for(i=0; i<image.rows-1;i++)
{
slider = gray(Rect(0,i,gray.cols,1));
if(countNonZero(slider) == 0)
continue;
else
break;
}
top = i;
i=0;
for(i=image.rows-1; i>=0;i--)
{
slider = gray(Rect(0,i,gray.cols,1));
if(countNonZero(slider) == 0)
continue;
else
break;
}
bottom = i;
}
int main(int argc, char **argv)
{
/*Arguments should be 1-input_image_path 2-Output_image_path 3-Horizontal fov(Field of view) of the lense 4-Vertical fov of the lense*/
if(argc< 5)
return 0;
FileStorage fsx("FishEyeConversionXmap.yml", FileStorage::WRITE);
FileStorage fsy("FishEyeConversionYmap.yml", FileStorage::WRITE);
Mat orignalImage = imread(argv[1]);
int hFov = atoi(argv[3]);
int vFov = atoi(argv[4]);
//resize(orignalImage,orignalImage,Size(720,1280));
if(orignalImage.empty())
{
cout<<"Empty image\n";
return 0;
}
Mat outImage(orignalImage.rows,orignalImage.cols,CV_8UC3);
Mat xMap(orignalImage.rows,orignalImage.cols,CV_32FC1);
Mat yMap(orignalImage.rows,orignalImage.cols,CV_32FC1);
//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,hFov,vFov);
xMap.at<float>(j,i) = inP.x;
yMap.at<float>(j,i) = inP.y;
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 = getColorSubpix(orignalImage,inP);
//Vec3b color = orignalImage.at<cv::Vec3b>(inP2.y,inP2.x);
Vec3b color = BilinearInterpolation(inP,orignalImage);
outImage.at<Vec3b>(Point(i,j)) = color;
}
}
int top,bottom;
CropBlackArea(outImage,top,bottom);
cout<<"Croping "<<top<<","<<bottom<<"\n";
cout<<outImage.size()<<endl;
Rect r(0,top,outImage.cols,(bottom-top));
cout<<r<<endl;
outImage = outImage(r);
xMap = xMap(r);
yMap = yMap(r);
/* resize(outImage,outImage,Size(OUT_WIDTH,OUT_HEIGHT));
resize(outImage,outImage,Size(OUT_WIDTH,OUT_HEIGHT));
resize(xMap,xMap,Size(OUT_WIDTH,OUT_HEIGHT));
resize(yMap,yMap,Size(OUT_WIDTH,OUT_HEIGHT));*/
fsx << "xMap" << xMap;
fsy << "yMap" << yMap;
fsx.release();
fsy.release();
imshow("result",outImage);
imwrite(argv[2],outImage);
waitKey(0);
}