maxruby / OpenCV.jl

The OpenCV (C++) interface for Julia
Other
105 stars 28 forks source link

LoadError while using OpenCV #17

Closed kvmanohar22 closed 7 years ago

kvmanohar22 commented 7 years ago

After installing opencv-3.2.0, when I import OpenCV, I get the following LoadError,

julia> using OpenCV
ERROR: LoadError: ReadOnlyMemoryError()
 in dlopen_e(::String, ::UInt32) at ./libdl.jl:103
 in macro expansion; at /home/kv/.julia/v0.5/OpenCV/src/OpenCV.jl:76 [inlined]
 in anonymous at ./<missing>:?
 in include_from_node1(::String) at ./loading.jl:488
 in eval(::Module, ::Any) at ./boot.jl:234
 in require(::Symbol) at ./loading.jl:415
while loading /home/kv/.julia/v0.5/OpenCV/src/OpenCV.jl, in expression starting on line 71

julia> 

Any ideas how to get around this ?

maxruby commented 7 years ago

I have not set up/tested import of .dyld libraries from OpenCV 3.2.0, but if you look at the code in /OpenCV/src/OpenCV.jl below it needs to be udpated. I will have a look at it tonight as well after installing the latest Julia master v0.5.

Please do the following:

  1. Make sure that C++ templates work as expected with your own installation of Cxx.jl - independent of OpenCV.jl. My experience is that in several cases, if something does not work in OpenCV.jl, there could be a problem with dependencies on Cxx.jl, deprecation of something in Julia, or changes in the LLVM compiler which Cxx.jl depends on.

  2. When you encounter an issue, please indicate exactly the setup used. When it comes to importing .dyld (OSX) or .so (Unix), the loading methods are dependent on the system.

# Load OpenCV shared libraries (default file extension is .dylib)
# IMPORTANT: make sure to link symbols accross libraries with RTLD_GLOBAL
for i in opencv_libraries
    # TO DO: ensure compatible path/extension for Windows OS
    if is_linux()
         i = swapext(i[1:end-6], ".so")
    end
    Libdl.dlopen_e(joinpath(cvlibdir,i), Libdl.RTLD_GLOBAL)==C_NULL ? println("Not loading $(i)"): nothing
end

# Now include C++ header files
addHeaderDir(joinpath(cvheaderdir,"opencv2"), kind = C_System )
addHeaderDir(joinpath(cvheaderdir,"opencv2/core"), kind = C_System )
cxxinclude(joinpath(cvheaderdir,"opencv2/opencv.hpp"))
    # => opencv.hpp calls all the main headers
    #include "opencv2/core.hpp"
    #include "opencv2/imgproc.hpp"
    #include "opencv2/photo.hpp"
    #include "opencv2/video.hpp"
    #include "opencv2/features2d.hpp"
    #include "opencv2/objdetect.hpp"
    #include "opencv2/calib3d.hpp"
    #include "opencv2/imgcodecs.hpp"
    #include "opencv2/videoio.hpp"
    #include "opencv2/highgui.hpp"
    #include "opencv2/ml.hpp"
kvmanohar22 commented 7 years ago

Make sure that C++ templates work as expected with your own installation of Cxx.jl - independent of OpenCV.jl

Yes, C++ templates seem to work. I tested the written template for src/OpenCV_Mat.jl in REPL and there were no errors associated with it !

julia> using Cxx

julia> cxx"""
       #include <opencv2/core/core.hpp>
       #include <opencv2/highgui/highgui.hpp>
       #include <iostream>
       """
true

julia> cxx"""
       // Grayscale and binary images 
       template <typename T1>
       inline T1 ptr_val(cv::Mat &img, int row, int col)
       {
         return(static_cast<int>(img.at<T1>(row, col)));
       }
       """
true

julia> cxx"""
       // RGB images
       template <typename T1>
       inline std::vector<T1> ptr_val3(cv::Mat &img, int row, int col)
       {
           std::vector<T1>vec(3);
           for(int i = 0; i < 3; ++i)
           {
               vec[i] = img.at<cv::Vec<T1, 3>>(row, col)[i];
           }
           return vec;
       }
       """
true

