2016-10-20 3 views
1

두 개의 물고기 눈 카메라에서 나온 두 개의 이미지를 스티칭하는 방법을 찾으려고합니다. 하지만 원본 이미지를 수정하는 방법에 대해서는 잘 모릅니다. 나는 opencv3.0에서 fisheye 클래스를 사용하여이 작업을 시도했지만 다음 단계에서 스티치 할 충분한 정보가 없도록 큰 화면 손실이 있습니다. 이 문제를 해결할 수있는 아이디어가 있습니까? 네가 나에게 특별한 전략을 보여줄 수 있다면 나는 운이 좋다. 고마워요!카메라 왜곡 후 뷰를 저장하는 방법

답변

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

답장을 보내 주셔서 감사합니다! 이 방법은 물고기 눈 카메라 고유의 매개 변수를 기반으로하지 않고 3D 공간에서 왜곡되지 않은 이미지를 재구성하지만 2D에서 이미지를 바로 잡습니다. 이것은 인간의 것과는 다른 괴상한 시각을 초래할 수 있습니다. 원근감있는 방식으로 이미지를 왜곡시키지 않고 카메라의 FOV를 절약 할 수있는 방법이 있습니까? –

관련 문제