6

I am trying to implement cv::cuda::warpPerspective in python2, there is a very sweet post about how to do that here: link. I followed the instruction as described in that post, however, I got Segmentation fault (core dumped) error.

I was able to allocate the error in GpuWrapper.pyx file line 11:

pyopencv_to(<PyObject*> _src, src_mat)

It seems that it fails to convert numpy array to opencv Mat.

I am not sure where is wrong and how to fix it.

The python script that got Segmentation fault (core dumped) error is in below:

import cv2
import numpy as np
import csv
import timeit
import GpuWrapper

while (1):
    start = timeit.default_timer()
    eo_img = cv2.imread('./sample/eo.png', 1)
    nir_img = cv2.imread('./sample/nir.png', 0)
    with open('./sample/reg.csv', 'rb') as f:
        line = csv.reader(f)
        reg_line = list(line)
    reg = np.array(reg_line[0], dtype=np.float32)
    new_reg = reg.reshape((3,3))
    print nir_img.shape
    dist = GpuWrapper.cudaWarpPerspectiveWrapper(nir_img, new_reg, (2448,2048))
    cv2.imwrite('./sample/result.png', dist)
    end = timeit.default_timer()
    print end-start

Another thing to mention, when compiling cython code, it has some warnings:

[1/1] Cythonizing GpuWrapper.pyx
running build_ext
building 'GpuWrapper' extension
x86_64-linux-gnu-gcc -pthread -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fno-strict-aliasing -Wdate-time -D_FORTIFY_SOURCE=2 -g -fstack-protector-strong -Wformat -Werror=format-security -fPIC -I/home/xinyao/Tensorflow/local/lib/python2.7/site-packages/numpy/core/include -I-I/usr/local/include/opencv -I-I/usr/local/include -I/usr/include/python2.7 -c GpuWrapper.cpp -o build/temp.linux-x86_64-2.7/GpuWrapper.o
cc1plus: warning: command line option ‘-Wstrict-prototypes’ is valid for C/ObjC but not for C++
In file included from /home/xinyao/Tensorflow/local/lib/python2.7/site-packages/numpy/core/include/numpy/ndarraytypes.h:1809:0,
                 from /home/xinyao/Tensorflow/local/lib/python2.7/site-packages/numpy/core/include/numpy/ndarrayobject.h:18,
                 from pyopencv_converter.cpp:2,
                 from GpuWrapper.cpp:544:
/home/xinyao/Tensorflow/local/lib/python2.7/site-packages/numpy/core/include/numpy/npy_1_7_deprecated_api.h:15:2: warning: #warning "Using deprecated NumPy API, disable it by " "#defining NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION" [-Wcpp]
 #warning "Using deprecated NumPy API, disable it by " \
  ^
c++ -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-Bsymbolic-functions -Wl,-z,relro -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -Wdate-time -D_FORTIFY_SOURCE=2 -g -fstack-protector-strong -Wformat -Werror=format-security -Wl,-Bsymbolic-functions -Wl,-z,relro -Wdate-time -D_FORTIFY_SOURCE=2 -g -fstack-protector-strong -Wformat -Werror=format-security build/temp.linux-x86_64-2.7/GpuWrapper.o -o /home/xinyao/projects/image_reg/GpuWrapper.so -L/usr/local/lib -lopencv_cudabgsegm -lopencv_cudaobjdetect -lopencv_cudastereo -lopencv_dnn -lopencv_ml -lopencv_shape -lopencv_stitching -lopencv_cudafeatures2d -lopencv_superres -lopencv_cudacodec -lopencv_videostab -lopencv_cudaoptflow -lopencv_cudalegacy -lopencv_calib3d -lopencv_features2d -lopencv_highgui -lopencv_videoio -lopencv_photo -lopencv_imgcodecs -lopencv_cudawarping -lopencv_cudaimgproc -lopencv_cudafilters -lopencv_video -lopencv_objdetect -lopencv_imgproc -lopencv_flann -lopencv_cudaarithm -lopencv_viz -lopencv_core -lopencv_cudev

Which seems to be fine according to here.

Environment: CUDA 8.0 OpenCV 3.3 without extra modules Ubuntu 16.04 Python 2.7 Cython 0.26

I have tried cv::cuda::warpPerspective in C++ and it works fine with GPU support. I have also tried cv2.warpPerspective in python and without any issue(so my opencv for python was compiled correctly).