julia> function pixget(img, row::Int, col::Int)
         (row < 0 || col < 0 || row > rows(img) || col > cols(img)) ? throw(BoundsError()) : nothing

         # Grayscale and binary images
         val = @cxx ptr_val(img, row, col);
         println(val)
         return (val)

         # RGB images
         vec = @cxx ptr_val3(img, row, col);
         println([int(at(vec, 0)), int(at(vec, 1)), int(at(vec, 2))])
         return (vec)
       end
pixget (generic function with 1 method)

julia> 

Sorry, I should have mentioned it before, here is the information of my setup :

$ uname -a
Linux kv 3.19.0-78-generic #86~14.04.1-Ubuntu SMP Tue Dec 6 17:58:35 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
kvmanohar22 commented 7 years ago

Moreover when I execute this in REPL,

for i in opencv_libraries
    # TO DO: ensure compatible path/extension for Windows OS
    if is_linux()
         i = swapext(i[1:end-6], ".so")
    end
    Libdl.dlopen_e(joinpath(cvlibdir,i), Libdl.RTLD_GLOBAL)==C_NULL ? println("Not loading $(i)"): nothing
end

I get the error for libopencv_viz.3.0.0 and the error is :

ERROR: ReadOnlyMemoryError()
 in dlopen_e(::String, ::UInt32) at ./libdl.jl:103
 in macro expansion; at ./REPL[5]:6 [inlined]
 in anonymous at ./<missing>:?

julia> 
maxruby commented 7 years ago

Does libopencv_viz.3.0.0.soactually exist in cvlibdir? Is it possible that it should be 3.2.0 instead?

kvmanohar22 commented 7 years ago

Yes, that file does exist in the path (In fact there are five files : libopencv_viz.so, libopencv_viz.so.3.0, libopencv_viz.so.3.0.0, libopencv_viz.so.3.2, libopencv_viz.so.3.2.0 ). I tried even with 3.2.0 but there is no luck.

maxruby commented 7 years ago

After commit b861501 above, I am able to load all opencv shared (dyld) libs on my MacOS Sierra 10.12.3 with the latest julia master 0.6.0-alpha.

Please let me know what you find after updating OpenCV.jl so we can close this.

kvmanohar22 commented 7 years ago

My version of julia is currently 0.5.1-pre, do you want me to build it for 0.6.0-alpha ?

maxruby commented 7 years ago

Yes, please. Considering the effort that goes into building Julia every time something changes upstream, we might as well work with 0.6.0, at least I would prefer to do so for work with OpenCV.jl. It is largely working ok now and there have also been efforts to update Cxx.jl for 0.6.0.

kvmanohar22 commented 7 years ago

That doesn't seem to work either. I built julia 0.6.0-pre.alpha.0 from source and there was same error while using OpenCV

julia> using OpenCV
ERROR: LoadError: ReadOnlyMemoryError()
Stacktrace:
 [1] dlopen(::String, ::UInt32) at ./libdl.jl:97
 [2] macro expansion at /home/kv/.julia/v0.6/OpenCV/src/OpenCV.jl:75 [inlined]
 [3] anonymous at ./<missing>:?
 [4] include_from_node1(::String) at ./loading.jl:539
 [5] eval(::Module, ::Any) at ./boot.jl:235
 [6] require(::Symbol) at ./loading.jl:453
while loading /home/kv/.julia/v0.6/OpenCV/src/OpenCV.jl, in expression starting on line 70

julia>
maxruby commented 7 years ago

This is clearly an issue with the loading paths or dlopen on some libs in Linux because the exact same code is working perfectly on OSX Sierra 10.12.3 witn 0.6.0-alpha. Please change the libNames array in OpenCV_libs.jlto the following and then test again:

libNames = [
              "shape",
              "stitching",
              "objdetect",
              "superres",
              "videostab",
              "calib3d",
              "features2d",
              "highgui",
              "videoio",
              "imgcodecs",
              "video",
              "photo",
              "ml",
              "imgproc"
             ]

We need to know if the other libs (except for viz) are indeed being loaded properly.

maxruby commented 7 years ago

From what I recall and have learnt in the past, julia dlopenis sometimes tricky to get to work on certain libraries that depend on other shared libraries. For example the RTLD_GLOBAL is crucial in OSX to load such libraries and to link symbols across imported libraries. We need to know first whether the problem is specific to loading this lib or other libs are also failing to load in your Linux setup.

dlopen(libfile::AbstractString[, flags::Integer]) Load a shared library, returning an opaque handle.

The optional flags argument is a bitwise-or of zero or more of RTLD_LOCAL, RTLD_GLOBAL, RTLD_LAZY, RTLD_NOW, RTLD_NODELETE, RTLD_NOLOAD, RTLD_DEEPBIND, and RTLD_FIRST. These are converted to the corresponding flags of the POSIX (and/or GNU libc and/or MacOS) dlopen command, if possible, or are ignored if the specified functionality is not available on the current platform. The default flags are platform specific. On MacOS the default dlopen flags are RTLD_LAZY|RTLD_DEEPBIND|RTLD_GLOBAL while on other platforms the defaults are RTLD_LAZY|RTLD_DEEPBIND|RTLD_LOCAL. An important usage of these flags is to specify non default behavior for when the dynamic library loader binds library references to exported symbols and if the bound references are put into process local or global scope. For instance RTLD_LAZY|RTLD_DEEPBIND|RTLD_GLOBAL allows the library’s symbols to be available for usage in other shared libraries, addressing situations where there are dependencies between shared libraries.

kvmanohar22 commented 7 years ago

I tried with other libs (except for viz) and there was very long error something like this (This is not the complete error. The error was way too big). This error is just beginning and ending few statements.

julia> using OpenCV
In file included from :1:
In file included from /usr/local/include/opencv2/opencv.hpp:52:
In file included from /usr/local/include/opencv2/core.hpp:59:
/usr/lib/gcc/x86_64-linux-gnu/4.9.4/../../../../include/opencv2/core/mat.hpp:58:13: error: incomplete type 'cv::Mat' named in nested name specifier
inline void Mat::initEmpty()
            ^~~~~
/usr/local/include/opencv2/core/base.hpp:629:18: note: forward declaration of 'cv::Mat'
class CV_EXPORTS Mat;
                 ^
In file included from :1:
In file included from /usr/local/include/opencv2/opencv.hpp:52:
In file included from /usr/local/include/opencv2/core.hpp:59:
/usr/lib/gcc/x86_64-linux-gnu/4.9.4/../../../../include/opencv2/core/mat.hpp:67:8: error: incomplete type 'cv::Mat' named in nested name specifier
inline Mat::Mat() : size(&rows)
       ^~~~~
/usr/local/include/opencv2/core/base.hpp:629:18: note: forward declaration of 'cv::Mat'
class CV_EXPORTS Mat;
                 ^
In file included from :1:
In file included from /usr/local/include/opencv2/opencv.hpp:52:
In file included from /usr/local/include/opencv2/core.hpp:59:
/usr/lib/gcc/x86_64-linux-gnu/4.9.4/../../../../include/opencv2/core/mat.hpp:72:8: error: incomplete type 'cv::Mat' named in nested name specifier
inline Mat::Mat(int _rows, int _cols, int _type) : size(&rows)
       ^~~~~
/usr/local/include/opencv2/core/base.hpp:629:18: note: forward declaration of 'cv::Mat'
class CV_EXPORTS Mat;

...
...
...

In file included from :1:
__cxxjl_70.cpp:1:26: error: variable has incomplete type 'cv::UMat'
 void  assignTo(cv::UMat img, cv::UMat& m, int type) { img.assignTo(m, type); } 
                         ^
/usr/local/include/opencv2/core/base.hpp:632:18: note: forward declaration of 'cv::UMat'
class CV_EXPORTS UMat;
                 ^

