0

Attempting to do forward warping of a homography matrix in OpenCV. You don't have to know what that means to understand the issue though.

Assume there are 2 images (an image is a 2D Numpy array of pixel values), A and B, and an array match that looks like

[[  6.96122642e+01  -1.06556338e+03   1.02251944e+00] 
 [  6.92265938e+01  -1.06334423e+03   1.02246589e+00]
 [  6.88409234e+01  -1.06112508e+03   1.02241234e+00]
 ... ]

The first column is X, second Y, and third is a scalar. These XY values are image A pixel indices and correspond to the imageB indexes

[[0,0], 
 [0,1], 
 [0,2]
 ... ]

I want to use this info to quickly set imageB values from imageA. I have this working but it is not as fast as I'd like

yAs = np.int32(np.round( match[:, 0] / match[:, 2] )
xAs = np.int32(np.round( match[:, 1] / match[:, 2] )
it = np.nditer(pixelsImageB[0], flags=['f_index'])
while not it.finished:
    i = it.index    
    xA = xAs[i]
    yA = yAs[i] 
    if in_bounds(xA, yA, imageA):
        yB = pixB[0][i]
        xB = pixB[1][i] 
        imageB[xB,yB] = imageA[xA,yA]

    it.iternext()

But I'm not sure how to make this fast in Numpy, naively doing this loop is very slow. I'm a total scrub at advanced indexing, broadcasting, and the like. Any ideas?

James L.
  • 12,893
  • 4
  • 49
  • 60

1 Answers1

1

The fastest way would be to not reinvent the wheel and use cv.WarpPerspective function.

Alternatively, you can use Pillow Image.transform method which according to docs has slight advantage over OpenCV in that it also supports bicubic interpolation, which should produce output of better quality.

lomereiter
  • 356
  • 1
  • 5
  • Absolutely this is the best option if you actually want to get stuff done. I'm implementing it just to learn how it works and was hoping to learn a bit about Numpy here too – James L. Oct 01 '17 at 15:52
  • Ok, then 1) you move the condition (in_bounds) outside the loop by creating a mask: just replace x/y in the expression you wrote with xAs and yAs, save it into a mask variable; 2) then do the broadcasting simply like this: imageB[pixB[1, mask], pixB[0, mask]] = imageA[xAs[mask], yAs[mask]] – lomereiter Oct 01 '17 at 17:20