opencv / opencv_contrib

Repository for OpenCV's extra modules
Apache License 2.0
9.45k stars 5.77k forks source link

Contrib modules getting built perfectly fine, even when CMAKE says their dependencies are not available #630

Closed StevenPuttemans closed 8 years ago

StevenPuttemans commented 8 years ago

Just grabbed latest master from both main and contrib repository and tried to build all the contrib modules also. What baffled me is the following.

The Cmake procedure clearly looks for dependencies and states that for example the following dependencies are not found

Caffe:   NO
Tesseract:   NO

And there comes the catch, it then states, ow lets build the modules depending on it

To be built:                 cudev core cudaarithm flann imgproc ml reg surface_matching video cudabgsegm cudafilters cudaimgproc cudawarping dnn fuzzy imgcodecs photo shape videoio cudacodec highgui objdetect plot ts xobjdetect xphoto bgsegm bioinspired dpm face features2d line_descriptor saliency text calib3d ccalib cudafeatures2d cudalegacy cudaobjdetect cudaoptflow cudastereo datasets rgbd stereo structured_light superres tracking videostab xfeatures2d ximgproc aruco optflow stitching matlab python2
    Disabled:                    world contrib_world
    Disabled by dependency:      -
    Unavailable:                 java python3 viz cvv hdf sfm

Which means in my opinion that the CMake is wrongly configured.

So my suggestions

alalek commented 8 years ago

It is just a report of checks. It is not error report. Most part of OpenCV dependencies is optional.

If dependencies are not found on the system, do not build the modules itself

It works if dependency is required for module, for example, see "hdf" or "viz" module (or set of cuda modules).

Tesseract: NO

Agree, double check is redundant. "text" module is available in this case, but it is not fully functional (it is not disabled totally because there was an assumption that there are many detection backends and "tesseract" is only one of them)

StevenPuttemans commented 8 years ago

I know they are checks. So if I understand it correctly, even though torch and caffe are for example not on my system, i am still able to completely use the dnn module?

alalek commented 8 years ago