signal (11): Segmentation fault
while loading /home/kv/.julia/v0.6/OpenCV/./src/OpenCV_ocl.jl, in expression starting on line 676
_ZNK5clang10ASTContext18getASTRecordLayoutEPKNS_10RecordDeclE at /home/kv/.julia/v0.6/Cxx/src/../deps/usr/lib/libcxxffi.so (unknown line)
_ZNK5clang10ASTContext15getTypeInfoImplEPKNS_4TypeE at /home/kv/.julia/v0.6/Cxx/src/../deps/usr/lib/libcxxffi.so (unknown line)
_ZNK5clang10ASTContext11getTypeInfoEPKNS_4TypeE at /home/kv/.julia/v0.6/Cxx/src/../deps/usr/lib/libcxxffi.so (unknown line)
unknown function (ip: 0x7f4dea183edb)
unknown function (ip: 0x7f4dea184e18)
unknown function (ip: 0x7f4dea18629c)
_ZN5clang7CodeGen12CodeGenTypes23arrangeLLVMFunctionInfoENS_7CanQualINS_4TypeEEEbbN4llvm8ArrayRefIS4_EENS_12FunctionType7ExtInfoENS6_INS_17FunctionProtoType16ExtParameterInfoEEENS0_12RequiredArgsE at /home/kv/.julia/v0.6/Cxx/src/../deps/usr/lib/libcxxffi.so (unknown line)
_ZN5clang7CodeGen12CodeGenTypes23arrangeFreeFunctionTypeENS_7CanQualINS_17FunctionProtoTypeEEEPKNS_12FunctionDeclE at /home/kv/.julia/v0.6/Cxx/src/../deps/usr/lib/libcxxffi.so (unknown line)
_ZN5clang7CodeGen12CodeGenTypes26arrangeFunctionDeclarationEPKNS_12FunctionDeclE at /home/kv/.julia/v0.6/Cxx/src/../deps/usr/lib/libcxxffi.so (unknown line)
_ZN5clang7CodeGen13CodeGenModule28EmitGlobalFunctionDefinitionENS_10GlobalDeclEPN4llvm11GlobalValueE at /home/kv/.julia/v0.6/Cxx/src/../deps/usr/lib/libcxxffi.so (unknown line)
_ZN5clang7CodeGen13CodeGenModule20EmitGlobalDefinitionENS_10GlobalDeclEPN4llvm11GlobalValueE at /home/kv/.julia/v0.6/Cxx/src/../deps/usr/lib/libcxxffi.so (unknown line)
_ZN5clang7CodeGen13CodeGenModule10EmitGlobalENS_10GlobalDeclE at /home/kv/.julia/v0.6/Cxx/src/../deps/usr/lib/libcxxffi.so (unknown line)
unknown function (ip: 0x7f4dea114d88)
EmitTopLevelDecl at /home/kv/.julia/v0.6/Cxx/deps/../src/bootstrap.cpp:1244
HandleTopLevelDecl at /home/kv/.julia/v0.6/Cxx/deps/../src/bootstrap.cpp:1252
_ZN5clang17MultiplexConsumer18HandleTopLevelDeclENS_12DeclGroupRefE at /home/kv/.julia/v0.6/Cxx/src/../deps/usr/lib/libcxxffi.so (unknown line)
_cxxparse at /home/kv/.julia/v0.6/Cxx/deps/../src/bootstrap.cpp:216
ParseToEndOfFile at /home/kv/.julia/v0.6/Cxx/src/initialization.jl:107
ParseVirtual at /home/kv/.julia/v0.6/Cxx/src/initialization.jl:138
unknown function (ip: 0x7f4deae04f5c)
jl_call_method_internal at /home/kv/julia/src/julia_internal.h:248 [inlined]
jl_apply_generic at /home/kv/julia/src/gf.c:2212
do_call at /home/kv/julia/src/interpreter.c:75
eval at /home/kv/julia/src/interpreter.c:230
eval_body at /home/kv/julia/src/interpreter.c:534
jl_interpret_toplevel_thunk at /home/kv/julia/src/interpreter.c:679
jl_toplevel_eval_flex at /home/kv/julia/src/toplevel.c:592
jl_parse_eval_all at /home/kv/julia/src/ast.c:874
jl_load at /home/kv/julia/src/toplevel.c:616
include_from_node1 at ./loading.jl:539
unknown function (ip: 0x7f4deae03362)
jl_call_method_internal at /home/kv/julia/src/julia_internal.h:248 [inlined]
jl_apply_generic at /home/kv/julia/src/gf.c:2212
include at ./sysimg.jl:14
unknown function (ip: 0x7f4ffc3dbd8b)
jl_call_method_internal at /home/kv/julia/src/julia_internal.h:248 [inlined]
jl_apply_generic at /home/kv/julia/src/gf.c:2212
do_call at /home/kv/julia/src/interpreter.c:75
eval at /home/kv/julia/src/interpreter.c:230
jl_interpret_toplevel_expr at /home/kv/julia/src/interpreter.c:34
jl_toplevel_eval_flex at /home/kv/julia/src/toplevel.c:577
jl_parse_eval_all at /home/kv/julia/src/ast.c:874
jl_load at /home/kv/julia/src/toplevel.c:616
include_from_node1 at ./loading.jl:539
unknown function (ip: 0x7f4deae03362)
jl_call_method_internal at /home/kv/julia/src/julia_internal.h:248 [inlined]
jl_apply_generic at /home/kv/julia/src/gf.c:2212
include at ./sysimg.jl:14
unknown function (ip: 0x7f4ffc3dbd8b)
jl_call_method_internal at /home/kv/julia/src/julia_internal.h:248 [inlined]
jl_apply_generic at /home/kv/julia/src/gf.c:2212
do_call at /home/kv/julia/src/interpreter.c:75
eval at /home/kv/julia/src/interpreter.c:230
jl_interpret_toplevel_expr at /home/kv/julia/src/interpreter.c:34
jl_toplevel_eval_flex at /home/kv/julia/src/toplevel.c:577
jl_parse_eval_all at /home/kv/julia/src/ast.c:874
jl_load at /home/kv/julia/src/toplevel.c:616
include_from_node1 at ./loading.jl:539
unknown function (ip: 0x7f4ffc5248cb)
jl_call_method_internal at /home/kv/julia/src/julia_internal.h:248 [inlined]
jl_apply_generic at /home/kv/julia/src/gf.c:2212
do_call at /home/kv/julia/src/interpreter.c:75
eval at /home/kv/julia/src/interpreter.c:230
jl_interpret_toplevel_expr at /home/kv/julia/src/interpreter.c:34
jl_toplevel_eval_flex at /home/kv/julia/src/toplevel.c:577 [inlined]
jl_toplevel_eval at /home/kv/julia/src/toplevel.c:600
jl_toplevel_eval_in at /home/kv/julia/src/builtins.c:484
eval at ./boot.jl:235
unknown function (ip: 0x7f4ffc4f9e9f)
jl_call_method_internal at /home/kv/julia/src/julia_internal.h:248 [inlined]
jl_apply_generic at /home/kv/julia/src/gf.c:2212
require at ./loading.jl:453
unknown function (ip: 0x7f4ffc56caab)
jl_call_method_internal at /home/kv/julia/src/julia_internal.h:248 [inlined]
jl_apply_generic at /home/kv/julia/src/gf.c:2212
jl_apply at /home/kv/julia/src/julia.h:1410 [inlined]
eval_import_path_ at /home/kv/julia/src/toplevel.c:401
eval_import_path at /home/kv/julia/src/toplevel.c:428 [inlined]
jl_toplevel_eval_flex at /home/kv/julia/src/toplevel.c:495 [inlined]
jl_toplevel_eval at /home/kv/julia/src/toplevel.c:600
jl_toplevel_eval_in at /home/kv/julia/src/builtins.c:484
eval at ./boot.jl:235
unknown function (ip: 0x7f4ffc4f9e9f)
jl_call_method_internal at /home/kv/julia/src/julia_internal.h:248 [inlined]
jl_apply_generic at /home/kv/julia/src/gf.c:2212
eval_user_input at ./REPL.jl:66
unknown function (ip: 0x7f4deada78b6)
jl_call_method_internal at /home/kv/julia/src/julia_internal.h:248 [inlined]
jl_apply_generic at /home/kv/julia/src/gf.c:2212
macro expansion at ./REPL.jl:97 [inlined]
#1 at ./event.jl:73
unknown function (ip: 0x7f4dead9ff0f)
jl_call_method_internal at /home/kv/julia/src/julia_internal.h:248 [inlined]
jl_apply_generic at /home/kv/julia/src/gf.c:2212
jl_apply at /home/kv/julia/src/julia.h:1410 [inlined]
start_task at /home/kv/julia/src/task.c:261
unknown function (ip: 0xffffffffffffffff)
Allocations: 14683565 (Pool: 14681079; Big: 2486); GC: 27
[1]    15424 segmentation fault (core dumped)  /home/kv/julia/julia
$ 

