Skip to content
Snippets Groups Projects
Commit d922942a authored by angelsantamaria's avatar angelsantamaria
Browse files

imported from gitlab

parent 54c61fa3
No related branches found
No related tags found
No related merge requests found
Showing
with 1717 additions and 0 deletions
/Default/
# Pre-requisites about cmake itself
CMAKE_MINIMUM_REQUIRED(VERSION 2.4)
if(COMMAND cmake_policy)
cmake_policy(SET CMP0005 NEW)
cmake_policy(SET CMP0003 NEW)
endif(COMMAND cmake_policy)
# The project name and the type of project
PROJECT(vision_utils)
SET(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/bin)
SET(LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/lib)
SET(CMAKE_INSTALL_PREFIX /usr/local)
IF (NOT CMAKE_BUILD_TYPE)
SET(CMAKE_BUILD_TYPE "DEBUG")
ENDIF (NOT CMAKE_BUILD_TYPE)
SET(CMAKE_CXX_FLAGS_DEBUG "-g -Wall -D_REENTRANT")
SET(CMAKE_CXX_FLAGS_RELEASE "-O3 -D_REENTRANT")
ADD_SUBDIRECTORY(src)
FIND_PACKAGE(Doxygen)
ADD_CUSTOM_TARGET (doc ${DOXYGEN_EXECUTABLE} ${CMAKE_SOURCE_DIR}/doc/doxygen.conf)
ADD_CUSTOM_TARGET (distclean @echo cleaning cmake files)
IF (UNIX)
ADD_CUSTOM_COMMAND(
COMMENT "distribution clean"
COMMAND make ARGS clean
COMMAND rm ARGS -rf ${CMAKE_SOURCE_DIR}/build/*
TARGET distclean
)
ELSE(UNIX)
ADD_CUSTOM_COMMAND(
COMMENT "distclean only implemented in unix"
TARGET distclean
)
ENDIF(UNIX)
ADD_CUSTOM_TARGET (uninstall @echo uninstall package)
IF (UNIX)
ADD_CUSTOM_COMMAND(
COMMENT "uninstall package"
COMMAND xargs ARGS rm < install_manifest.txt
TARGET uninstall
)
ELSE(UNIX)
ADD_CUSTOM_COMMAND(
COMMENT "uninstall only implemented in unix"
TARGET uninstall
)
ENDIF(UNIX)
#edit the following line to add the librarie's header files
FIND_PATH(vision_utils_INCLUDE_DIR vision_utils.h /usr/include/vision_utils /usr/local/include/vision_utils)
FIND_LIBRARY(vision_utils_LIBRARY
NAMES vision_utils
PATHS /usr/lib /usr/local/lib /usr/local/lib/vision_utils)
IF (vision_utils_INCLUDE_DIR AND vision_utils_LIBRARY)
SET(vision_utils_FOUND TRUE)
ENDIF (vision_utils_INCLUDE_DIR AND vision_utils_LIBRARY)
IF (vision_utils_FOUND)
IF (NOT vision_utils_FIND_QUIETLY)
MESSAGE(STATUS "Found vision_utils: ${vision_utils_LIBRARY}")
ENDIF (NOT vision_utils_FIND_QUIETLY)
ELSE (vision_utils_FOUND)
IF (vision_utils_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find vision_utils")
ENDIF (vision_utils_FIND_REQUIRED)
ENDIF (vision_utils_FOUND)
ReadMe.md 0 → 100644
# vision_utils
## Introduction
#### Pre-Requisites
This package requires of the following libraries and packages
* [cmake](http://www.cmake.org), a cross-platform build system
* [doxygen](http://www.doxygen.org) and
[graphviz](http://www.graphviz.org) to generate the documentation
* stdc++
Under linux all of these utilities are available in ready-to-use packages.
Under MacOS most of the packages are available via [fink](http://www.finkproject.org).
#### Compilation
Just download this package, uncompress it, and execute
`cd build`
`cmake ..`
to generate the makefile and then
`make`
to obtain the shared library and also all the example programs.
The *cmake* only needs to be executed once (make will automatically call *cmake*
if you modify one of the `CMakeList.txt` files).
To generate this documentation type
`make doc`
The files in the `build` directory are genetated by *cmake* and *make*
and can be safely removed.
After doing so you will need to call cmake manually again.
#### Configuration
The default build mode is DEBUG. That is, objects and executables include debug information.
The RELEASE build mode optimizes for speed. To build in this mode execute
`cmake .. -DCMAKE_BUILD_TYPE=RELEASE`
The release mode will be kept until next time cmake is executed.
#### Installation
In order to be able to use the library, it it necessary to copy it into the system.
To do that, execute
`make install`
as root and the shared libraries will be copied to `/usr/local/lib/<vision_utils>` directory
and the header files will be copied to `/usr/local/include/<vision_utils>` directory. At
this point, the library may be used by any user.
To remove the library from the system, exceute
`make uninstall`
as root, and all the associated files will be removed from the system.
## Customization
To build a new application using these library, first it is necessary to locate if the library
has been installed or not using the following command in your `CMakeLists.txt`
`FIND_PACKAGE(vision_utils REQUIRED)`
In the case that the package is present, it is necessary to add the header files directory to
the include directory path by using
`INCLUDE_DIRECTORIES(${vision_utils_INCLUDE_DIR})`
Finally, it is also nevessary to link with the desired libraries by using the following command
`TARGET_LINK_LIBRARIES(<executable name> ${vision_utils_LIBRARY})`
## License
This package is licensed under a [GPL 3.0 License](http://www.gnu.org/licenses/gpl.html)
#### Disclaimer
Copyright (C) 2017
[http://www.angelsantamaria.eu](http://www.angelsantamaria.eu)
All rights reserved.
This file is part of vision_utils library
vision_utils library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see [gnu licenses](http://www.gnu.org/licenses/)
*
*/
!.gitignore
*
*/
!.gitignore
# Doxyfile 1.5.5
@INCLUDE_PATH = ../doc/
@INCLUDE = doxygen_project_name.conf
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
DOXYFILE_ENCODING = UTF-8
PROJECT_NUMBER =
OUTPUT_DIRECTORY = ../doc
CREATE_SUBDIRS = NO
OUTPUT_LANGUAGE = English
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = NO
ABBREVIATE_BRIEF =
ALWAYS_DETAILED_SEC = NO
INLINE_INHERITED_MEMB = NO
FULL_PATH_NAMES = YES
STRIP_FROM_PATH =
STRIP_FROM_INC_PATH =
SHORT_NAMES = NO
JAVADOC_AUTOBRIEF = NO
QT_AUTOBRIEF = NO
MULTILINE_CPP_IS_BRIEF = NO
DETAILS_AT_TOP = NO
INHERIT_DOCS = YES
SEPARATE_MEMBER_PAGES = NO
TAB_SIZE = 8
ALIASES =
OPTIMIZE_OUTPUT_FOR_C = YES
OPTIMIZE_OUTPUT_JAVA = NO
OPTIMIZE_FOR_FORTRAN = NO
OPTIMIZE_OUTPUT_VHDL = NO
BUILTIN_STL_SUPPORT = NO
CPP_CLI_SUPPORT = NO
SIP_SUPPORT = NO
DISTRIBUTE_GROUP_DOC = NO
SUBGROUPING = YES
TYPEDEF_HIDES_STRUCT = NO
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
EXTRACT_ALL = NO
EXTRACT_PRIVATE = NO
EXTRACT_STATIC = NO
EXTRACT_LOCAL_CLASSES = YES
EXTRACT_LOCAL_METHODS = NO
EXTRACT_ANON_NSPACES = NO
HIDE_UNDOC_MEMBERS = NO
HIDE_UNDOC_CLASSES = NO
HIDE_FRIEND_COMPOUNDS = NO
HIDE_IN_BODY_DOCS = NO
INTERNAL_DOCS = NO
CASE_SENSE_NAMES = YES
HIDE_SCOPE_NAMES = NO
SHOW_INCLUDE_FILES = YES
INLINE_INFO = YES
SORT_MEMBER_DOCS = NO
SORT_BRIEF_DOCS = NO
SORT_GROUP_NAMES = NO
SORT_BY_SCOPE_NAME = NO
GENERATE_TODOLIST = YES
GENERATE_TESTLIST = YES
GENERATE_BUGLIST = YES
GENERATE_DEPRECATEDLIST= YES
ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = YES
SHOW_DIRECTORIES = YES
FILE_VERSION_FILTER =
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------
QUIET = YES
WARNINGS = YES
WARN_IF_UNDOCUMENTED = YES
WARN_IF_DOC_ERROR = YES
WARN_NO_PARAMDOC = NO
WARN_FORMAT = "$file:$line: $text"
WARN_LOGFILE =
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
INPUT = ../src \
../doc/main.dox
INPUT_ENCODING = UTF-8
FILE_PATTERNS = *.c \
*.h \
*.cpp
RECURSIVE = YES
EXCLUDE =
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS = *.tab.c \
*.tab.h \
lex* \
*glr.h \
*llr.h \
*glr.c \
*llr.c \
*general.h
EXCLUDE_SYMBOLS =
EXAMPLE_PATH = ../src/examples
EXAMPLE_PATTERNS =
EXAMPLE_RECURSIVE = NO
IMAGE_PATH = ../doc/images
INPUT_FILTER =
FILTER_PATTERNS =
FILTER_SOURCE_FILES = NO
#---------------------------------------------------------------------------
# configuration options related to source browsing
#---------------------------------------------------------------------------
SOURCE_BROWSER = YES
INLINE_SOURCES = NO
STRIP_CODE_COMMENTS = YES
REFERENCED_BY_RELATION = YES
REFERENCES_RELATION = YES
REFERENCES_LINK_SOURCE = YES
USE_HTAGS = NO
VERBATIM_HEADERS = YES
#---------------------------------------------------------------------------
# configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
ALPHABETICAL_INDEX = YES
COLS_IN_ALPHA_INDEX = 5
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# configuration options related to the HTML output
#---------------------------------------------------------------------------
GENERATE_HTML = YES
HTML_OUTPUT = html
HTML_FILE_EXTENSION = .html
HTML_HEADER =
HTML_FOOTER =
HTML_STYLESHEET =
HTML_ALIGN_MEMBERS = YES
GENERATE_HTMLHELP = NO
GENERATE_DOCSET = NO
DOCSET_FEEDNAME = "Doxygen generated docs"
DOCSET_BUNDLE_ID = org.doxygen.Project
HTML_DYNAMIC_SECTIONS = NO
CHM_FILE =
HHC_LOCATION =
GENERATE_CHI = NO
BINARY_TOC = NO
TOC_EXPAND = NO
DISABLE_INDEX = NO
ENUM_VALUES_PER_LINE = 4
GENERATE_TREEVIEW = NO
TREEVIEW_WIDTH = 250
#---------------------------------------------------------------------------
# configuration options related to the LaTeX output
#---------------------------------------------------------------------------
GENERATE_LATEX = NO
LATEX_OUTPUT = latex
LATEX_CMD_NAME = latex
MAKEINDEX_CMD_NAME = makeindex
COMPACT_LATEX = NO
PAPER_TYPE = a4
EXTRA_PACKAGES =
LATEX_HEADER =
PDF_HYPERLINKS = YES
USE_PDFLATEX = NO
LATEX_BATCHMODE = NO
LATEX_HIDE_INDICES = NO
#---------------------------------------------------------------------------
# configuration options related to the RTF output
#---------------------------------------------------------------------------
GENERATE_RTF = NO
RTF_OUTPUT = rtf
COMPACT_RTF = NO
RTF_HYPERLINKS = NO
RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
#---------------------------------------------------------------------------
# configuration options related to the man page output
#---------------------------------------------------------------------------
GENERATE_MAN = NO
MAN_OUTPUT = man
MAN_EXTENSION = .3
MAN_LINKS = NO
#---------------------------------------------------------------------------
# configuration options related to the XML output
#---------------------------------------------------------------------------
GENERATE_XML = NO
XML_OUTPUT = xml
XML_SCHEMA =
XML_DTD =
XML_PROGRAMLISTING = YES
#---------------------------------------------------------------------------
# configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
# configuration options related to the Perl module output
#---------------------------------------------------------------------------
GENERATE_PERLMOD = NO
PERLMOD_LATEX = NO
PERLMOD_PRETTY = YES
PERLMOD_MAKEVAR_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = NO
EXPAND_ONLY_PREDEF = NO
SEARCH_INCLUDES = YES
INCLUDE_PATH =
INCLUDE_FILE_PATTERNS =
PREDEFINED = _USE_MPI=1
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration::additions related to external references
#---------------------------------------------------------------------------
TAGFILES =
GENERATE_TAGFILE =
ALLEXTERNALS = NO
EXTERNAL_GROUPS = YES
PERL_PATH = /usr/bin/perl
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
CLASS_DIAGRAMS = YES
MSCGEN_PATH =
HIDE_UNDOC_RELATIONS = YES
HAVE_DOT = YES
CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES
GROUP_GRAPHS = YES
UML_LOOK = NO
TEMPLATE_RELATIONS = NO
INCLUDE_GRAPH = NO
INCLUDED_BY_GRAPH = NO
CALL_GRAPH = YES
CALLER_GRAPH = YES
GRAPHICAL_HIERARCHY = YES
DIRECTORY_GRAPH = NO
DOT_IMAGE_FORMAT = png
DOT_PATH =
DOTFILE_DIRS =
DOT_GRAPH_MAX_NODES = 50
MAX_DOT_GRAPH_DEPTH = 2
DOT_TRANSPARENT = YES
DOT_MULTI_TARGETS = NO
GENERATE_LEGEND = YES
DOT_CLEANUP = YES
#---------------------------------------------------------------------------
# Configuration::additions related to the search engine
#---------------------------------------------------------------------------
SEARCHENGINE = NO
PROJECT_NAME = "vision_utils"
/*! \mainpage vision_utils
\section Introduction
\subsection Pre-Requisites
This package requires of the following libraries and packages
- <A href="http://www.cmake.org">cmake</A>, a cross-platform build system.
- <A href="http://www.doxygen.org">doxygen</a> and
<A href="http://www.graphviz.org">graphviz</a> to generate the documentation.
- stdc++,
.
Under linux all of these utilities are available in ready-to-use packages.
Under MacOS most of the packages are available via <a href="http://www.finkproject.org/">fink</a>. <br>
\subsection Compilation
Just download this package, uncompress it, and execute
- cd build
- cmake ..
.
to generate the makefile and then
- make
.
to obtain the shared library and also all the example programs.
The <em>cmake</em> only need to be executed once (make will automatically call
<em>cmake</em> if you modify one of the <em>CMakeList.txt</em> files).
To generate this documentation type
- make doc
.
The files in the <em>build</em> directory are genetated by <em>cmake</em>
and <em>make</em> and can be safely removed.
After doing so you will need to call cmake manually again.
\subsection Configuration
The default build mode is DEBUG. That is, objects and executables
include debug information.
The RELEASE build mode optimizes for speed. To build in this mode
execute
- cmake .. -DCMAKE_BUILD_TYPE=RELEASE
.
The release mode will be kept until next time cmake is executed.
\subsection Installation
In order to be able to use the library, it it necessary to copy it into the system.
To do that, execute
- make install
.
as root and the shared libraries will be copied to <em>/usr/local/lib/vision_utils</em> directory
and the header files will be copied to <em>/usr/local/include/vision_utils</em> directory. At
this point, the library may be used by any user.
To remove the library from the system, exceute
- make uninstall
.
as root, and all the associated files will be removed from the system.
\section Customization
To build a new application using these library, first it is necessary to locate if the library
has been installed or not using the following command
- FIND_PACKAGE(vision_utils REQUIRED)
In the case that the package is present, it is necessary to add the header files directory to
the include directory path by using
- INCLUDE_DIRECTORIES(${vision_utils_INCLUDE_DIR})
Finally, it is also nevessary to link with the desired libraries by using the following command
- TARGET_LINK_LIBRARIES(<executable name> ${vision_utils_LIBRARY})
.
\section License
This package is licensed under a
<a href="http://www.gnu.org/licenses/lgpl.html">
LGPL 3.0 License</a>.
\section Disclaimer
This is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
*
*/
!.gitignore
# library source files
SET(sources vision_utils.cpp cam_utils/cam_utils.cpp feature_detector/feature_detector.cpp feature_descriptor/feature_descriptor.cpp feature_matcher/feature_matcher.cpp)
# application header files
SET(headers vision_utils.h common/vu_base.h cam_utils/cam_utils.h feature_detector/feature_detector.h feature_descriptor/feature_descriptor.h feature_matcher/feature_matcher.h)
# locate the necessary dependencies
FIND_PACKAGE(Eigen3 REQUIRED)
FIND_PACKAGE(OpenCV REQUIRED)
FIND_PACKAGE(Boost REQUIRED)
if (OpenCV_FOUND)
if (${OpenCV_VERSION_MAJOR} GREATER 2)
message("-- [INFO] Found OpenCV ${OpenCV_VERSION_MAJOR}.${OpenCV_VERSION_MINOR} support")
ADD_DEFINITIONS(-DHAVE_OPENCV_H)
SET(USE_CV true)
else(${OpenCV_VERSION_MAJOR} GREATER 2)
message("[WARN] OpenCV support not installed. Minimum 3.0 version required.")
message("[WARN] Current version ${OpenCV_VERSION_MAJOR}")
endif(${OpenCV_VERSION_MAJOR} GREATER 2)
else(OpenCV_FOUND)
message("[WARN] OpenCV support not installed. Minimum 3.0 version required.")
endif(OpenCV_FOUND)
# add the necessary include directories
INCLUDE_DIRECTORIES(. ${EIGEN3_INCLUDE_DIR} ${OpenCV_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS})
# create the shared library
ADD_LIBRARY(vision_utils SHARED ${sources})
# link necessary libraries
TARGET_LINK_LIBRARIES(vision_utils ${OpenCV_LIBS} ${Boost_LIBRARIES})
# install
INSTALL(TARGETS vision_utils
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib/vision_utils
ARCHIVE DESTINATION lib/vision_utils)
INSTALL(FILES ${headers} DESTINATION include/vision_utils)
INSTALL(FILES ../Findvision_utils.cmake DESTINATION ${CMAKE_ROOT}/Modules/)
# examples of usage
ADD_SUBDIRECTORY(examples)
#include "cam_utils.h"
CCamUtils::CCamUtils()
{
}
CCamUtils::~CCamUtils()
{
}
bool CCamUtils::openCamera(const int& _cam_num, cv::VideoCapture& _cam)
{
cv::VideoCapture camera(_cam_num);
if (!camera.isOpened()) // check if we succeeded
{
std::cerr << "ERROR: Could not open camera: " << _cam_num << std::endl;
return false;
}
_cam = camera;
return true;
}
bool CCamUtils::getFrame(cv::VideoCapture& _cam, cv::Mat& _frame)
{
try
{
_cam >> _frame;
}
catch (cv::Exception& e)
{
std::cout << "An exception occurred. Ignoring frame. " << e.err << std::endl;
return false;
}
return true;
}
bool CCamUtils::showFrame(const std::string& _window_name, const cv::Mat& _frame)
{
try
{
cv::imshow(_window_name, _frame);
}
catch (cv::Exception& e)
{
std::cout << "An exception occurred. Ignoring frame. " << e.err << std::endl;
return false;
}
return true;
}
#ifndef _CAMUTILS_H
#define _CAMUTILS_H
// std stuff
#include <stdio.h>
#include <iostream>
// OpenCV stuff
#include "opencv2/opencv.hpp"
class CCamUtils
{
public:
/**
* \brief Constructor
*
* Main class constructor.
*/
CCamUtils();
/**
* \brief Destructor
*
* Main class destructor.
*/
~CCamUtils();
/**
* \brief Open Webcam
*
* This method opens the specified webcam using OpenCV
* Inputs:
* _cam_num: system camera number (int)
* Ouptuts:
* cam: camera handle (cv::VideoCapture)
*
* Returns true if the camera is correctly opened
*
*/
bool openCamera(const int& _cam_num, cv::VideoCapture& _cam);
/**
* \brief Get frame
*
* This method gets a frame from the specified webcam
*
* Inputs:
* cam: camera handle (cv::VideoCapture)
* Outputs:
* frame: filled frame (cv::Mat)
* Returns true if the frame is correctly obtained
*/
bool getFrame(cv::VideoCapture& _cam, cv::Mat& _frame);
/**
*\brief Show Frame
*
* This method shows the specified frame using OpenCV
*
* Inputs:
* window_name: Window name inwhich the frame will be displayed (string)
* frame: Frame to be displayed (cv::Mat)
* Returns true if the frame is correctly displayed
*/
bool showFrame(const std::string& _window_name, const cv::Mat& _frame);
};
#endif
#ifndef FACTORY_H_
#define FACTORY_H_
// wolf
//#include "wolf.h"
// std
#include <string>
#include <map>
#include <iostream>
#include <iomanip>
namespace cv_utils
{
/** \brief Singleton template factory
*
* This class implements a generic factory as a singleton.
*
* > IMPORTANT: This template factory can be used to construct many different objects except:
* > - Objects deriving from DetectorBase --> see DetectorFactory
* > - Objects deriving from DescriptorBase --> see DescriptorFactory
* > - Objects deriving from MatcherBase --> see MatcherFactory
* >
* > The reason for this is that the two cases above need a more elaborated API than the one in this template class.
*
* \param TypeBase base type of all the objects created by the factory
* \param TypeInput type of the input argument. Typical cases are std::string for file names, and YAML::Node for YAML nodes.
*
* - The class is templatized on the class of the produced objects, __TypeBase__.
* The produced objects are always of a class deriving from TypeBase.
* The returned data is always a pointer to TypeBase.
*
* For example, you may use as __TypeBase__ the following types:
* - DetectorBase: the Factory creates detectors deriving from DetectorBase and returns base pointers ````DetectorBasePtr```` to them
* - XxxBase: the Factory creates objects deriving from XxxBase and returns pointers ````XxxBasePtr```` to them.
*
* - The class in also templatized on the type of the input parameter of the creator, __TypeInput__:
* - ````std::string```` is used when the input parameter is a file name from which to read data (typically a YAML file).
* - ````YAML::Node```` is used when the input parameter is a YAML node with structured data.
*
* ### Operation of the factory
*
* #### Rationale
*
* This factory can create objects of classes deriving from TypeBase.
*
* > For example, if you want to make a Detector factory, set TypeBase = DetectorBase.\n
* > Then, the factory will create specific detectors deriving from DetectorBase.\n
* > The specific type of detector (e.g. FAST, SIFT, ORB, etc) is indicated by a string that we call TYPE in this documentation.
*
* Specific object creation is invoked by the method ````create(TYPE, params ... )````, where
* - the TYPE of object to create is identified with a string
* - the params may be provided in different forms -- see TypeInput.
*
* The methods to create specific objects are called __creators__.
* Creators must be registered to the factory before they can be invoked for object creation.
*
* This documentation shows you how to:
* - Define correct TYPE names
* - Access the factory
* - Write object creators
* - Register and unregister object creators to the factory
* - Create objects using the factory
* - Examples: Write and register a detector creator for FAST.
*
* #### Define correct TYPE names
* The rule to make new TYPE strings unique is that you skip the generic 'Type' prefix from your class name,
* and you build a string in CAPITALS with space separators, e.g.:
* - ParamsDetectorORB -> ````"ORB PARAMS"````
* - ParamsMatcherKnn -> ````"KNN PARAMS"````
* - etc.
*
* #### Access the factory
* The first thing to know is that we have defined typedefs for the templates that we are using. For example:
*
* \code
* typedef Factory<ParamsBase, std::string> ParamsFactory;
* typedef Factory<DetectorBase, std::string> DetectorFactory;
* typedef Factory<DescriptorBase, YAML::Node> DescriptorFactory;
* \endcode
*
*
* Second to know, the Factory class is a <a href="http://stackoverflow.com/questions/1008019/c-singleton-design-pattern#1008289">singleton</a>: it can only exist once in your application.
* To access it, use the static method get(),
*
* \code
* Factory<MyTypeBase, MyTypeInput>::get()
* \endcode
*
* where, of course, you better make use of the appropriate typedef in place of ````Factory<MyTypeBase, MyTypeInput>````.
*
* You can then call the methods you like, e.g. to create a detector, you use:
*
* \code
* DetectorFactory::get().create(...); // see below for creating objects ...
* \endcode
*
* #### Write creator methods (in your derived object classes)
* The method DetectorORB::create(...) exists in the DetectorORB class as a static method.
* All these ````XxxXxx::create()```` methods need to have exactly the same API, regardless of the object type.
* The API puts into play the two template parameters:
*
* \code
* static TypeBase* create( const TypeInput& );
* \endcode
*
* This API includes an element of type TypeInput, which might be either a std::string, or a YAML::node:
* - ````std::string```` is used to indicate the name of a configuration file. These files are usually YAML files containing configuration data to create your object.
* - ````YAML::Node```` is used to access parts of a YAML file already encoded as nodes, such as when loading landmarks from a SLAM map stored as a YAML file.
*
*
* Two examples:
*
* \code
* static ParamsBasePtr create(const std::string& _params_dot_yaml)
* static DetectorBasePtr create(const YAML::Node& _lmk_yaml_node)
* \endcode
*
* See further down for an implementation example.
*
* #### Register object creators
* Prior to invoking the creation of an object of a particular TYPE,
* you must register the creator for this type into the factory.
*
* Registering object creators into the factory is done through registerCreator().
* You provide an object TYPE string (above), and a pointer to a static method
* that knows how to create your specific object, e.g.:
*
* \code
* DetectorFactory::get().registerCreator("DETECTOR ORB", DetectorORB::create);
* \endcode
*
* #### Automatic registration
* Currently, registering is performed in specific source files, object_xxxx.cpp.
* For example, in detector_orb_yaml.cpp we find the line:
*
* \code
* const bool registered_detector_params = ParamsFactory::get().registerCreator("ORB PARAMS", createORBParams);
* \endcode
*
* which is a static invocation (i.e., it is placed at global scope outside of the ORBParams class).
*
* Therefore, at application level, all objects that have a .cpp file compiled are automatically registered.
*
* #### Unregister object creators
* The method unregisterCreator() unregisters the ObjectXxx::create() method. It only needs to be passed the string of the object type.
*
* \code
* Factory<MyTypeBase, MyTypeInput>::get().unregisterCreator("CAMERA");
* \endcode
*
* #### Create objects using the factory
* Note: Prior to invoking the creation of a object of a particular type,
* you must register the creator for this type into the factory.
*
* To create e.g. a DetectorORB from a YAML node you type:
*
* \code
* DetectorBasePtr det_orb_ptr = Factory<DetectorBasePtr, YAML::Node>::get().create("DETECTOR ORB", det_orb_yaml_node);
* \endcode
*
* or even better, make use of the convenient typedefs:
*
* \code
* DetectorBasePtr det_orb_ptr = DetectorFactory::get().create("DETECTOR ORB", det_orb_yaml_node);
* \endcode
*
* ### Examples
* TODO: Update this
* #### Example 1: Writing the creator of DetectorORB from a YAML node
*
* You can find this code in the detector_orb.cpp file.
*
* \code
* // Creator (this method is static):
* DetectorBasePtr DetectorORB::create(const YAML::Node& _det_orb_node)
* {
* // Parse YAML node with lmk info and data
* unsigned int id = _det_orb_node["id"].as<unsigned int>();
* int first_id = _det_orb_node["first_id"].as<int>();
* bool first_defined = _det_orb_node["first_defined"].as<bool>();
* bool last_defined = _det_orb_node["last_defined"].as<bool>();
* unsigned int npoints = _det_orb_node["points"].size();
* Eigen::MatrixXs points(2,npoints);
* for (unsigned int i = 0; i < npoints; i++)
* {
* points.col(i) = _lmk_node["points"][i].as<Eigen::Vector2s>();
* }
*
* // Create a new landmark
* LandmarkBasePtr lmk_ptr = new LandmarkPolyline2D(points, first_defined, last_defined, first_id);
* lmk_ptr->setId(id);
*
* return lmk_ptr;
* }
* \endcode
*
* #### Example 2: Registering the creator of LandmarkPolyline2D from a YAML node
*
* You can find this code in the landmark_polyline_2D.cpp file.
*
* \code
* // Register landmark creator (put the register code inside an unnamed namespace):
* namespace
* {
* const bool registered_lmk_polyline_2D = LandmarkFactory::get().registerCreator("POLYLINE 2D", LandmarkPolyline2D::create);
* }
*
* \endcode
*
* ### More information
* - IntrinsicsFactory: typedef of this template to create intrinsic structs deriving from IntrinsicsBase directly from YAML files.
* - ProcessorParamsFactory: typedef of this template to create processor params structs deriving from ProcessorParamsBase directly from YAML files.
* - LandmarkFactory: typedef of this template to create landmarks deriving from LandmarkBase directly from YAML nodes.
* - Problem::loadMap() : to load a maps directly from YAML files.
* - You can also check the code in the example file ````src/examples/test_map_yaml.cpp````.
*
* #### See also
* - SensorFactory: to create sensors
* - ProcessorFactory: to create processors.
* - Problem::installSensor() : to install sensors in WOLF Problem.
* - Problem::installProcessor() : to install processors in WOLF Problem.
*
*/
template<class TypeBase, typename... TypeInput>
class Factory
{
typedef std::shared_ptr<TypeBase> TypeBasePtr;
public:
// example of creator callback (see typedefs below)
typedef TypeBasePtr (*CreatorCallback)(TypeInput... _input);
// Main factory API
bool registerCreator(const std::string& _type, CreatorCallback createFn);
bool unregisterCreator(const std::string& _type);
TypeBasePtr create(const std::string& _type, TypeInput... _input);
std::string getClass();
private:
typedef std::map<std::string, CreatorCallback> CallbackMap;
CallbackMap callbacks_;
// Singleton ---------------------------------------------------
// This class is a singleton. The code below guarantees this.
// See: http://stackoverflow.com/questions/1008019/c-singleton-design-pattern
public:
static Factory& get();
Factory(const Factory&) = delete;
void operator=(Factory const&) = delete;
private:
Factory() { }
~Factory() { }
};
template<class TypeBase, typename... TypeInput>
inline bool Factory<TypeBase, TypeInput...>::registerCreator(const std::string& _type, CreatorCallback createFn)
{
bool reg = callbacks_.insert(typename CallbackMap::value_type(_type, createFn)).second;
if (reg)
std::cout << std::setw(22) << std::left << getClass() << " <-- registered " << _type << std::endl;
else
std::cout << std::setw(22) << std::left << getClass() << " X-- skipping " << _type << ": already registered." << std::endl;
return reg;
}
template<class TypeBase, typename... TypeInput>
inline bool Factory<TypeBase, TypeInput...>::unregisterCreator(const std::string& _type)
{
return callbacks_.erase(_type) == 1;
}
template<class TypeBase, typename... TypeInput>
inline typename Factory<TypeBase, TypeInput...>::TypeBasePtr Factory<TypeBase, TypeInput...>::create(const std::string& _type, TypeInput... _input)
{
typename CallbackMap::const_iterator creator_callback_it = callbacks_.find(_type);
if (creator_callback_it == callbacks_.end())
// not found
throw std::runtime_error(getClass() + " : Unknown type \"" + _type + "\". Possibly you tried to use an unregistered creator.");
// Invoke the creation function
return (creator_callback_it->second)(std::forward<TypeInput>(_input)...);
}
template<class TypeBase, typename... TypeInput>
inline Factory<TypeBase, TypeInput...>& Factory<TypeBase, TypeInput...>::get()
{
static Factory instance_;
return instance_;
}
template<class TypeBase, typename... TypeInput>
inline std::string Factory<TypeBase, TypeInput...>::getClass()
{
return "Factory<class TypeBase>";
}
// Some specializations
//======================
// Parameters
struct ParamsBase;
typedef Factory<ParamsBase,
const std::string&> ParamsFactory;
template<>
inline std::string ParamsFactory::getClass()
{
return "ParamsFactory";
}
// Frames
class FrameBase;
class TimeStamp;
typedef Factory<FrameBase, const FrameType&, const TimeStamp&, const Eigen::VectorXs&> FrameFactory;
template<>
inline std::string FrameFactory::getClass()
{
return "FrameFactory";
}
#define WOLF_REGISTER_FRAME(FrameType, FrameName) \
namespace{ const bool FrameName##Registered = \
FrameFactory::get().registerCreator(FrameType, FrameName::create); }\
} /* namespace cv_utils */
#endif /* FACTORY_H_ */
#ifndef _VU_BASE_H
#define _VU_BASE_H
// std
#include <functional>
#include <set>
#include <iostream>
#include <map>
#include <vector>
#include <string>
#include <iostream>
#include <time.h>
// Boost
#include <boost/assign/std/vector.hpp> // for 'operator+=()'
using namespace boost::assign; // bring 'operator+=()' into scope
// OpenCV
#include <opencv2/core/core.hpp>
#include <opencv2/core/types.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/xfeatures2d/nonfree.hpp>
#include <opencv2/xfeatures2d.hpp>
#include <opencv2/line_descriptor/descriptor.hpp>
typedef std::vector<cv::KeyPoint> KeyPointVector;
typedef std::vector<cv::KeyPoint> KeyPointVector;
typedef std::vector<cv::line_descriptor::KeyLine> KeyLineVector;
/**
* \brief Class to set object types
*/
class CTypes {
public:
CTypes(void): init_(false) {};
~CTypes(void) {};
void set(std::vector<std::string> &_types)
{
for (unsigned int ii = 0; ii < _types.size(); ii++)
types_[_types[ii]] = ii;
init_= true;
};
std::vector<std::string> list(void)
{
std::vector<std::string> list;
list.reserve(types_.size());
for(std::map<std::string,int>::iterator it = types_.begin(); it != types_.end(); ++it)
{
list.push_back(it->first);
}
return list;
}
int operator()(const std::string &name) {
if (init_)
{
// Search done to take advantage of MAP alphabetical order
int idx = 0;
for (std::map<std::string, int>::const_iterator it = types_.begin();it != types_.end(); ++it)
{
if (it->first.compare(name) == 0)
return idx;
++idx;
}
}
else
{
std::cerr << "[Vision Utils]: Wrong object initialization" << std::cout;
}
return 0;
};
std::string operator()(const int &num) {
if (init_)
{
// Search done to take advantage of MAP alphabetical order
int idx = 0;
for (std::map<std::string, int>::const_iterator it = types_.begin();it != types_.end(); ++it)
{
if (num == idx)
return it->first;
++idx;
}
}
else
std::cerr << "[Vision Utils]: Wrong object initialization" << std::cout;
return 0;
};
unsigned int size(void)
{ return types_.size(); }
protected:
std::map<std::string, int> types_;
bool init_;
};
/**
* \brief Class to set object parameters
*/
class CParams {
public:
CParams(void) {
}
;
~CParams(void) {
}
;
};
/**
* \brief Superbase Class
*
* This Super class is created in order to work with pointers to the derived
* classes. Otherwise CSensor_base is templated and does not allow it.
*/
class CVu_Superbase
{
public:
CVu_Superbase(){};
virtual ~CVu_Superbase(){};
};
/**
* \brief base Class
*/
template <class T_PARAMS>
class CVu_Base: public CVu_Superbase {
public:
CVu_Base(void): is_init_(false) {};
virtual ~CVu_Base(void){};
/**
* \brief Get detection duration
*/
double getTime(void){return comp_time_;};
/**
* \brief list types
*/
std::vector<std::string> list(void)
{ return types_.list();};
/**
* \brief Set object without constructor
*/
bool set(const std::string& _type, const T_PARAMS &_params)
{
bool success = init(_type, _params);
return success;
};
void get(std::string& _type)
{ _type = type_; };
void get(int& _type)
{
_type = types_(type_);
};
cv::Mat drawKeyFeatures(const cv::Mat& _image, const KeyPointVector& _kp_vec)
{
cv::Mat img_out(_image);
for (unsigned int ii = 0; ii < _kp_vec.size(); ++ii)
cv::circle(img_out, _kp_vec[ii].pt, 5, cv::Scalar(128, 128, 255), -1);
return img_out;
}
cv::Mat drawKeyFeatures(const cv::Mat& _image, const KeyLineVector& _kl_vec)
{
cv::Mat img_out(_image);
for (unsigned int ii = 0; ii < _kl_vec.size(); ++ii)
cv::line(img_out, _kl_vec[ii].getStartPoint(), _kl_vec[ii].getEndPoint(), cv::Scalar(128, 128, 255), 3);
return img_out;
}
protected:
// Flags
bool is_init_;
double comp_time_; // Detection time
CTypes types_;
std::string type_;
virtual bool init(const std::string &_type, const T_PARAMS &_params) = 0;
/**
* \brief Set all types
*/
virtual void setAllTypes(void) = 0;
};
#endif
# create an example application
ADD_EXECUTABLE(capture capture.cpp)
ADD_EXECUTABLE(feature_detectors feature_detect.cpp)
ADD_EXECUTABLE(feature_detectors_and_descriptors feature_detect_descript.cpp)
ADD_EXECUTABLE(feature_detectors_descriptors_and_matchers feature_detect_descript_match.cpp)
# link necessary libraries
TARGET_LINK_LIBRARIES(capture vision_utils)
TARGET_LINK_LIBRARIES(feature_detectors vision_utils)
TARGET_LINK_LIBRARIES(feature_detectors_and_descriptors vision_utils)
TARGET_LINK_LIBRARIES(feature_detectors_descriptors_and_matchers vision_utils)
\ No newline at end of file
// OWN stuff
#include <string>
#include <vision_utils.h>
int main(int argc, char *argv[])
{
// Open camera
cv::VideoCapture cam;
CCamUtils cam_fc;
cam_fc.openCamera(0, cam);
cv::startWindowThread();
cv::namedWindow("Cam Test", 1);
for (;;)
{
// Get frame
cv::Mat frame;
cam_fc.getFrame(cam, frame);
// Show frame
cv::imshow("Cam Test", frame);
cv::waitKey(1);
//if (cv::waitKey(30) >= 0) break;
}
cv::destroyAllWindows();
}
// OWN stuff
#include <string>
#include "vision_utils.h"
int main(int argc, char *argv[])
{
std::cout << "----------------------------------------" << std::endl;
std::cout << "| Feature detector example |" << std::endl;
std::cout << "----------------------------------------" << std::endl;
std::cout << std::endl;
CFeature_Detector detector;
CDetector_Params detector_params; // TODO: Fill parameters
std::vector<std::string> detectors_list;
detectors_list = detector.list();
for (unsigned int ii=0; ii<detectors_list.size(); ii++)
std::cout << "[" << ii << "]: " << detectors_list[ii] << std::endl;
//***********
// Detector |
//***********
// Get default value
int feat_type;
detector.get(feat_type);
std::cout << std::endl << "Which DETECTOR do you want to test?[default: " << detectors_list[feat_type] << "]";
feat_type = readFromUser(feat_type);
detector.set(detectors_list[feat_type],detector_params);
std::cout << std::endl << "Testing: " << detectors_list[feat_type] << std::endl;
// *****************************
// Open camera
cv::VideoCapture cam;
CCamUtils cam_fc;
cam_fc.openCamera(0, cam);
// Create displays
cv::startWindowThread();
cv::namedWindow("Original image", cv::WINDOW_NORMAL);
cv::namedWindow("Detections", cv::WINDOW_NORMAL);
// The following line is used to remove the OpenCV "init done" from the terminal
std::cout << "\e[A" << " " << std::endl;
for (int nframe = 0; nframe < 1000; ++nframe)
{
// Get frame
cv::Mat frame;
cam_fc.getFrame(cam, frame);
// Show ORIGINAL frame
cv::imshow("Original image", frame);
if (!detector.isLine())
{
KeyPointVector keypoints;
keypoints = detector.detectKeyPoints(frame);
// Show frame with features
detector.drawKeyFeatures(frame, keypoints);
}
else
{
KeyLineVector keypoints;
keypoints = detector.detectKeyLines(frame);
// Show frame with features
detector.drawKeyFeatures(frame, keypoints);
}
std::cout << "\e[A" << "Detection time: " << detector.getTime() << std::endl;
// Show NEW frame
cv::imshow("Detections", frame);
cv::waitKey(1);
// if (cv::waitKey(30) >= 0) break;
}
cv::destroyAllWindows();
}
// OWN stuff
#include <string>
#include "vision_utils.h"
int main(int argc, char *argv[])
{
std::cout << "---------------------------------------------------------" << std::endl;
std::cout << "| Feature detectors and descriptors example |" << std::endl;
std::cout << "---------------------------------------------------------" << std::endl;
std::cout << std::endl;
//***********
// Detector |
//***********
CFeature_Detector detector;
CDetector_Params detector_params; // TODO: Fill parameters
std::vector<std::string> detectors_list;
detectors_list = detector.list();
for (unsigned int ii=0; ii<detectors_list.size(); ii++)
{
if ( (detectors_list[ii].compare("LSD")!=0) && (detectors_list[ii].compare("ED")!=0) )
std::cout << "[" << ii << "]: " << detectors_list[ii] << std::endl;
}
// Get default value
int feat_type;
detector.get(feat_type);
std::cout << std::endl << "Which DETECTOR do you want to test?[default: " << detectors_list[feat_type] << "]";
feat_type = readFromUser(feat_type);
detector.set(detectors_list[feat_type],detector_params);
//*************
// Descriptor |
//*************
CFeature_Descriptor descriptor;
CDescriptor_Params descriptor_params; // TODO: Fill parameters
std::vector<std::string> descriptor_list;
descriptor_list = descriptor.list();
for (unsigned int ii=0; ii<descriptor_list.size(); ii++)
std::cout << "[" << ii << "]: " << descriptor_list[ii] << std::endl;
// Get default value
int desc_type;
descriptor.get(desc_type);
std::cout << std::endl << "Which DESCRIPTOR do you want to test?[default: " << descriptor_list[desc_type] << "]";
desc_type = readFromUser(desc_type);
descriptor.set(descriptor_list[desc_type],descriptor_params);
std::cout << std::endl << "Testing: " << detectors_list[feat_type] << " + " << descriptor_list[desc_type] << " (DETECTOR + DESCRIPTOR)" << std::endl;
// *****************************
// Open camera
cv::VideoCapture cam;
CCamUtils cam_fc;
cam_fc.openCamera(0, cam);
// Create displays
cv::startWindowThread();
cv::namedWindow("Original image", cv::WINDOW_NORMAL);
cv::namedWindow("Detections", cv::WINDOW_NORMAL);
// The following line is used to remove the OpenCV "init done" from the terminal
std::cout << "\e[A" << " " << std::endl;
for (int nframe = 0; nframe < 1000; ++nframe)
{
// Get frame
cv::Mat frame;
cam_fc.getFrame(cam, frame);
// Show ORIGINAL frame
cv::imshow("Original image", frame);
// Detector
KeyPointVector keypoints;
keypoints = detector.detectKeyPoints(frame);
// Descriptor
cv::Mat descriptors;
descriptors = descriptor.getDescriptor(frame,keypoints);
// Show frame with features
detector.drawKeyFeatures(frame, keypoints);
std::cout << "\e[A" <<
"Detection time: " << detector.getTime() << " " <<
"Description time: " << descriptor.getTime() << " " <<
"TOTAL time: " << detector.getTime() + descriptor.getTime() << std::endl;
// Show NEW frame
cv::imshow("Detections", frame);
cv::waitKey(1);
// if (cv::waitKey(30) >= 0) break;
}
cv::destroyAllWindows();
}
// OWN stuff
#include <string>
#include "vision_utils.h"
#include <sstream>
int main(int argc, char *argv[])
{
std::cout << "-------------------------------------------------------------------" << std::endl;
std::cout << "| Feature detectors, descriptors and matchers example |" << std::endl;
std::cout << "-------------------------------------------------------------------" << std::endl;
std::cout << std::endl;
//***********
// Detector |
//***********
CFeature_Detector detector;
CDetector_Params detector_params; // TODO: Fill parameters
std::vector<std::string> detectors_list;
detectors_list = detector.list();
for (unsigned int ii=0; ii<detectors_list.size(); ii++)
{
if ( (detectors_list[ii].compare("LSD")!=0) && (detectors_list[ii].compare("ED")!=0) )
std::cout << "[" << ii << "]: " << detectors_list[ii] << std::endl;
}
// Get default value
int feat_type;
detector.get(feat_type);
std::cout << std::endl << "Which DETECTOR do you want to test?[default: " << detectors_list[feat_type] << "]";
// feat_type = readFromUser(feat_type);
detector.set(detectors_list[feat_type],detector_params);
//*************
// Descriptor |
//*************
CFeature_Descriptor descriptor;
CDescriptor_Params descriptor_params; // TODO: Fill parameters
std::vector<std::string> descriptor_list;
descriptor_list = descriptor.list();
for (unsigned int ii=0; ii<descriptor_list.size(); ii++)
std::cout << "[" << ii << "]: " << descriptor_list[ii] << std::endl;
// Get default value
int desc_type;
descriptor.get(desc_type);
std::cout << std::endl << "Which DESCRIPTOR do you want to test?[default: " << descriptor_list[desc_type] << "]" << std::endl;
// desc_type = readFromUser(desc_type);
descriptor.set(descriptor_list[desc_type],descriptor_params);
//**********
// Matcher |
//**********
CFeature_Matcher matcher;
CMatcher_Params matcher_params; // TODO: Fill parameters
CMatcher_Params matcher_search_params; // TODO: Fill parameters
std::vector<std::string> matchers_list;
matchers_list = matcher.list();
for (unsigned int ii=0; ii<matchers_list.size(); ii++)
std::cout << "[" << ii << "]: " << matchers_list[ii] << std::endl;
// Get default value
int match_type;
matcher.get(match_type);
std::cout << std::endl << "Which MATCHER do you want to test?[default: " << matchers_list[match_type] << "]" << std::endl;
// match_type = readFromUser(match_type);
matcher.set(matchers_list[match_type],matcher_params);
std::vector<std::string> matchers_search_list;
matchers_search_list = matcher.listSearchTypes();
for (unsigned int ii=0; ii<matchers_search_list.size(); ii++)
std::cout << "[" << ii << "]: " << matchers_search_list[ii] << std::endl;
// Get default value
int match_search_type;
matcher.getSearchType(match_search_type);
std::cout << std::endl << "Which MATCHER SEARCH do you want to test?[default: " << matchers_search_list[match_search_type] << "]" << std::endl;
// match_search_type = readFromUser(match_search_type);
matcher.setSearchType(matchers_search_list[match_search_type],matcher_search_params);
std::cout << std::endl << "Testing: " << detectors_list[feat_type] << " + " << descriptor_list[desc_type] << " + " << matchers_list[match_type] << " + " << matchers_search_list[match_search_type] << " (DETECTOR + DESCRIPTOR + MATCHER + MATCHER SEARCH)" << std::endl;
// *****************************
// Open camera
cv::VideoCapture cam;
CCamUtils cam_fc;
cam_fc.openCamera(0, cam);
// Create displays
cv::startWindowThread();
cv::namedWindow("Original image", cv::WINDOW_NORMAL);
cv::namedWindow("Detections", cv::WINDOW_NORMAL);
cv::namedWindow("Matches", cv::WINDOW_NORMAL);
cv::Mat frame_old;
KeyPointVector keypoints_old;
KeyPointVector good_keypoints;
cv::Mat descriptors_old;
std::vector<cv::DMatch> good_matches;
// The following line is used to remove the OpenCV "init done" from the terminal
std::cout << "\e[A" << " " << std::endl;
for (int nframe = 0; nframe < 1000; ++nframe)
{
// Get frame
cv::Mat frame;
cam_fc.getFrame(cam, frame);
cv::Mat frame_matches = frame.clone();
// Show ORIGINAL frame
cv::imshow("Original image", frame);
// Detector
KeyPointVector keypoints;
keypoints = detector.detectKeyPoints(frame);
// Descriptor
cv::Mat descriptors;
descriptors = descriptor.getDescriptor(frame,keypoints);
// Matcher
if (nframe > 1)
{
// TODO: Implement this object creation depending on user preferences
// if (matchers_search_list[match_search_type].compare("Match") == 0)
// std::vector<cv::DMatch> matches;
// else
std::vector< std::vector<cv::DMatch> > matches;
matcher.match(descriptors,descriptors_old,matches);
// Filter matches
good_matches.clear();
good_keypoints.clear();
matcher.filterMatches(keypoints_old, keypoints, matches, frame.rows, frame.cols, good_matches, good_keypoints);
}
// Update objects
keypoints_old.clear();
keypoints_old.resize(keypoints.size());
for (unsigned int ii = 0; ii < keypoints.size(); ++ii)
keypoints_old.push_back(keypoints[ii]);
descriptors_old = cv::Mat(descriptors.size(),descriptors.type());
descriptors_old = descriptors.clone();
frame_old = frame;
// Show frame with features
detector.drawKeyFeatures(frame, keypoints);
// Draw matches
if (nframe > 1 && !keypoints_old.empty() && !keypoints.empty())
{
matcher.drawKeyFeatures(frame_matches, good_keypoints);
// cv::drawMatches( frame_old, keypoints_old, frame, keypoints,
// good_matches, frame_matches, cv::Scalar::all(-1), cv::Scalar::all(-1),
// std::vector<char>(), cv::DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );
for (unsigned int ii = 0; ii < good_keypoints.size(); ++ii)
cv::line(frame_matches,good_keypoints[ii].pt,good_keypoints[ii].pt,cv::Scalar(0,255,0),3);
cv::imshow("Matches", frame_matches);
}
// Show NEW frame
cv::imshow("Detections", frame);
cv::waitKey(1);
// if (cv::waitKey(30) >= 0) break;
std::cout << "\e[A" <<
"Detection time: " << detector.getTime() << " " <<
"Description time: " << descriptor.getTime() << " " <<
"Match time: " << matcher.getTime() << " " <<
"TOTAL time: " << detector.getTime() + descriptor.getTime() << std::endl;
}
cv::destroyAllWindows();
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment