2016-10-20 5 views
1

J'essaie de trouver une méthode pour assembler deux images provenant de deux caméras fish-eye. Mais je n'ai aucune idée de comment corriger les images originales. J'ai essayé de le faire avec fisheye de classe dans opencv3.0 mais il a une grande perte de vue de sorte que je n'ai pas assez d'informations pour coudre à l'étape suivante. Alors, y a-t-il une idée pour résoudre ce problème? J'ai de la chance si vous pouviez me montrer une stratégie spécifique. Merci beaucoup!Comment enregistrer la vue après la distorsion de la caméra

Répondre

0

En utilisant ce link comme référence. J'ai été capable de corriger la distorsion des poissons des images. Voici un exemple de code

#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); 
} 
+0

Merci pour votre réponse! Je note que cette méthode n'est pas basée sur les paramètres intrinsèques de la caméra fish-eye, reconstruire l'image de distorsion dans l'espace 3D mais rectifier l'image juste en 2D. Cela peut entraîner une vision anormale qui n'est pas la même que celle de l'humain. Alors, y a-t-il une méthode pour ne pas distordre l'image de façon perspective et sauver le FOV de la caméra? –