Search code examples
image-processingopencvemgucv

cvRemap to replace cvWarpPerspective


Below transformation is what I want to do.

For each tile in source image, I know the coordinate of each corner, and I know the coordinate of each corresponding corner in the output image, so I can call cvWarpPerspective to warp each tile and then connect the quadrangles together to get the final output image.

Can cvRemap do this in one transformation? If yes, how do I construct the map (mapx, and mapy) from the coordinate that I have so to pass to the cvRemap function? I've searched the EmguCV documentation but could not find a cvRemap example.

The source image

The output image


Solution

  • I have no experience with emgu (actually I have a low esteem for it) but I can explain about remap and warpPerspective. It may help you find the corresponding functions in emgu.

    remap takes an input picture, and a coordinate relocation map, and applies it to the output. The map stores info like this: take pixel (1, 4) and move it to (3, 5). The pixels that are not defined in the map are filled with 0, or other value, depending on the extra parameters. Note that it also uses some interpolation for smooth results.

    warpPerspective takes a geometric perspective transform, calculates internally the map for the transform, and then calls remap() to apply it to the input. Actually, many functions in OpenCV use remap, or can use it. warpAffine, lens correction, and others build their custom maps, then call remap to apply them.

    The perspective transform is defined by a 3.3 matrix H. So, each coordinate in the input image will be shifted according to the H matrix:

                [ h11 h12 h13 ]    [ x ]
    [x' y' 1] = [ h21 h22 h23 ] *  [ y ]
                [ h31 h32 h33 ]    [ 1 ]
    

    warpPerspective applies the inverse transform for each point in the destination image, to find out where in the source image is the pixel that should be moved in, and stores that info in the map.

    You can take that code and make a custom function in your app, but I do not know how easy is to do it in C#. C++ would have been a piece of cake.

    Final note: I have used the term map, although there are two map parameters in the remap() function. And to be more confusing, they can have completely different meanings.

    • First valid combination is where mapx contains the coordinate transforms of the x coordinate, in a width-by-height image, one channel. mapy is the corresponding map for y dimension. The coordinates are floating-point values, reflecting the fact that coordinate transforms from one image to another do not map exactly to integer values. By example, pixel (2, 5) may map to (3.456, 7.293)

    • second possibility is to store the integer coordinates in mapx, for both x, and y, in two channels, and keep an interpolation weights table in the second parameter, mapy. It is usually far easier to generate the first format, however the second is faster to process. To understand the sencod format you should read the OpenCV sources, because it's not documented anywere.