julia version 0.6.0-pre.alpha. I built from source from this commit 29bc2ac by doing, git checkout v0.6.0-pre.alpha. Is it possible that this is an error related to building opencv 3.2.0 ?

maxruby commented 7 years ago

This is the compiler telling you it is unhappy with forward Mat class declarations... Something may be wrong with your opencv build or setup... Do you have multiple versions of opencv installed? http://answers.opencv.org/question/86962/building-opencv-3-contrib-for-ios-incomplete-type-cvmat/

kvmanohar22 commented 7 years ago

I had a 3.0.0 version of it installed earlier but then I installed 3.2.0 without removing the shared object files in /usr/local/lib/. Maybe this was causing the problem. Now I'm doing fresh install of opencv 3.2.0. I'll update you soon after it.

kvmanohar22 commented 7 years ago

I reinstalled opencv 3.2.0 by removing the previously installed versions of opencv and the error produced now seems to have reduced. With the libNames as follows I get the following error :

libNames = [
              "shape",
              "stitching",
              "objdetect",
              "superres",
              "videostab",
              "calib3d",
              "features2d",
              "highgui",
              "videoio",
              "imgcodecs",
              "video",
              "photo",
              "ml",
              "imgproc",
              #"flann",   // TODO: resolve typeid error due to rtti flag
              # "viz"
            ]
