Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

CUDA Warp Perspective - Improving Accuracy

I am writing a Python program with Cython bindings to OpenCV. I am trying to substitute a cv::warpPerspective(...) call with a cv::cuda::warpPerspective(...) call. However, when I compare the results of the two methods, I am getting very poor accuracy.

0.362847222222
0.328125
0.671875
0.725694444444
0.394097222222
0.505208333333
0.559027777778
0.350694444444
0.34375
0.371527777778
0.373263888889

Is there a way for me to improve the accuracy? I am rather sure that my Cython bindings are proper (I compared my Cython binding to OpenCV's Python binding for cv::warpPerspective, and they return identical results):

def cudaWarpPerspectiveWrapper(np.ndarray[np.uint8_t, ndim=2] _src,
                               np.ndarray[np.float32_t, ndim=2] _M,
                               _size_tuple,
                               int _flags=INTER_NEAREST):
    # Create GPU/device InputArray for src
    cdef Mat src_mat
    cdef GpuMat src_gpu
    pyopencv_to(<PyObject*> _src, src_mat)
    src_gpu.upload(src_mat)

    # Create CPU/host InputArray for M
    cdef Mat M_mat = Mat()
    pyopencv_to(<PyObject*> _M, M_mat)

    # Create Size object from size tuple
    # Note that size/shape in Python is handled in row-major-order -- therefore, width is [1] and height is [0]
    cdef Size size = Size(<int> _size_tuple[1], <int> _size_tuple[0])

    # Create empty GPU/device OutputArray for dst
    cdef GpuMat dst_gpu = GpuMat()
    warpPerspective(src_gpu, dst_gpu, M_mat, size, _flags)

    # Get result of dst
    cdef Mat dst_host
    dst_gpu.download(dst_host)
    cdef np.ndarray out = <np.ndarray> pyopencv_from(dst_host)
    return out

def warpPerspectiveWrapper(np.ndarray[np.uint8_t, ndim=2] _src,
                               np.ndarray[np.float32_t, ndim=2] _M,
                               _size_tuple,
                               int _flags=INTER_NEAREST):
    # Create GPU/device InputArray for src
    cdef Mat src_mat = Mat()
    pyopencv_to(<PyObject*> _src, src_mat)

    # Create CPU/host InputArray for M
    cdef Mat M_mat = Mat()
    pyopencv_to(<PyObject*> _M, M_mat)

    # Create Size object from size tuple
    # Note that size/shape in Python is handled in row-major-order -- therefore, width is [1] and height is [0]
    cdef Size size = Size(<int> _size_tuple[1], <int> _size_tuple[0])

    # Create empty GPU/device OutputArray for dst
    cdef Mat dst_mat = Mat()
    warpPerspective(src_mat, dst_mat, M_mat, size, _flags)

    # Get result of dst
    cdef np.ndarray out = <np.ndarray> pyopencv_from(dst_mat)
    return out

CUDA Warp Perspective - Improving Accuracy

I am writing a Python program with Cython bindings to OpenCV. I am trying to substitute a cv::warpPerspective(...) call with a cv::cuda::warpPerspective(...) call. However, when I compare the results of the two methods, I am getting very poor accuracy.accuracy (some accuracies from multiple test photos follows below).

0.362847222222
0.328125
0.671875
0.725694444444
0.394097222222
0.505208333333
0.559027777778
0.350694444444
0.34375
0.371527777778
0.373263888889

Is there a way for me to improve the accuracy? I am rather sure that my Cython bindings are proper (I compared my Cython binding to OpenCV's Python binding for cv::warpPerspective, and they return identical results):

def cudaWarpPerspectiveWrapper(np.ndarray[np.uint8_t, ndim=2] _src,
                               np.ndarray[np.float32_t, ndim=2] _M,
                               _size_tuple,
                               int _flags=INTER_NEAREST):
    # Create GPU/device InputArray for src
    cdef Mat src_mat
    cdef GpuMat src_gpu
    pyopencv_to(<PyObject*> _src, src_mat)
    src_gpu.upload(src_mat)

    # Create CPU/host InputArray for M
    cdef Mat M_mat = Mat()
    pyopencv_to(<PyObject*> _M, M_mat)

    # Create Size object from size tuple
    # Note that size/shape in Python is handled in row-major-order -- therefore, width is [1] and height is [0]
    cdef Size size = Size(<int> _size_tuple[1], <int> _size_tuple[0])

    # Create empty GPU/device OutputArray for dst
    cdef GpuMat dst_gpu = GpuMat()
    warpPerspective(src_gpu, dst_gpu, M_mat, size, _flags)

    # Get result of dst
    cdef Mat dst_host
    dst_gpu.download(dst_host)
    cdef np.ndarray out = <np.ndarray> pyopencv_from(dst_host)
    return out

def warpPerspectiveWrapper(np.ndarray[np.uint8_t, ndim=2] _src,
                               np.ndarray[np.float32_t, ndim=2] _M,
                               _size_tuple,
                               int _flags=INTER_NEAREST):
    # Create GPU/device InputArray for src
    cdef Mat src_mat = Mat()
    pyopencv_to(<PyObject*> _src, src_mat)

    # Create CPU/host InputArray for M
    cdef Mat M_mat = Mat()
    pyopencv_to(<PyObject*> _M, M_mat)

    # Create Size object from size tuple
    # Note that size/shape in Python is handled in row-major-order -- therefore, width is [1] and height is [0]
    cdef Size size = Size(<int> _size_tuple[1], <int> _size_tuple[0])

    # Create empty GPU/device OutputArray for dst
    cdef Mat dst_mat = Mat()
    warpPerspective(src_mat, dst_mat, M_mat, size, _flags)

    # Get result of dst
    cdef np.ndarray out = <np.ndarray> pyopencv_from(dst_mat)
    return out