Another thing is I cannot compile opencv C++ code directly with g++, I need to add extra flags to do it, like in this way: g++ -o main main.cc `pkg-config opencv --cflags --libs Otherwise I will have issues on finding opencv:

main.cc:(.text+0x45): undefined reference to `cv::cuda::GpuMat::defaultAllocator()'
main.cc:(.text+0x9b): undefined reference to `cv::imread(cv::String const&, int)'
main.cc:(.text+0x104): undefined reference to `cv::imread(cv::String const&, int)'
main.cc:(.text+0x140): undefined reference to `cv::cuda::GpuMat::defaultAllocator()'
main.cc:(.text+0x1a5): undefined reference to `cv::Mat::eye(int, int, int)'
main.cc:(.text+0x31f): undefined reference to `cv::cuda::Stream::Null()'
main.cc:(.text+0x3d6): undefined reference to `cv::cuda::warpPerspective(cv::_InputArray const&, cv::_OutputArray const&, cv::_InputArray const&, cv::Size_<int>, int, int, cv::Scalar_<double>, cv::cuda::Stream&)'
main.cc:(.text+0x487): undefined reference to `cv::imwrite(cv::String const&, cv::_InputArray const&, std::vector<int, std::allocator<int> > const&)'

Not sure if that is a factor, but I am not able to fix it as well.

UPDATE: I was able to allocate the bug by using pdb:

>$gdb --args python opencv_reg_cuda.py
>$run

    Starting program: /usr/bin/python opencv_reg_cuda.py
    [Thread debugging using libthread_db enabled]
    Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
    [New Thread 0x7fffc6b83700 (LWP 10933)]
    [New Thread 0x7fffc4382700 (LWP 10934)]
    [New Thread 0x7fffc1b81700 (LWP 10935)]
    [New Thread 0x7fffc1380700 (LWP 10936)]
    [New Thread 0x7fffbcb7f700 (LWP 10937)]
    [New Thread 0x7fffba37e700 (LWP 10938)]
    [New Thread 0x7fffb7b7d700 (LWP 10939)]
    (2048, 2448)

    Thread 1 "python" received signal SIGSEGV, Segmentation fault.
    pyopencv_to (o=o@entry=0x7fffb37e3b70, m=..., info=...) at pyopencv_converter.cpp:210
    210     if( !PyArray_Check(o) )

>$bt

    #0  pyopencv_to (o=o@entry=0x7fffb37e3b70, m=..., info=...) at pyopencv_converter.cpp:210
    #1  0x00007fffb33c56f5 in pyopencv_to<cv::Mat> (name=0x7fffb33c98d8 "<unknown>", m=..., o=0x7fffb37e3b70) at pyopencv_converter.cpp:349
    #2  __pyx_pf_10GpuWrapper_cudaWarpPerspectiveWrapper (__pyx_v(short, long double, char)=__pyx_v(short, long double, char)@entry=0x7fffb37e3b70, __pyx_v__M=__pyx_v__M@entry=0x7fffb37e3c60, 
        __pyx_v__size_tuple=__pyx_v__size_tuple@entry=0x7ffff7e80b90, __pyx_v__flags=<optimized out>, __pyx_self=<optimized out>) at GpuWrapper.cpp:1796
    #3  0x00007fffb33c76a2 in __pyx_pw_10GpuWrapper_1cudaWarpPerspectiveWrapper (__pyx_self=<optimized out>, __pyx_args=<optimized out>, __pyx_kwds=<optimized out>) at GpuWrapper.cpp:1737
    #4  0x00000000004c468a in PyEval_EvalFrameEx ()
    #5  0x00000000004c2765 in PyEval_EvalCodeEx ()
    #6  0x00000000004c2509 in PyEval_EvalCode ()
    #7  0x00000000004f1def in ?? ()
    #8  0x00000000004ec652 in PyRun_FileExFlags ()
    #9  0x00000000004eae31 in PyRun_SimpleFileExFlags ()
    #10 0x000000000049e14a in Py_Main ()
    #11 0x00007ffff7810830 in __libc_start_main (main=0x49dab0 <main>, argc=2, argv=0x7fffffffde38, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffde28)
        at ../csu/libc-start.c:291
    #12 0x000000000049d9d9 in _start ()

>list

    205             }
    206         }
    207         return true;
    208     }
    209 
    210     if( !PyArray_Check(o) )
    211     {
    212         failmsg("%s is not a numpy array, neither a scalar", info.name);
    213         return false;
    214     }

It seems like it cannot pass o to PyArray_Check, but I have no idea what was going on and how to fix it.

1 Answer 1

4

Finally I found the answer. In order to use numpy, we have to call numpy.import_array(). For detail, see Here.

It can be tricky to find where to call it, for my case, I just call in my .pyx script:

import numpy as np  # Import Python functions, attributes, submodules of numpy
cimport numpy as np  # Import numpy C/C++ API

np.import_array()

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[0], <int> _size_tuple[1])

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

    # 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

Then everything is working like a magic.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.