julia> using OpenCV
In file included from :1:
In file included from /usr/local/include/opencv2/opencv.hpp:62:
In file included from /usr/local/include/opencv2/flann.hpp:48:
In file included from /usr/local/include/opencv2/flann/flann_base.hpp:40:
In file included from /usr/local/include/opencv2/flann/params.h:33:
/usr/local/include/opencv2/flann/any.h:58:51: error: cannot use typeid with -fno-rtti
    virtual const std::type_info& type() { return typeid(T); }
                                                  ^
/usr/local/include/opencv2/flann/any.h:268:31: error: cannot use typeid with -fno-rtti
        if (policy->type() != typeid(T)) throw anyimpl::bad_any_cast();
                              ^
/usr/local/include/opencv2/flann/any.h:277:31: error: cannot use typeid with -fno-rtti
        if (policy->type() != typeid(T)) throw anyimpl::bad_any_cast();
                              ^
/usr/local/include/opencv2/flann/any.h:285:34: error: cannot use typeid with -fno-rtti
        return policy->type() == typeid(anyimpl::empty_any);
                                 ^
/usr/local/include/opencv2/flann/any.h:305:34: error: cannot use typeid with -fno-rtti
        return policy->type() == typeid(T);
                                 ^
WARNING: requiring "OpenCV" in module "Main" did not define a corresponding module.

julia> 

This has got something to do with enabling RTTI flag as mentioned here

maxruby commented 7 years ago

Yes, it has to do with enabling RTTI which is mentioned already in the bottom of the OpenCV.jl README. However, not sure if Cxx.jl supports the C++ RTTI - I once tried to enable it and I faced some issues. I suggest you first simply comment out the #include statements for flann in opencv.hpp which are in the include folders.

kvmanohar22 commented 7 years ago

Finally ! This issue is solved !! I think we can now close this issue ;)

maxruby commented 7 years ago

Great! What did you do exactly? Its important to confirm what works with every OS.

maxruby commented 7 years ago

I will open another issue to address support for flann and viz libraries in OpenCV.jl.

kvmanohar22 commented 7 years ago

I had opencv 2.4.0 and opencv 3.0.0 installed previsouly and on top of this I installed 3.2.0. This caused errors. Finally I removed all the versions of opencv (including the shared object files) and did a fresh install of opencv 3.2.0. And then as you mentioned I commented #include statements for flann in opencv.hpp and the problem was solved ! How about I update README.md for installation of Linux and open a PR ?

maxruby commented 7 years ago

Thanks. I am closing this.