title: Correcting barrel lens distortion in an x,y series in R
body: <p><strong>Edit: Ideally, I would like to use an identical algorithm to ImageMagick's <code>-distort</code> function, but implemented in R so as to transform raw x,y coordinates, rather than images. Using ImageMagick would also allow me to gain a visual proof of the effectiveness of the undistortion.</strong></p>
  
  <h3>The question</h3>
  
  <p>I have an x,y series, produced from analysis of a video by a tracking software. The original images in the video have some barrel lens distortion that I would like to correct in order to improve the accuracy of the tracking coordinates.</p>
  
  <p>I can perform what looks like a suitable correction using the distort operator in ImageMagick, e.g.:</p>
  
  <p><code>convert input.jpg -distort barrel '0 -0.022 0' output.jpg</code></p>
  
  <p>Now I know I could apply this correction to each frame in the video (before tracking), but this doesn't seem like the best option as I have dozens of videos, each of which consists of >7e4 frames. It seems like it would be much easier to apply the correction to the x,y coordinates themselves after tracking.</p>
  
  <p>From the ImageMagick <a href="http://www.imagemagick.org/Usage/distorts/#barrel" rel="nofollow noreferrer">documentation</a>, the barrel distortion equation is:</p>
  
  <blockquote>
    <p>Rsrc = r * ( A<em>r^3 + B</em>r^2 + C*r + D )  </p>
    
    <p>Where "r" is the destination radius and "Rsrc" is the source pixel to get the pixel color from. the radii are normalized so that radius = '1.0' for the half minimum width or height of the input image."</p>
  </blockquote>
  
  <p>But I'm unaware of how to implement this in R in order to transform an x,y series. Could anyone offer any help? Thanks!</p>
  
  <h3>What I've tried so far</h3>
  
  <p>I've experimented with my own function, modifying a simple algorithm I found <a href="http://www.tannerhelland.com/4743/simple-algorithm-correcting-lens-distortion/" rel="nofollow noreferrer">here</a>, but this seems to introduce a greater barrel distortion if anything (and the polarity of which does not seem to be able to be reversed):</p>
  
  <pre><code>undistortFun &lt;- function(X, Y, strength) {
  
      imWidth &lt;- 640
      imHeight &lt;- 480
  
      radius_u &lt;- sqrt(imWidth^2 + imHeight^2) / strength
  
      normX &lt;- X - (imWidth / 2)
      normY &lt;- Y - (imHeight / 2)
  
      distance &lt;- sqrt(normX^2 + normY^2)
      r &lt;- distance / radius_u
  
      theta &lt;- ifelse(r == 0, 1, atan(r) / r)
  
      newX &lt;- (imWidth / 2) + theta * normX
      newY &lt;- (imHeight / 2) + theta * normY
  
      return(data.frame(X = newX, Y = newY))
  
  }
  </code></pre>
  
  <h3>Similar questions</h3>
  
  <p>I found two similar questions, <a href="https://stackoverflow.com/questions/12620025/barrel-distortion-correction-algorithm-to-correct-fisheye-lens-failing-to-impl">here</a> and <a href="https://stackoverflow.com/questions/2477774/correcting-fisheye-distortion-programmatically">here</a>, but these are concerned with undistorting images rather than raw x,y coordinates, and are implemented in Java and C++, which I'm not familiar with.</p>