2016-02-15 3 views
1

Я видел по этой ссылке http://www.tannerhelland.com/4743/simple-algorithm-correcting-lens-distortion/ алгоритм для отмены искажения объективов Fisheye, и я попытался реализовать его на C++ с opencv. Выходное изображение точно такое же, как и входное изображение, когда сила параметра близка к нулю, и я получаю плохие результаты с более высокими значениями. Если кто-то знает, что может быть проблемой (в моем коде или, в общем, в алгоритме), было бы очень полезно. спасибо.Коррекция искажений рыбий глаз

#include "opencv2\core\core.hpp" 
#include "opencv2\highgui\highgui.hpp" 
#include "opencv2\calib3d\calib3d.hpp" 
#include <stdio.h> 
#include <iostream> 
#include <math.h> 

using namespace std; 
using namespace cv; 

int main() { 

    cout << " Usage: display_image ImageToLoadAndDisplay" << endl; 
    Mat_<Vec3b> eiffel; 
    eiffel = imread("C:/Users/Administrator/Downloads/TestFisheye.jpg", CV_LOAD_IMAGE_COLOR); // Read the file 
    if (!eiffel.data)        // Check for invalid input 
    { 
     cout << "Could not open or find the image" << endl; 
     return -1; 
    } 
    cout << "Input image depth: " << eiffel.depth() << endl; 

    namedWindow("Display window", WINDOW_AUTOSIZE);// Create a window for display. 
    imshow("Display window", eiffel);     // Show our image inside it. 

    //waitKey(0);           // Wait for a keystroke in the window 

    int halfWidth = eiffel.rows/2; 
    int halfHeight = eiffel.cols/2; 
    double strength = 0.0001; 
    double correctionRadius = sqrt(pow(eiffel.rows, 2) + pow(eiffel.cols, 2))/strength; 
    Mat_<Vec3b> dstImage = eiffel; 

    int newX, newY; 
    double distance; 
    double theta; 
    int sourceX; 
    int sourceY; 
    double r; 
    for (int i = 0; i < dstImage.rows; ++i) 
    { 
     for (int j = 0; j < dstImage.cols; j++) 
     { 
      newX = i - halfWidth; 
      newY = j - halfHeight; 
      distance = sqrt(pow(newX, 2) + pow(newY, 2)); 
      r = distance/correctionRadius; 
      if (r == 0.0) 
       theta = 1; 
      else 
       theta = atan(r)/r; 

      sourceX = round(halfWidth + theta*newX); 
      sourceY = round(halfHeight + theta * newY); 

      dstImage(i, j)[0] = eiffel(sourceX, sourceY)[0]; 
      dstImage(i, j)[1] = eiffel(sourceX, sourceY)[1]; 
      dstImage(i, j)[2] = eiffel(sourceX, sourceY)[2]; 
     } 
    } 

    namedWindow("Display window 2", WINDOW_AUTOSIZE); 
    imshow("Display window 2", dstImage);     // Show our image inside it. 
    waitKey(0); 

    return 0; 
} 

PS: В настоящее время я работаю над первым изображением, размещенным по ссылке.

+0

[This] (http://marcodiiga.github.io/radial-lens-undistortion-filtering) также может вас заинтересовать –

ответ

2

У вас есть 2 проблемы здесь:

1 - вам нужно увеличить силу от 0,0001 до чего-то более разумном (попробуйте 5).

2 - вы используете одну и ту же матрицу происхождения и назначения. Этот Mat_<Vec3b> dstImage = eiffel; не выделяет никакой новой памяти. dstImage - это просто умный указатель на исходное изображение. Поэтому, когда вы его изменяете, вы одновременно изменяете исходное изображение. Это даст вам очень плохие результаты. Вместо того, чтобы сделать Mat_<Vec3b> dstImage = eiffel.clone()

С этими изменениями я получаю следующее изображение: enter image description here

Не большой, но по крайней мере, быстрый & простой.