meiqua / shape_based_matching

try to implement halcon shape based matching, refer to machine vision algorithms and applications, page 317 3.11.5, written by halcon engineers
BSD 2-Clause "Simplified" License
1.24k stars 481 forks source link

MacOS Python 使用问题 #97

Closed lih627 closed 4 years ago

lih627 commented 4 years ago

我只有一台 Mac 设备,想要尝试将用您的算法检测广告标志. 在编译的过程中遇到了一些问题.

我通过homebrew 按照了openv4, 然后按照您的教程编译(修改了 CMakeList 里面指定的版本), make的时候遇到了这个问题

clang: error: unsupported option '-fopenmp'
make[2]: *** [CMakeFiles/shape_based_matching_py.dir/line2Dup.cpp.o] Error 1
make[1]: *** [CMakeFiles/shape_based_matching_py.dir/all] Error 2

按照这个教程, Enable OpenMP support in clang in Mac OS X (sierra & Mojave)

MacOS Mojave with CMake

  1. Install LLVM with openmp and libomp with brew
 brew update
 brew install llvm libomp
  1. add include directories and link directories in CMakeList.txt
    include_directories("/usr/local/include" "/usr/local/opt/llvm/include")
    link_directories("/usr/local/lib" "/usr/local/opt/llvm/lib")
  2. run CMake with the new compilers
    cmake -DCMAKE_C_COMPILER="/usr/local/opt/llvm/bin/clang" -DCMAKE_CXX_COMPILER="/usr/local/opt/llvm/bin/clang++" ..

    The clang version is 7.0.1 at time of writing

修改后仍然会遇到错误, make的时候错误信息如下