In general, it depends on module and its design. For example, dnn module can read caffe models and execute forward pass processing without using of anything from caffe (dnn module doesn't require caffe at all).

StevenPuttemans commented 8 years ago

:+1: okay then I guess simply providing a small fix for the redundant check would be enough for closing this down!

StevenPuttemans commented 8 years ago

Actually, I just did a grep -R "Tesseract" * inside the modules folder of the contrib repository and it returned me

datasets/samples/tr_svt_benchmark.cpp:        Ptr<OCRTesseract> ocr = OCRTesseract::create();
datasets/samples/tr_icdar_benchmark.cpp:        Ptr<OCRTesseract> ocr = OCRTesseract::create();
text/text_config.hpp.in:// HAVE OCR Tesseract
text/CMakeLists.txt:find_package(Tesseract)
text/CMakeLists.txt:if(Tesseract_FOUND)
text/CMakeLists.txt:    message(STATUS "Tesseract:   YES")
text/CMakeLists.txt:    message(STATUS "Tesseract:   NO")
text/CMakeLists.txt:if(${Tesseract_FOUND})
text/CMakeLists.txt:include_directories(${Tesseract_INCLUDE_DIR})
text/CMakeLists.txt:if(${Tesseract_FOUND})
text/CMakeLists.txt:  target_link_libraries(opencv_text ${Tesseract_LIBS})
text/README.md:The recognition part currently uses open-source Tesseract OCR (https://code.google.com/p/tesseract-ocr/). If Tesseract OCR is not installed on your system, the corresponding part of the functionality will be unavailable.
text/README.md:Here are instructions on how to install Tesseract on your machine (Linux or Mac; Windows users should look for precompiled binaries or try to adopt the instructions below):
text/README.md:Tesseract installation instruction (Linux, Mac)
text/README.md:1. Google announced that they close code.google.com, so at some moment in the future you may have to find Tesseract 3.03rc1 or later.
text/README.md:2. Tesseract configure script may fail to detect leptonica, so you may have to edit the configure script - comment off some if's around this message and retain only "then" branch.
text/samples/segmented_word_recognition.cpp:    Ptr<OCRTesseract>  ocrTes = OCRTesseract::create();
text/samples/segmented_word_recognition.cpp:    cout << " OCR_Tesseract  output \"" << output << "\". Done in "
text/samples/webcam_demo.cpp:    cout << "  Press 'o' to switch between OCRTesseract/OCRHMMDecoder recognition." << endl;
text/samples/webcam_demo.cpp:    char *recognitions_str[2] = {const_cast<char *>("Tesseract"), const_cast<char *>("NM_chain_features + KNN")};
text/samples/webcam_demo.cpp:    vector< Ptr<OCRTesseract> > ocrs;
text/samples/webcam_demo.cpp:      ocrs.push_back(OCRTesseract::create());
text/samples/webcam_demo.cpp:              parallel_for_(r, Parallel_OCR<OCRTesseract>(detections, outputs, boxes, words, confidences, ocrs));
text/samples/end_to_end_recognition.cpp: * Shows the use of the Tesseract OCR API with the Extremal Region Filter algorithm described in:
text/samples/end_to_end_recognition.cpp:    cout << "Shows the use of the Tesseract OCR API with the Extremal Region Filter algorithm described in:" << endl;
text/samples/end_to_end_recognition.cpp:    Ptr<OCRTesseract> ocr = OCRTesseract::create();
text/include/opencv2/text/ocr.hpp:/** @brief OCRTesseract class provides an interface with the tesseract-ocr API (v3.02.02) in C++.
text/include/opencv2/text/ocr.hpp:   -   (C++) An example of OCRTesseract recognition combined with scene text detection can be found
text/include/opencv2/text/ocr.hpp:    -   (C++) Another example of OCRTesseract recognition combined with scene text detection can be
text/include/opencv2/text/ocr.hpp:class CV_EXPORTS_W OCRTesseract : public BaseOCR
text/include/opencv2/text/ocr.hpp:    /** @brief Creates an instance of the OCRTesseract class. Initializes Tesseract.
text/include/opencv2/text/ocr.hpp:    CV_WRAP static Ptr<OCRTesseract> create(const char* datapath=NULL, const char* language=NULL,
text/FindTesseract.cmake:# Tesseract OCR
text/FindTesseract.cmake:unset(Tesseract_FOUND)
text/FindTesseract.cmake:find_path(Tesseract_INCLUDE_DIR tesseract/baseapi.h
text/FindTesseract.cmake:find_library(Tesseract_LIBRARY NAMES tesseract
text/FindTesseract.cmake:set(Tesseract_LIBS ${Tesseract_LIBRARY} ${Lept_LIBRARY})
text/FindTesseract.cmake:if(Tesseract_LIBS AND Tesseract_INCLUDE_DIR)
text/FindTesseract.cmake:    set(Tesseract_FOUND 1)
text/src/ocr_tesseract.cpp:void OCRTesseract::run(Mat& image, string& output_text, vector<Rect>* component_rects,
text/src/ocr_tesseract.cpp:void OCRTesseract::run(Mat& image, Mat& mask, string& output_text, vector<Rect>* component_rects,
text/src/ocr_tesseract.cpp:CV_WRAP String OCRTesseract::run(InputArray image, int min_confidence, int component_level)
text/src/ocr_tesseract.cpp:CV_WRAP String OCRTesseract::run(InputArray image, InputArray mask, int min_confidence, int component_level)
text/src/ocr_tesseract.cpp:class OCRTesseractImpl : public OCRTesseract
text/src/ocr_tesseract.cpp:    OCRTesseractImpl(const char* datapath, const char* language, const char* char_whitelist, int oemode, int psmode)
text/src/ocr_tesseract.cpp:            cout << "OCRTesseract: Could not initialize tesseract." << endl;
text/src/ocr_tesseract.cpp:        //cout << "OCRTesseract: tesseract version " << tess.Version() << endl;
text/src/ocr_tesseract.cpp:        cout << "OCRTesseract("<<oemode<<psmode<<"): Tesseract not found." << endl;
text/src/ocr_tesseract.cpp:    ~OCRTesseractImpl()
text/src/ocr_tesseract.cpp:        cout << "OCRTesseract(" << component_level << image.type() <<"): Tesseract not found." << endl;
text/src/ocr_tesseract.cpp:Ptr<OCRTesseract> OCRTesseract::create(const char* datapath, const char* language,
text/src/ocr_tesseract.cpp:    return makePtr<OCRTesseractImpl>(datapath, language, char_whitelist, oem, psmode);

You can clearly see that only text/CMakeLists.txt generates the output, which gets me wondering why this would be generated twice?

StevenPuttemans commented 8 years ago

So my guess is that somehow the CMakeLists.txt of the text module is called twice instead of simply once.

StevenPuttemans commented 8 years ago

BTW, inside the CMake config files of dnn I found #take into account OpenCV two-pass module addition scheme which could explain why also other stuff is double printed... Care to explain what is meant by this?

mshabunin commented 8 years ago

The ocv_glob_modules macro is used to process all modules, it makes two passes indicated by _OPENCV_INITIALPASS variable. ocv_add_module macro is used to init basic module variables and compute dependencies, during first pass it stops file processing by calling return(). During second pass it does not stop processing and other commands (ocv_glob_module_sources, ocv_module_include_directories, ocv_create_module, ...) will be called.

The text module is trying to detect Tesseract before ocv_add_module call (hidden inside ocv_define_module), that is why the detection is made twice.

StevenPuttemans commented 8 years ago

Okay thank you! That is exactly what I needed to know!

Just a last question, the CMakeLists.txt of text module doesn't even contain the ocv_add_module, only the ocv_define_module macro. However the define one calls the add one inside. So basically moving the define higher solves the problem right?

StevenPuttemans commented 8 years ago

Could you check if this is correct?

https://github.com/StevenPuttemans/opencv_contrib/commit/3824b1d3b575805c9bfc746d1fe088af75eb4ecf

alalek commented 8 years ago

Looks good to me

StevenPuttemans commented 8 years ago

@alalek well I am going to do the same for some of the other modules out there who are skipping this rule of first defining the ocv_define_module before pushing it. It seems to me it is better if the modules all have same behaviour.

Will continue on this by monday!

alalek commented 8 years ago

I believe CMakeLists.txt for modules should follow this scheme:

// quiet detection (no messages), find_package() with QUIET option

if(required dependencies are missing)
  message(missing required dependencies list) // optional
  ocv_module_disable(...)
endif()

ocv_define_module(...)

// report status of some important optional 3rdparty dependencies, like "Tesseract: YES/NO".

// compiler flags, etc
StevenPuttemans commented 8 years ago

Yeah I kind of agree :) I guess they follow it now?

alalek commented 8 years ago

It is fine now. Thanks!

StevenPuttemans commented 8 years ago

:+1: