LingDong- / skeleton-tracing

A new algorithm for retrieving topological skeleton as a set of polylines from binary images
https://skeleton-tracing.netlify.app
MIT License
505 stars 65 forks source link

swig compilation on Ubuntu #14

Open pluniak opened 3 years ago

pluniak commented 3 years ago

Hi @LingDong- I tested your Python version and it's really nice. I'd need a significant speed up though and I cannot run the swig version:

ImportError: /tf/Repos/trace_skeleton/swig/_trace_skeleton.so: invalid ELF header

I'm running this inside a docker container with gcc version:

gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0

My Python version is 3.6.9.

I cannot build from source as I don't have a .dylib file in my system (at least I cannot find it). I tried with

/usr/lib/x86_64-linux-gnu/libpython3.6m.so.1

instead, but it doesn't work:

collect2: error: ld returned 1 exit status

I'm unexperienced with gcc (and C in general) and I've spent a few hours on this already. Any suggestions would be greatly appreciated!

LingDong- commented 3 years ago

Hi @pluniak ,

Thanks for trying out the library!

The .so file I included is generated for macOS, so I'm afraid rebuilding is necessary on ubuntu.

I think you're right that the linux counterpart of the (macOS specific) .dylib would be a .so, and the path you listed seems plausible.

I was following swig's official tutorial (http://www.swig.org/tutorial.html) when I wrote my shell script, maybe it'll be helpful.

A while ago I got swig to work with raspberry pi (on another project). This was my shell script. Since it's also linux, the solution might look similar on ubuntu.

Also, there're some clang specific arguments, which might need to be replaced with gcc specific counterparts.

I hope this is helpful! I agree swig is not the easiest thing to get working, I remember it took me quite a while to figure it out on my OS too :)

pluniak commented 3 years ago

Thanks for the input @LingDong- . I had a look into it and I'm afraid that is out of scope for me at the moment. I'm more of a pure Pythonist ;-). I'll try to find another solution for making polylines from skeletons first. Cheers!

P.S.: Please consider pointing out the macOS restriction of the swig version in your readme.

3togo commented 2 years ago

Either way will do.

  1. overwrite compile.sh in swig directory ./compile.h

  2. copy CMakeLists.txt to swig directory

    
    cd swig
    mkdir build
    cd build
    make
    python3 example.py

compile.sh 

swig -python trace_skeleton.i gcc -fPIC -O3 -c trace_skeleton.c trace_skeleton_wrap.c -I/$(python3-config --cflags) g++ -shared $(python3-config --cflags --ldflags) *.o -o _trace_skeleton.so

quick tests

python3 -i -c "import trace_skeleton; trace_skeleton.trace('\0\0\0\1\1\1\0\0\0',3,3); print(trace_skeleton.len_polyline());"

python3 -i -c "import trace_skeleton; print(trace_skeleton.from_list([0,0,0,1,1,1,0,0,0],3,3))"

python3 example.py


CMakeLIsts.txt

cmake_minimum_required(VERSION 3.18) project(trace_skeleton) FIND_PACKAGE(SWIG REQUIRED) INCLUDE(${SWIG_USE_FILE})

FIND_PACKAGE(PythonLibs) INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_PATH}) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})

SET(CMAKE_SWIG_FLAGS "")

set(PYs "example.py;") foreach(PY ${PYs}) message("PY=${PY}") message("CMAKE_CURRENT_SOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR}") file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${PY} DESTINATION ${CMAKE_CURRENT_BINARY_DIR})

endforeach()

SET_SOURCE_FILES_PROPERTIES(trace_skeleton.i PROPERTIES) # CPLUSPLUS ON)

SET_SOURCE_FILES_PROPERTIES(trace_skeleton.i PROPERTIES SWIG_FLAGS "-includeall")

SWIG_ADD_LIBRARY(trace_skeleton LANGUAGE python SOURCES trace_skeleton.i trace_skeleton.c) SWIG_LINK_LIBRARIES(trace_skeleton ${PYTHON_LIBRARIES})

n1ckfg commented 2 years ago

The Ubuntu compile.sh script above works for me on Ubuntu 20, Python 3.8

balazon commented 2 years ago

I don't know about swig, but I managed to make the c++ code work with pybind I can't really share the code, but you can get started with this https://pybind11.readthedocs.io/en/stable/advanced/pycpp/numpy.html Then you can just wrap the trace_skeleton call in your function and return the polylines in some python object (a list of lists for example). With a setup.py you can even compile your c++ code, then it's usable from python.

n1ckfg commented 1 year ago

I was able to build for Windows using:

gcc -fPIC -O3 -c trace_skeleton.c trace_skeleton_wrap.c -I%HOMEDRIVE%%HOMEPATH%\AppData\Local\Programs\Python\Python310\include
g++ -shared *.o -o _trace_skeleton.pyd -L%HOMEDRIVE%%HOMEPATH%\AppData\Local\Programs\Python\Python310\libs -lpython310

...and Mac:

PYTHON_VERSION=3.10
PYTHON_VERSION_FULL=3.10.6
PYTHON_PATH=~/.pyenv/versions/$PYTHON_VERSION_FULL
PYTHON_INCLUDE=$PYTHON_PATH/include/python$PYTHON_VERSION
PYTHON_LIB=$PYTHON_PATH/lib/libpython$PYTHON_VERSION.a
gcc -O3 -c trace_skeleton.c trace_skeleton_wrap.c -I$PYTHON_INCLUDE
gcc $(python3-config --ldflags) -dynamiclib *.o -o _trace_skeleton.so -I$PYTHON_LIB -undefined dynamic_lookup