title: Barrel distortion correction algorithm to correct FishEye lens - failing to implement with Java
body: <p>I have a large bulk of photographs taken with a fisheye lens. As I want to do some image-processing (e.g. edge detection) on the photos I want to remove the barrel distortion which effects my results heavily.</p>
  
  <p>After some research and lots of read articles I found this <a href="http://mipav.cit.nih.gov/documentation/HTML%20Algorithms/BarrelDistortionCorrection.html" rel="nofollow noreferrer">page</a>:  They describe an algorithm (and some formulas) to solve this problem.</p>
  
  <blockquote>
    <p>M = a *rcorr^3 + b * rcorr^2 + c * rcorr + d<br>
    rsrc = (a * rcorr^3 + b * rcorr^2 + c * rcorr + d) * rcorr</p>
    
    <p>rsrc = distance of a pixel from the center of the source image<br>
    rcorr = distance of a pixel from the center in the corrected image<br>
    a,b,c = distortion of image 
    d = linear scaling of image</p>
  </blockquote>
  
  <p>I used these formulas and tried to implement this in a Java application. Unfortunately it doesn't work and I failed to make it work. "Corrected" image look nothing like the original photograph and instead show some mysterious circles in the middle. Look here:</p>
  
  <p><a href="http://imageshack.us/f/844/barreldistortioncorrect.jpg/" rel="nofollow noreferrer">http://imageshack.us/f/844/barreldistortioncorrect.jpg/</a>
  (this used to be a photograph of a white cow in front a blue wall)</p>
  
  <p>Here is my code:</p>
  
  <pre><code>protected int[] correction(int[] pixels) {
  
      //
      int[] pixelsCopy = pixels.clone();
  
      // parameters for correction
      double paramA = 0.0; // affects only the outermost pixels of the image
      double paramB = -0.02; // most cases only require b optimization
      double paramC = 0.0; // most uniform correction
      double paramD = 1.0 - paramA - paramB - paramC; // describes the linear scaling of the image
  
      //
      for(int x = 0; x &lt; dstView.getImgWidth(); x++) {
          for(int y = 0; y &lt; dstView.getImgHeight(); y++) {
  
              int dstX = x;
              int dstY = y;
  
              // center of dst image
              double centerX = (dstView.getImgWidth() - 1) / 2.0;
              double centerY = (dstView.getImgHeight() - 1) / 2.0;
  
              // difference between center and point
              double diffX = centerX - dstX;
              double diffY = centerY - dstY;
              // distance or radius of dst image
              double dstR = Math.sqrt(diffX * diffX + diffY * diffY);
  
              // distance or radius of src image (with formula)
              double srcR = (paramA * dstR * dstR * dstR + paramB * dstR * dstR + paramC * dstR + paramD) * dstR;
  
              // comparing old and new distance to get factor
              double factor = Math.abs(dstR / srcR);
              // coordinates in source image
              double srcXd = centerX + (diffX * factor);
              double srcYd = centerY + (diffX * factor);
  
              // no interpolation yet (just nearest point)
              int srcX = (int)srcXd;
              int srcY = (int)srcYd;
  
              if(srcX &gt;= 0 &amp;&amp; srcY &gt;= 0 &amp;&amp; srcX &lt; dstView.getImgWidth() &amp;&amp; srcY &lt; dstView.getImgHeight()) {
  
                  int dstPos = dstY * dstView.getImgWidth() + dstX;
                  pixels[dstPos] = pixelsCopy[srcY * dstView.getImgWidth() + srcX];
              }
          }
      }
  
      return pixels;
  }
  </code></pre>
  
  <p>My questions are:<br>
  1) Is this formula correct?<br>
  2) Do I have made a mistake turning that formula into a piece of software?<br>
  3) There are other algorithms out there (e.g. <a href="https://stackoverflow.com/questions/1927145/how-to-simulate-fisheye-lens-effect-by-opencv">How to simulate fisheye lens effect by openCV?</a> or  wiki/Distortion_(optics)), are they better?</p>
  
  <p>Thanks for your help!</p>