title: What are the inaccuracies of this 'inverse map' function in OpenCV?
body: <p>I am trying to horizontally stretch an image in a very specific way. Each x prime coordinate should follow a tangent path with respect to the original x coordinate. I believe there are two ways to do this:</p>
  <ol>
  <li>Inverse the tangent function and map it normally</li>
  <li>Map the tangent function and then inverse the mapping</li>
  </ol>
  <p>Using <a href="https://stackoverflow.com/questions/41703210/inverting-a-real-valued-index-grid/68706787#68706787">this</a> answer for map inversion, Im trying to figure out why the two images are not the same. I know that the first method gives me the correct image that I'm looking for, so why doesnt the second method work? Is it because of the &quot;limited precision&quot; that @ChristophRackwitz commented on the answer?</p>
  <pre><code>import cv2
  import glob
  import numpy as np
  import math
  
  A = -1010
  B = -3.931
  C = 5.258
  D = 978.3
  
  M = -193.8
  N = 1740
  
  def get_tan_func_value(x):
      return A * math.tan((((x-N)/M)+B)/C) + D
  
  def get_inverse_tan_func_value(x):
      return M * (C*math.atan((x-D)/A) - B) + N
  
  # answer from linked post
  def invert_map(F, shape):
      I = np.zeros_like(F)
      I[:,:,1], I[:,:,0] = np.indices(shape)
      P = np.copy(I)
      for i in range(10):
          P += I - cv2.remap(F, P, None, interpolation=cv2.INTER_LINEAR)
      return P
  
  # import image
  images = glob.glob('*.jpg')
  img = cv2.imread(images[0])
  h,  w = img.shape[:2]
  
  map_x_tan = np.zeros((img.shape[0], img.shape[1]), dtype=np.float32)
  map_x_inverse_tan = np.zeros((img.shape[0], img.shape[1]), dtype=np.float32)
  map_y = np.zeros((img.shape[0], img.shape[1]), dtype=np.float32)
  
  # x tan function map
  for i in range(map_x_tan.shape[0]):
      map_x_tan[i,:] = [get_tan_func_value(x) for x in range(map_x_tan.shape[1])]
  
  # x inverse tan function map
  for i in range(map_x_inverse_tan.shape[0]):
      map_x_inverse_tan[i,:] = [get_inverse_tan_func_value(x) for x in range(map_x_inverse_tan.shape[1])]
  
  # default y map
  for j in range(map_y.shape[1]):              
      map_y[:,j] = [y for y in range(map_y.shape[0])]
  
  # convert x tan map to 2 channel (x,y) map
  (xymap_tan, _) = cv2.convertMaps(map1=map_x_tan, map2=map_y, dstmap1type=cv2.CV_32FC2)
  
  # invert the 2 channel x tan map
  xymap_inverted = invert_map(xymap_tan, (h,w))
  
  # remap and write the target image (inverse tan function with normal map)
  target = cv2.remap(img, map_x_inverse_tan, map_y, cv2.INTER_LINEAR)
  cv2.imwrite(&quot;target.jpg&quot;, target)
  
  # remap and write the attempted image (normal tan function with inverted map) 
  attempt = cv2.remap(img, xymap_inverted, None, cv2.INTER_LINEAR)
  cv2.imwrite(&quot;attempt.jpg&quot;, attempt)
  </code></pre>
  <p>Method 1: Target Image
  <a href="https://i.stack.imgur.com/01EF0.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/01EF0.jpg" alt="target" /></a></p>
  <p>Method 2: Attempt Image
  <a href="https://i.stack.imgur.com/0IpUz.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/0IpUz.jpg" alt="attempt" /></a></p>
  <p>The results show that the attempt (normal tan function with inverted map) has less stretching near the edges of the image than expected. Almost everywhere else on the images are identical except the edges. I did not post the original picture to save space.</p>