2017-08-23 1 views
2

J'essaye d'implémenter cv::cuda::warpPerspective dans python2, il y a un très bon post sur comment faire ça ici: link. J'ai suivi les instructions décrites dans ce message, cependant, j'ai eu une erreur Segmentation fault (core dumped).Impossible de convertir le tableau Numpy en OpenCV Mat en Cython en essayant d'écrire la fonction C++ wrapper (Mis à jour)

j'ai pu affecter l'erreur dans la ligne de fichier GpuWrapper.pyx 11:

pyopencv_to(<PyObject*> _src, src_mat) 

Il semble qu'il ne parvient pas à convertir tableau numpy à OpenCV Mat.

Je ne sais pas où est le problème et comment le réparer.

Le script python qui a obtenu l'erreur Segmentation fault (core dumped) est en dessous:

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 

Une autre chose à mentionner, lors de la compilation du code de cython, il a quelques avertissements:

[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 

qui semble être bien selon à here.

Environnement: CUDA 8.0 OpenCV 3.3 sans modules supplémentaires Ubuntu 16.04 Python 2.7 Cython 0,26

J'ai essayé cv::cuda::warpPerspective en C++ et il fonctionne très bien avec le soutien du GPU. J'ai aussi essayé cv2.warpPerspective en python et sans aucun problème (donc mon opencv pour python a été compilé correctement).

Une autre chose est que je ne peux pas compiler le code OpenCV C++ directement avec g ++, je dois ajouter des indicateurs supplémentaires pour le faire, comme de cette façon: g++ -o main main.cc `pkg-config opencv --cflags --libs Sinon, je vais avoir des problèmes sur la recherche 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&)' 

Je ne sais pas si c'est un facteur, mais je ne suis pas capable de le réparer aussi.

Toute aide sera vraiment appréciée.

MISE À JOUR: j'ai pu affecter le bug en utilisant 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 ([email protected]=0x7fffb37e3b70, m=..., info=...) at pyopencv_converter.cpp:210 
    210  if(!PyArray_Check(o)) 

>$bt 

    #0 pyopencv_to ([email protected]=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, [email protected]=0x7fffb37e3c60, 
     [email protected]=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  } 

Il semble que il ne peut pas passer o PyArray_Check, mais je ne sais pas ce qui se passait et comment fixer il.

Répondre

1

Enfin j'ai trouvé la réponse. Pour utiliser numpy, nous devons appeler numpy.import_array(). Pour plus de détails, voir Here.

Il peut être difficile de trouver où l'appeler, pour mon cas, je viens d'appeler mon script .pyx:

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 

Ensuite, tout fonctionne comme une magie.