[ 42%] Building CXX object CMakeFiles/shape_based_matching_py.dir/pybind11/np2mat/ndarray_converter.cpp.o
/Users/lihao/Code/shape_based_matching-python_binding/pybind11/np2mat/ndarray_converter.cpp:92:15: warning: 
      'NumpyAllocator::allocate' hides overloaded virtual functions
      [-Woverloaded-virtual]
    UMatData* allocate(PyObject* o, int dims, const int* sizes, int type...
              ^
/usr/local/Cellar/opencv/4.4.0/include/opencv4/opencv2/core/mat.hpp:475:23: note: 
      hidden overloaded virtual function 'cv::MatAllocator::allocate' declared
      here: different number of parameters (7 vs 5)
    virtual UMatData* allocate(int dims, const int* sizes, int type,
                      ^
/usr/local/Cellar/opencv/4.4.0/include/opencv4/opencv2/core/mat.hpp:477:18: note: 
      hidden overloaded virtual function 'cv::MatAllocator::allocate' declared
      here: different number of parameters (3 vs 5)
    virtual bool allocate(UMatData* data, AccessFlag accessflags, UMatUs...
                 ^
/Users/lihao/Code/shape_based_matching-python_binding/pybind11/np2mat/ndarray_converter.cpp:105:15: warning: 
      'NumpyAllocator::allocate' hides overloaded virtual functions
      [-Woverloaded-virtual]
    UMatData* allocate(int dims0, const int* sizes, int type, void* data...
              ^
/usr/local/Cellar/opencv/4.4.0/include/opencv4/opencv2/core/mat.hpp:475:23: note: 
      hidden overloaded virtual function 'cv::MatAllocator::allocate' declared
      here: type mismatch at 6th parameter ('cv::AccessFlag' vs 'int')
    virtual UMatData* allocate(int dims, const int* sizes, int type,
                      ^
/usr/local/Cellar/opencv/4.4.0/include/opencv4/opencv2/core/mat.hpp:477:18: note: 
      hidden overloaded virtual function 'cv::MatAllocator::allocate' declared
      here: different number of parameters (3 vs 7)
    virtual bool allocate(UMatData* data, AccessFlag accessflags, UMatUs...
                 ^
/Users/lihao/Code/shape_based_matching-python_binding/pybind11/np2mat/ndarray_converter.cpp:134:10: warning: 
      'NumpyAllocator::allocate' hides overloaded virtual functions
      [-Woverloaded-virtual]
    bool allocate(UMatData* u, int accessFlags, UMatUsageFlags usageFlags) const
         ^
/usr/local/Cellar/opencv/4.4.0/include/opencv4/opencv2/core/mat.hpp:475:23: note: 
      hidden overloaded virtual function 'cv::MatAllocator::allocate' declared
      here: different number of parameters (7 vs 3)
    virtual UMatData* allocate(int dims, const int* sizes, int type,
                      ^
/usr/local/Cellar/opencv/4.4.0/include/opencv4/opencv2/core/mat.hpp:477:18: note: 
      hidden overloaded virtual function 'cv::MatAllocator::allocate' declared
      here: type mismatch at 2nd parameter ('cv::AccessFlag' vs 'int')
    virtual bool allocate(UMatData* data, AccessFlag accessflags, UMatUs...
                 ^
/Users/lihao/Code/shape_based_matching-python_binding/pybind11/np2mat/ndarray_converter.cpp:111:34: error: 
      no matching member function for call to 'allocate'
            return stdAllocator->allocate(dims0, sizes, type, data, step...
                   ~~~~~~~~~~~~~~^~~~~~~~
/usr/local/Cellar/opencv/4.4.0/include/opencv4/opencv2/core/mat.hpp:475:23: note: 
      candidate function not viable: no known conversion from 'int' to
      'cv::AccessFlag' for 6th argument
    virtual UMatData* allocate(int dims, const int* sizes, int type,
                      ^
/usr/local/Cellar/opencv/4.4.0/include/opencv4/opencv2/core/mat.hpp:477:18: note: 
      candidate function not viable: requires 3 arguments, but 7 were provided
    virtual bool allocate(UMatData* data, AccessFlag accessflags, UMatUs...
                 ^
/Users/lihao/Code/shape_based_matching-python_binding/pybind11/np2mat/ndarray_converter.cpp:136:30: error: 
      no matching member function for call to 'allocate'
        return stdAllocator->allocate(u, accessFlags, usageFlags);
               ~~~~~~~~~~~~~~^~~~~~~~
/usr/local/Cellar/opencv/4.4.0/include/opencv4/opencv2/core/mat.hpp:477:18: note: 
      candidate function not viable: no known conversion from 'int' to
      'cv::AccessFlag' for 2nd argument
    virtual bool allocate(UMatData* data, AccessFlag accessflags, UMatUs...
                 ^
/usr/local/Cellar/opencv/4.4.0/include/opencv4/opencv2/core/mat.hpp:475:23: note: 
      candidate function not viable: requires 7 arguments, but 3 were provided
    virtual UMatData* allocate(int dims, const int* sizes, int type,
                      ^
/Users/lihao/Code/shape_based_matching-python_binding/pybind11/np2mat/ndarray_converter.cpp:157:16: error: 
      variable type 'NumpyAllocator' is an abstract class
NumpyAllocator g_numpyAllocator;
               ^
/usr/local/Cellar/opencv/4.4.0/include/opencv4/opencv2/core/mat.hpp:475:23: note: 
      unimplemented pure virtual method 'allocate' in 'NumpyAllocator'
    virtual UMatData* allocate(int dims, const int* sizes, int type,
                      ^
/usr/local/Cellar/opencv/4.4.0/include/opencv4/opencv2/core/mat.hpp:477:18: note: 
      unimplemented pure virtual method 'allocate' in 'NumpyAllocator'
    virtual bool allocate(UMatData* data, AccessFlag accessflags, UMatUs...
                 ^
3 warnings and 3 errors generated.
make[2]: *** [CMakeFiles/shape_based_matching_py.dir/pybind11/np2mat/ndarray_converter.cpp.o] Error 1
make[1]: *** [CMakeFiles/shape_based_matching_py.dir/all] Error 2
make: *** [all] Error 2

请问有办法解决吗?

lih627 commented 4 years ago

查了一下可能是 opencv4版本过高, 需要安装 opencv3

brew install opencv@3

然后 cmakelist.txt 里面需要在开头加一行, 大致的路径是这样子的:

set(OpenCV_DIR /usr/local/Cellar/opencv@3/3.4.10_4/share/OpenCV)
meiqua commented 4 years ago

是的,pybind11绑cv::mat还没在opencv4上测过

lih627 commented 4 years ago

@meiqua 嗯嗯我私信你了. 我总结下, macOS 安装的流程是这样的. 就安装成功了.. 明天我试着使用新环境走一遍流程再确认下

pip install opencv-python
pip install pybind11
pip install ./
lih627 commented 4 years ago

@meiqua 今天完整走了一边流程, 安装成功了~总结了一下MacOS的安装方法,方面后面踩坑的人。

  1. 先创建python3虚拟环境smatch,我用的版本是python=3.6并进入:
# create conda env
conda create -n smatch python=3.6
source activate smatch
  1. 通过homebrew安装opencv@3。这里千万注意不要写成opencv3 因为opencv3对应的版本是opencv4,命令执行结束后,会安装在/usr/local/Cellar/opencv@3里面。
brew install opencv@3 
  1. 安装结束后,需要让虚拟环境中的python能够访问到cv2 cv2.so文件在第二步已经存在了,在我的电脑上的位置在下面这个路径/usr/local/Cellar/opencv@3/3.4.10_4/lib/python3.8/site-packages/cv2/python-3.8/cv2.cpython-38-darwin.so 需要把它放到虚拟环境python的site-packages, 操作如下。此时测试虚拟环境下的python导入cv2正常
    # 切换目录到 homebrew opencv-python下面 cv2.cpython-38-darwin.so存在于此
    cd /usr/local/Cellar/opencv@3/3.4.10_4/lib/python3.8/site-packages/cv2/python-3.8
    # 复制到虚拟环境下面
    cp cv2.cpython-38-darwin.so cv2.so
    cp cv2.so /Users/lihao/anaconda3/envs/smatch/lib/python3.6/site-packages 

复制完毕测试一下cv2能否正常使用

(smatch) ➜  site-packages python
Python 3.6.10 |Anaconda, Inc.| (default, May  7 2020, 23:06:31) 
[GCC 4.2.1 Compatible Clang 4.0.1 (tags/RELEASE_401/final)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import cv2
>>> cv2.__version__
'3.4.10'
  1. 修改CMakeLists.txt这个文件,设定OpenCV_DIR包含brew安装的OpenCVConfig.cmakeopencv-config.cmake这两个文件, 因此在CMakeLists.txt文件中加上这一行

    # CMakeLists.txt
    # opencv
    # 加入OpenCV_DIR
    set(OpenCV_DIR /usr/local/Cellar/opencv@3/3.4.10_4/share/OpenCV)
    set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} /opt/ros/kinetic)
    find_package(OpenCV 3 REQUIRED)
    include_directories(${OpenCV_INCLUDE_DIRS})
  2. 安装Pybind11 brew install pybind11

  3. 修改CMakeLists.txt这个文件, 我查了一下 MacOS 的 gcc 是 clang, 我不会cpp,需要去掉-fopenmp这个选项

    这是修改后的文件

    cmake_minimum_required(VERSION 2.8)
    set (CMAKE_CXX_STANDARD 14)
    project(shape_based_matching)
    
    OPTION(USE_PYBIND "Enable pybind" ON)
    
    # debug or release
    SET(CMAKE_BUILD_TYPE "Release")
    
    # arm or x86
    IF(${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm")
        SET(PLATFORM_COMPILE_FLAGS "-mfpu=neon")
    ELSE()
        SET(PLATFORM_COMPILE_FLAGS "-march=native")
    
        # some places of the algorithm are designed for 128 SIMD
        # so 128 SSE may slightly faster than 256 AVX, you may want this
    #    SET(PLATFORM_COMPILE_FLAGS "-msse -msse2 -msse3 -msse4 -mssse3")  # SSE only
    ENDIF()
    
    # SET(PLATFORM_COMPILE_FLAGS "-DMIPP_NO_INTRINSICS")  # close SIMD
    # 修改这一行 
    #SET(COMMON_COMPILE_FLAGS "-fopenmp -Wall -Wno-sign-compare")
    # 去掉 -fopenmp
    SET(COMMON_COMPILE_FLAGS "-Wall -Wno-sign-compare")
    SET(CMAKE_CXX_FLAGS "${PLATFORM_COMPILE_FLAGS} ${COMMON_COMPILE_FLAGS} $ENV{CXXFLAGS}")
    SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g2 -ggdb")
    SET(CMAKE_CXX_FLAGS_RELEASE "-O3")
    
    # opencv
    # 加入OpenCV_DIR 改成自己的路径
    set(OpenCV_DIR /usr/local/Cellar/opencv@3/3.4.10_4/share/OpenCV)
    set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} /opt/ros/kinetic)
    find_package(OpenCV 3 REQUIRED)
    include_directories(${OpenCV_INCLUDE_DIRS})
    
    # include MIPP headers
    include_directories (${INCLUDE_DIRECTORIES} 
        ${PROJECT_SOURCE_DIR} "${CMAKE_CURRENT_SOURCE_DIR}/MIPP/")
    
    # test exe
    add_executable(${PROJECT_NAME}_test line2Dup.cpp test.cpp)
    target_link_libraries(${PROJECT_NAME}_test ${OpenCV_LIBS})
    
    # pybind
    if (USE_PYBIND)
        find_package(PythonLibs 3 REQUIRED)
        find_package(pybind11 REQUIRED)
        include(pybind11/Cmake/FindNumPy.cmake)
        set(SOURCE_PYBIND
            pybind11/pybind11.cpp
            pybind11/np2mat/ndarray_converter.cpp)
        include_directories(${INCLUDE_DIRECTORIES}
                ${PYTHON_INCLUDE_DIRS}
                ${PYTHON_NUMPY_INCLUDE_DIR})
        pybind11_add_module(${PROJECT_NAME}_py line2Dup.cpp ${SOURCE_PYBIND})
        target_link_libraries(${PROJECT_NAME}_py PRIVATE ${OpenCV_LIBS})
    endif()
  4. 切换到/path/to/shape_based_matching-python_binding 安装python拓展

pip install ./

然后就可以使用了,如下:

(smatch) ➜  shape_based_matching-python_binding pip list      
Package                 Version
----------------------- -------------------
certifi                 2020.6.20
numpy                   1.19.1
pip                     20.1.1
setuptools              49.2.0.post20200714
shape-based-matching-py 0.0.1  # 安装好的包
wheel                   0.34.2

我的CPP零基础,编译相关完全不会,关于那个OpenMP在Mac上面使用, 可能需要参考这个链Enable OpenMP support in clang in Mac OS X (sierra & Mojave)