Xin*_*ang 6 python opencv cython python-2.7
我正在尝试在 python2 中实现cv::cuda::warpPerspective,这里有一篇关于如何做到这一点的非常好的帖子:link。我按照该帖子中描述的说明进行操作,但是出现Segmentation fault (core dumped)错误。
我能够在GpuWrapper.pyx文件第 11 行中分配错误:
pyopencv_to(<PyObject*> _src, src_mat)\nRun Code Online (Sandbox Code Playgroud)\n\n似乎无法将 numpy 数组转换为 opencv Mat。
\n\n我不确定哪里出了问题以及如何修复。
\n\n出现错误的Python脚本Segmentation fault (core dumped)如下:
import cv2\nimport numpy as np\nimport csv\nimport timeit\nimport GpuWrapper\n\nwhile (1):\n start = timeit.default_timer()\n eo_img = cv2.imread(\'./sample/eo.png\', 1)\n nir_img = cv2.imread(\'./sample/nir.png\', 0)\n with open(\'./sample/reg.csv\', \'rb\') as f:\n line = csv.reader(f)\n reg_line = list(line)\n reg = np.array(reg_line[0], dtype=np.float32)\n new_reg = reg.reshape((3,3))\n print nir_img.shape\n dist = GpuWrapper.cudaWarpPerspectiveWrapper(nir_img, new_reg, (2448,2048))\n cv2.imwrite(\'./sample/result.png\', dist)\n end = timeit.default_timer()\n print end-start\nRun Code Online (Sandbox Code Playgroud)\n\n另外值得一提的是,在编译 cython 代码时,它有一些警告:
\n\n[1/1] Cythonizing GpuWrapper.pyx\nrunning build_ext\nbuilding \'GpuWrapper\' extension\nx86_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\ncc1plus: warning: command line option \xe2\x80\x98-Wstrict-prototypes\xe2\x80\x99 is valid for C/ObjC but not for C++\nIn file included from /home/xinyao/Tensorflow/local/lib/python2.7/site-packages/numpy/core/include/numpy/ndarraytypes.h:1809:0,\n from /home/xinyao/Tensorflow/local/lib/python2.7/site-packages/numpy/core/include/numpy/ndarrayobject.h:18,\n from pyopencv_converter.cpp:2,\n from GpuWrapper.cpp:544:\n/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]\n #warning "Using deprecated NumPy API, disable it by " \\\n ^\nc++ -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\nRun Code Online (Sandbox Code Playgroud)\n\n根据here似乎没问题。
\n\n环境:\nCUDA 8.0\nOpenCV 3.3,无额外模块\nUbuntu 16.04\nPython 2.7\nCython 0.26
\n\n我已经cv::cuda::warpPerspective在 C++ 中尝试过,并且在 GPU 支持下工作得很好。我也在cv2.warpPerspectivepython 中尝试过,没有任何问题(所以我的 python opencv 编译正确)。
另一件事是我无法直接用 g++ 编译 opencv C++ 代码,我需要添加额外的标志来做到这一点,就像这样:\n g++ -o main main.cc `pkg-config opencv --cflags --libs\n否则我在查找 opencv 时会遇到问题:
main.cc:(.text+0x45): undefined reference to `cv::cuda::GpuMat::defaultAllocator()\'\nmain.cc:(.text+0x9b): undefined reference to `cv::imread(cv::String const&, int)\'\nmain.cc:(.text+0x104): undefined reference to `cv::imread(cv::String const&, int)\'\nmain.cc:(.text+0x140): undefined reference to `cv::cuda::GpuMat::defaultAllocator()\'\nmain.cc:(.text+0x1a5): undefined reference to `cv::Mat::eye(int, int, int)\'\nmain.cc:(.text+0x31f): undefined reference to `cv::cuda::Stream::Null()\'\nmain.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&)\'\nmain.cc:(.text+0x487): undefined reference to `cv::imwrite(cv::String const&, cv::_InputArray const&, std::vector<int, std::allocator<int> > const&)\'\nRun Code Online (Sandbox Code Playgroud)\n\n不确定这是否是一个因素,但我也无法解决它。
\n\n更新: \n我能够使用 pdb 来分配错误:
\n\n>$gdb --args python opencv_reg_cuda.py\n>$run\n\n Starting program: /usr/bin/python opencv_reg_cuda.py\n [Thread debugging using libthread_db enabled]\n Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".\n [New Thread 0x7fffc6b83700 (LWP 10933)]\n [New Thread 0x7fffc4382700 (LWP 10934)]\n [New Thread 0x7fffc1b81700 (LWP 10935)]\n [New Thread 0x7fffc1380700 (LWP 10936)]\n [New Thread 0x7fffbcb7f700 (LWP 10937)]\n [New Thread 0x7fffba37e700 (LWP 10938)]\n [New Thread 0x7fffb7b7d700 (LWP 10939)]\n (2048, 2448)\n\n Thread 1 "python" received signal SIGSEGV, Segmentation fault.\n pyopencv_to (o=o@entry=0x7fffb37e3b70, m=..., info=...) at pyopencv_converter.cpp:210\n 210 if( !PyArray_Check(o) )\n\n>$bt\n\n #0 pyopencv_to (o=o@entry=0x7fffb37e3b70, m=..., info=...) at pyopencv_converter.cpp:210\n #1 0x00007fffb33c56f5 in pyopencv_to<cv::Mat> (name=0x7fffb33c98d8 "<unknown>", m=..., o=0x7fffb37e3b70) at pyopencv_converter.cpp:349\n #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, \n __pyx_v__size_tuple=__pyx_v__size_tuple@entry=0x7ffff7e80b90, __pyx_v__flags=<optimized out>, __pyx_self=<optimized out>) at GpuWrapper.cpp:1796\n #3 0x00007fffb33c76a2 in __pyx_pw_10GpuWrapper_1cudaWarpPerspectiveWrapper (__pyx_self=<optimized out>, __pyx_args=<optimized out>, __pyx_kwds=<optimized out>) at GpuWrapper.cpp:1737\n #4 0x00000000004c468a in PyEval_EvalFrameEx ()\n #5 0x00000000004c2765 in PyEval_EvalCodeEx ()\n #6 0x00000000004c2509 in PyEval_EvalCode ()\n #7 0x00000000004f1def in ?? ()\n #8 0x00000000004ec652 in PyRun_FileExFlags ()\n #9 0x00000000004eae31 in PyRun_SimpleFileExFlags ()\n #10 0x000000000049e14a in Py_Main ()\n #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)\n at ../csu/libc-start.c:291\n #12 0x000000000049d9d9 in _start ()\n\n>list\n\n 205 }\n 206 }\n 207 return true;\n 208 }\n 209 \n 210 if( !PyArray_Check(o) )\n 211 {\n 212 failmsg("%s is not a numpy array, neither a scalar", info.name);\n 213 return false;\n 214 }\nRun Code Online (Sandbox Code Playgroud)\n\n似乎它无法将 o 传递给 PyArray_Check,但我不知道发生了什么以及如何修复它。
\n最后我找到了答案。为了使用 numpy,我们必须调用numpy.import_array(). 详细信息请参见此处。
找到在哪里调用它可能很棘手,对于我的情况,我只是调用我的 .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
Run Code Online (Sandbox Code Playgroud)
然后一切都像魔术一样运作。