AlessandroS
AlessandroS

Reputation: 63

Implementing from scratch cv2.warpPerspective()

I was making some experimentations with the OpenCV function cv2.warpPerspective when I decided to code it from scratch to better understand its pipeline. Though I followed (hopefully) every theoretical step, it seems I am still missing something and I am struggling a lot to understand what. Could you please help me?

SRC image (left) and True DST Image (right)

Output of the cv2.warpPerspective overlapped on the True DST

# Invert the homography SRC->DST to DST->SRC
hinv = np.linalg.inv(h)
src = gray1
dst = np.zeros(gray2.shape)
h, w = src.shape

# Remap back and check the domain
for ox in range(h):
    for oy in range(w):

        # Backproject from DST to SRC
        xw, yw, w = hinv.dot(np.array([ox, oy, 1]).T)

        # cv2.INTER_NEAREST
        x, y = int(xw/w), int(yw/w)

        # Check if it falls in the src domain
        c1 = x >= 0 and y < h
        c2 = y >= 0 and y < w

        if c1 and c2:
            dst[x, y] = src[ox, oy]

cv2.imshow(dst + gray2//2)

Output of my code

PS: The output images are the overlapping of Estimated DST and the True DST to better highlight differences.

Upvotes: 6

Views: 1344

Answers (2)

code_messiah
code_messiah

Reputation: 1

This is a working sample code with minor modifications and typo fixes from the OP following the suggestions of @Christoph for anyone interested.

src_img = post_img
dst = np.zeros(src_img.shape)
height, width = src_img.shape

for ox in range(height):
    for oy in range(width):
        xw, yw, w = homography_matrix.dot(np.array([ox, oy, 1]).T)

        tx, ty = int(xw / w), int(yw / w)

        # Check if it falls in the src domain
        c1 = tx >= 0 and tx < height
        c2 = ty >= 0 and ty < width

        if c1 and c2:
            dst[ty, tx] = src_img[oy, ox]

The homography_matrix was calculated using the OpenCV function cv2.findHomography

Upvotes: 0

Christoph Rackwitz
Christoph Rackwitz

Reputation: 15354

Your issue amounts to a typo. You mixed up the naming of your coordinates. The homography assumes (x,y,1) order, which would correspond to (j,i,1).

Just use (x, y, 1) in the calculation, and (xw, yw, w) in the result of that (then x,y = xw/w, yw/w). the w factor mirrors the math, when formulated properly.

Avoid indexing into .shape. The indices don't "speak". Just do (height, width) = src.shape[:2] and use those.

I'd recommend to fix the naming scheme, or define it up top in a comment. I'd recommend sticking with x,y instead of i,j,u,v, and then extend those with prefixes/suffixes for the space they're in ("src/dst/in/out"). Perhaps something like ox,oy for iterating, just xw,yw,w for the homography result, which turns into x,y via division, and ix,iy (integerized) for sampling in the input? Then you can use dst[oy, ox] = src[iy, ix]

Upvotes: 4

Related Questions