diff --git a/.readthedocs.yml b/.readthedocs.yml new file mode 100644 index 00000000..79484e63 --- /dev/null +++ b/.readthedocs.yml @@ -0,0 +1,19 @@ +# .readthedocs.yml +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +# Build documentation in the docs/ directory with Sphinx +sphinx: + configuration: doc/sphinx/source/conf.py + +# Optionally build your docs in additional formats such as PDF and ePub +formats: all + +# Optionally set the version of Python and requirements required to build your docs +python: + version: 3.7 + install: + - requirements: doc/sphinx/requirements.txt diff --git a/.travis.yml b/.travis.yml index 4e71f353..dd24a21b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -92,14 +92,14 @@ before_script: - mkdir -p ${POPSIFT_BUILD_RELEASE} - cd ${POPSIFT_BUILD_RELEASE} - > - cmake . ${POPSIFT_SOURCE} -DCMAKE_INSTALL_PREFIX=${POPSIFT_INSTALL_RELEASE} -DCMAKE_BUILD_TYPE=Release + cmake . ${POPSIFT_SOURCE} -DCMAKE_INSTALL_PREFIX=${POPSIFT_INSTALL_RELEASE} -DCMAKE_BUILD_TYPE=Release -DPopSift_BUILD_DOCS:BOOL=OFF # Classic debug build # Create build folder - mkdir -p ${POPSIFT_BUILD_DEBUG} - cd ${POPSIFT_BUILD_DEBUG} - > - cmake . ${POPSIFT_SOURCE} -DCMAKE_INSTALL_PREFIX=${POPSIFT_INSTALL_DEBUG} -DCMAKE_BUILD_TYPE=Debug + cmake . ${POPSIFT_SOURCE} -DCMAKE_INSTALL_PREFIX=${POPSIFT_INSTALL_DEBUG} -DCMAKE_BUILD_TYPE=Debug -DPopSift_BUILD_DOCS:BOOL=OFF script: - cd ${POPSIFT_BUILD_RELEASE} @@ -111,7 +111,7 @@ script: - cd ${POPSIFT_APP_SRC} - mkdir -p ${POPSIFT_APP_BUILD_RELEASE} - cd ${POPSIFT_APP_BUILD_RELEASE} - - cmake .. -DPopSift_DIR=${POPSIFT_INSTALL_RELEASE}/lib/cmake/PopSift/ -DCMAKE_INSTALL_PREFIX=${POPSIFT_APP_INSTALL_RELEASE} -DCMAKE_BUILD_TYPE=Release + - cmake .. -DPopSift_DIR=${POPSIFT_INSTALL_RELEASE}/lib/cmake/PopSift/ -DCMAKE_INSTALL_PREFIX=${POPSIFT_APP_INSTALL_RELEASE} -DCMAKE_BUILD_TYPE=Release -DPopSift_BUILD_DOCS:BOOL=OFF - make install -j 2 VERBOSE=1 # same for debug @@ -124,7 +124,7 @@ script: - cd ${POPSIFT_APP_SRC} - mkdir -p ${POPSIFT_APP_BUILD_DEBUG} - cd ${POPSIFT_APP_BUILD_DEBUG} - - cmake .. -DPopSift_DIR=${POPSIFT_INSTALL_DEBUG}/lib/cmake/PopSift/ -DCMAKE_INSTALL_PREFIX=${POPSIFT_APP_INSTALL_DEBUG} -DCMAKE_BUILD_TYPE=Debug + - cmake .. -DPopSift_DIR=${POPSIFT_INSTALL_DEBUG}/lib/cmake/PopSift/ -DCMAKE_INSTALL_PREFIX=${POPSIFT_APP_INSTALL_DEBUG} -DCMAKE_BUILD_TYPE=Debug -DPopSift_BUILD_DOCS:BOOL=OFF - make install -j 2 VERBOSE=1 cache: diff --git a/CMakeLists.txt b/CMakeLists.txt index 13d49614..9735bc2d 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,6 +8,7 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${CMAKE_SYSTEM_NAME}-$ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}") option(PopSift_BUILD_EXAMPLES "Build PopSift applications." ON) +option(PopSift_BUILD_DOCS "Build PopSift documentation." OFF) option(PopSift_USE_NVTX_PROFILING "Use CUDA NVTX for profiling." OFF) option(PopSift_ERRCHK_AFTER_KERNEL "Synchronize and check CUDA error after every kernel." OFF) option(PopSift_USE_POSITION_INDEPENDENT_CODE "Generate position independent code." ON) @@ -200,6 +201,10 @@ endif() add_subdirectory(src) +if(PopSift_BUILD_DOCS) + add_subdirectory(doc) +endif() + set(PopSift_TESTFILE_PATH "popsift-samples/datasets/sample/big_set/" CACHE STRING "Base directory where your test files are stored") if(PopSift_USE_TEST_CMD) if(NOT IS_ABSOLUTE("${PopSift_TESTFILE_PATH}")) @@ -229,6 +234,7 @@ message(STATUS "PopSift version: " ${PROJECT_VERSION}) message(STATUS "Build type: " ${CMAKE_BUILD_TYPE}) message(STATUS "Build Shared libs: " ${BUILD_SHARED_LIBS}) message(STATUS "Build examples: " ${PopSift_BUILD_EXAMPLES}) +message(STATUS "Build documentation: " ${PopSift_BUILD_DOCS}) message(STATUS "Generate position independent code: " ${CMAKE_POSITION_INDEPENDENT_CODE}) message(STATUS "Use CUDA NVTX for profiling: " ${PopSift_USE_NVTX_PROFILING}) message(STATUS "Synchronize and check CUDA error after every kernel: " ${PopSift_ERRCHK_AFTER_KERNEL}) diff --git a/appveyor.yml b/appveyor.yml index 3cdf7298..dc822f2b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -26,7 +26,7 @@ install: before_build: - md build - cd build - - cmake -G "Visual Studio 14 2015" -A x64 -T v140,host=x64 -DBUILD_SHARED_LIBS=%DBUILD_SHARED_LIBS% -DPopSift_USE_POSITION_INDEPENDENT_CODE:BOOL=%DBUILD_SHARED_LIBS% -DPopSift_BUILD_EXAMPLES:BOOL=ON -DCMAKE_BUILD_TYPE=%configuration% -DCMAKE_TOOLCHAIN_FILE=c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake .. + - cmake -G "Visual Studio 14 2015" -A x64 -T v140,host=x64 -DBUILD_SHARED_LIBS=%DBUILD_SHARED_LIBS% -DPopSift_BUILD_DOCS:BOOL=OFF -DPopSift_USE_POSITION_INDEPENDENT_CODE:BOOL=%DBUILD_SHARED_LIBS% -DPopSift_BUILD_EXAMPLES:BOOL=ON -DCMAKE_BUILD_TYPE=%configuration% -DCMAKE_TOOLCHAIN_FILE=c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake .. - ls -l build: diff --git a/cmake/FindSphinx.cmake b/cmake/FindSphinx.cmake new file mode 100644 index 00000000..9b9d2b9e --- /dev/null +++ b/cmake/FindSphinx.cmake @@ -0,0 +1,12 @@ +#Look for an executable called sphinx-build +find_program(SPHINX_EXECUTABLE + NAMES sphinx-build + HINTS ${SPHINX_ROOT} + DOC "Path to sphinx-build executable") + +include(FindPackageHandleStandardArgs) + +#Handle standard arguments to find_package like REQUIRED and QUIET +find_package_handle_standard_args(Sphinx + "Failed to find sphinx-build executable" + SPHINX_EXECUTABLE) \ No newline at end of file diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt new file mode 100644 index 00000000..5468184f --- /dev/null +++ b/doc/CMakeLists.txt @@ -0,0 +1,39 @@ +find_package(Doxygen REQUIRED) + +file(GLOB_RECURSE ALL_PUBLIC_HEADERS ${PROJECT_SOURCE_DIR}/src/popsift/*.h*) +set(CCTAG_OTHER_DOC_SOURCES ${PROJECT_SOURCE_DIR}/README.md ${PROJECT_SOURCE_DIR}/INSTALL.md) +set(DOXYGEN_USE_MDFILE_AS_MAINPAGE ${PROJECT_SOURCE_DIR}/README.md) +set(DOXYGEN_PROJECT_BRIEF "A faithful implementation of the SIFT algorithm in CUDA.") +set(DOXYGEN_GENERATE_XML YES) +set(DOXYGEN_GENERATE_TREEVIEW YES) +set(DOXYGEN_GENERATE_DEPRECATEDLIST YES) +set(DOXYGEN_SORT_BRIEF_DOCS YES) +set(DOXYGEN_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doxygen) +set(DOXYGEN_INDEX_FILE ${DOXYGEN_OUTPUT_DIRECTORY}/xml/index.xml) + +doxygen_add_docs(doxygen + ${ALL_PUBLIC_HEADERS} ${CCTAG_OTHER_DOC_SOURCES} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "Generate the doc") + + + +find_package(Sphinx REQUIRED) + +set(SPHINX_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/sphinx/source) +set(SPHINX_BUILD ${CMAKE_CURRENT_BINARY_DIR}/sphinx) + +add_custom_target(sphinx ALL + COMMAND + ${SPHINX_EXECUTABLE} -b html + # Tell Breathe where to find the Doxygen output + -Dbreathe_projects.PopSift=${DOXYGEN_OUTPUT_DIRECTORY}/xml + ${SPHINX_SOURCE} ${SPHINX_BUILD} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS + doxygen + # Other docs files you want to track should go here (or in some variable) + ${CMAKE_CURRENT_SOURCE_DIR}/sphinx/source/index.rst + ${DOXYGEN_INDEX_FILE} + # MAIN_DEPENDENCY ${SPHINX_SOURCE}/conf.py + COMMENT "Generating documentation with Sphinx") \ No newline at end of file diff --git a/doc/sphinx/Makefile b/doc/sphinx/Makefile new file mode 100644 index 00000000..d0c3cbf1 --- /dev/null +++ b/doc/sphinx/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = source +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/doc/sphinx/make.bat b/doc/sphinx/make.bat new file mode 100644 index 00000000..6247f7e2 --- /dev/null +++ b/doc/sphinx/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/doc/sphinx/requirements.txt b/doc/sphinx/requirements.txt new file mode 100644 index 00000000..45a2e179 --- /dev/null +++ b/doc/sphinx/requirements.txt @@ -0,0 +1,4 @@ +sphinx>=1.9.0 +sphinx_rtd_theme +sphinxcontrib-bibtex +breathe diff --git a/doc/sphinx/source/Doxyfile b/doc/sphinx/source/Doxyfile new file mode 100644 index 00000000..3a42393f --- /dev/null +++ b/doc/sphinx/source/Doxyfile @@ -0,0 +1,267 @@ +DOXYFILE_ENCODING = UTF-8 +PROJECT_NAME = PopSift +PROJECT_NUMBER = 1.0.0 +PROJECT_BRIEF = "A faithful implementation of the SIFT algorithm in CUDA." +PROJECT_LOGO = +OUTPUT_DIRECTORY = ../build +CREATE_SUBDIRS = NO +ALLOW_UNICODE_NAMES = NO +OUTPUT_LANGUAGE = English +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ABBREVIATE_BRIEF = "The $name class" "The $name widget" "The $name file" is provides specifies contains represents a an the +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 +INHERIT_DOCS = YES +SEPARATE_MEMBER_PAGES = NO +TAB_SIZE = 4 +ALIASES = +TCL_SUBST = +OPTIMIZE_OUTPUT_FOR_C = NO +OPTIMIZE_OUTPUT_JAVA = NO +OPTIMIZE_FOR_FORTRAN = NO +OPTIMIZE_OUTPUT_VHDL = NO +EXTENSION_MAPPING = +MARKDOWN_SUPPORT = YES +TOC_INCLUDE_HEADINGS = 0 +AUTOLINK_SUPPORT = YES +BUILTIN_STL_SUPPORT = NO +CPP_CLI_SUPPORT = NO +SIP_SUPPORT = NO +IDL_PROPERTY_SUPPORT = YES +DISTRIBUTE_GROUP_DOC = NO +GROUP_NESTED_COMPOUNDS = NO +SUBGROUPING = YES +INLINE_GROUPED_CLASSES = NO +INLINE_SIMPLE_STRUCTS = NO +TYPEDEF_HIDES_STRUCT = NO +LOOKUP_CACHE_SIZE = 0 +EXTRACT_ALL = NO +EXTRACT_PRIVATE = NO +EXTRACT_PACKAGE = 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 +HIDE_COMPOUND_REFERENCE= NO +SHOW_INCLUDE_FILES = YES +SHOW_GROUPED_MEMB_INC = NO +FORCE_LOCAL_INCLUDES = NO +INLINE_INFO = YES +SORT_MEMBER_DOCS = YES +SORT_BRIEF_DOCS = NO +SORT_MEMBERS_CTORS_1ST = NO +SORT_GROUP_NAMES = NO +SORT_BY_SCOPE_NAME = NO +STRICT_PROTO_MATCHING = NO +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = YES +SHOW_FILES = YES +SHOW_NAMESPACES = YES +FILE_VERSION_FILTER = +LAYOUT_FILE = +CITE_BIB_FILES = +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = NO +WARN_AS_ERROR = NO +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +INPUT = ../../../src +INPUT_ENCODING = UTF-8 +FILE_PATTERNS = *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.idl *.ddl *.odl *.h *.hh *.hxx *.hpp *.h++ *.cs *.d *.php *.php4 *.php5 *.phtml *.inc *.m *.markdown *.md *.mm *.dox *.py *.pyw *.f90 *.f95 *.f03 *.f08 *.f *.for *.tcl *.vhd *.vhdl *.ucf *.qsf +RECURSIVE = YES +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = */.git/* */.svn/* */.hg/* */CMakeFiles/* */_CPack_Packages/* DartConfiguration.tcl CMakeLists.txt CMakeCache.txt +EXCLUDE_SYMBOLS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = * +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_PATTERNS = +FILTER_SOURCE_FILES = NO +FILTER_SOURCE_PATTERNS = +SOURCE_BROWSER = NO +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = NO +REFERENCES_RELATION = NO +REFERENCES_LINK_SOURCE = YES +SOURCE_TOOLTIPS = YES +USE_HTAGS = NO +VERBATIM_HEADERS = YES +CLANG_ASSISTED_PARSING = NO +CLANG_OPTIONS = +ALPHABETICAL_INDEX = YES +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +GENERATE_HTML = NO +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_EXTRA_STYLESHEET = +HTML_EXTRA_FILES = +HTML_COLORSTYLE_HUE = 220 +HTML_COLORSTYLE_SAT = 100 +HTML_COLORSTYLE_GAMMA = 80 +HTML_TIMESTAMP = NO +HTML_DYNAMIC_SECTIONS = NO +HTML_INDEX_NUM_ENTRIES = 100 +GENERATE_DOCSET = NO +DOCSET_FEEDNAME = "Doxygen generated docs" +DOCSET_BUNDLE_ID = org.doxygen.Project +DOCSET_PUBLISHER_ID = org.doxygen.Publisher +DOCSET_PUBLISHER_NAME = Publisher +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +CHM_INDEX_ENCODING = +BINARY_TOC = NO +TOC_EXPAND = NO +GENERATE_QHP = NO +QCH_FILE = +QHP_NAMESPACE = org.doxygen.Project +QHP_VIRTUAL_FOLDER = doc +QHP_CUST_FILTER_NAME = +QHP_CUST_FILTER_ATTRS = +QHP_SECT_FILTER_ATTRS = +QHG_LOCATION = +GENERATE_ECLIPSEHELP = NO +ECLIPSE_DOC_ID = org.doxygen.Project +DISABLE_INDEX = NO +GENERATE_TREEVIEW = YES +ENUM_VALUES_PER_LINE = 4 +TREEVIEW_WIDTH = 250 +EXT_LINKS_IN_WINDOW = NO +FORMULA_FONTSIZE = 10 +FORMULA_TRANSPARENT = YES +USE_MATHJAX = NO +MATHJAX_FORMAT = HTML-CSS +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest +MATHJAX_EXTENSIONS = +MATHJAX_CODEFILE = +SEARCHENGINE = YES +SERVER_BASED_SEARCH = NO +EXTERNAL_SEARCH = NO +SEARCHENGINE_URL = +SEARCHDATA_FILE = searchdata.xml +EXTERNAL_SEARCH_ID = +EXTRA_SEARCH_MAPPINGS = +GENERATE_LATEX = NO +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4 +EXTRA_PACKAGES = +LATEX_HEADER = +LATEX_FOOTER = +LATEX_EXTRA_STYLESHEET = +LATEX_EXTRA_FILES = +PDF_HYPERLINKS = YES +USE_PDFLATEX = YES +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +LATEX_SOURCE_CODE = NO +LATEX_BIB_STYLE = plain +LATEX_TIMESTAMP = NO +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +RTF_SOURCE_CODE = NO +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_SUBDIR = +MAN_LINKS = NO +GENERATE_XML = YES +XML_OUTPUT = xml +XML_PROGRAMLISTING = YES +GENERATE_DOCBOOK = NO +DOCBOOK_OUTPUT = docbook +DOCBOOK_PROGRAMLISTING = NO +GENERATE_AUTOGEN_DEF = NO +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +EXTERNAL_PAGES = YES +PERL_PATH = /usr/bin/perl +CLASS_DIAGRAMS = YES +MSCGEN_PATH = +DIA_PATH = +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = YES +DOT_NUM_THREADS = 0 +DOT_FONTNAME = Helvetica +DOT_FONTSIZE = 10 +DOT_FONTPATH = +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +GROUP_GRAPHS = YES +UML_LOOK = NO +UML_LIMIT_NUM_FIELDS = 10 +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = NO +CALLER_GRAPH = NO +GRAPHICAL_HIERARCHY = YES +DIRECTORY_GRAPH = YES +DOT_IMAGE_FORMAT = png +INTERACTIVE_SVG = NO +DOT_PATH = /usr/bin +DOTFILE_DIRS = +MSCFILE_DIRS = +DIAFILE_DIRS = +PLANTUML_JAR_PATH = +PLANTUML_CFG_FILE = +PLANTUML_INCLUDE_PATH = +DOT_GRAPH_MAX_NODES = 50 +MAX_DOT_GRAPH_DEPTH = 0 +DOT_TRANSPARENT = NO +DOT_MULTI_TARGETS = YES +GENERATE_LEGEND = YES +DOT_CLEANUP = YES diff --git a/doc/sphinx/source/about/about.rst b/doc/sphinx/source/about/about.rst new file mode 100644 index 00000000..52e76402 --- /dev/null +++ b/doc/sphinx/source/about/about.rst @@ -0,0 +1,53 @@ +About +===== + + + +License +~~~~~~~ + +PopSift is licensed under `MPLv2 license `_. + +More info about the license and what you can do with the code can be found at `tldrlegal website `_ + +SIFT was patented in the United States from 1999-03-08 to 2020-03-28. +See the `patent link `_ for more information. +PopSift license only concerns the PopSift source code and does not release users of this code from any requirements that may arise from patents. + +Contact us +~~~~~~~~~~ + +You can contact us on the public mailing list at +`alicevision@googlegroups.com `_ + +You can also contact us privately at +`alicevision-team@googlegroups.com `_ + + +Cite us +~~~~~~~ + +If you want to cite this work in your publication, please use the following + +.. code:: bibtex + + @inproceedings{Griwodz2018Popsift, + author = {Griwodz, Carsten and Calvet, Lilian and Halvorsen, P{\aa}l}, + title = {Popsift: A Faithful SIFT Implementation for Real-time Applications}, + booktitle = {Proceedings of the 9th {ACM} Multimedia Systems Conference}, + series = {MMSys '18}, + year = {2018}, + isbn = {978-1-4503-5192-8}, + location = {Amsterdam, Netherlands}, + pages = {415--420}, + numpages = {6}, + doi = {10.1145/3204949.3208136}, + acmid = {3208136}, + publisher = {ACM}, + address = {New York, NY, USA}, + } + +Acknowledgements +~~~~~~~~~~~~~~~~ + +This has been developed in the context of the `European project POPART `_ founded by European Union’s Horizon 2020 research and innovation programme under `grant agreement No 644874 `_. \ No newline at end of file diff --git a/doc/sphinx/source/api/api.rst b/doc/sphinx/source/api/api.rst new file mode 100644 index 00000000..5e9ef3cc --- /dev/null +++ b/doc/sphinx/source/api/api.rst @@ -0,0 +1,25 @@ +API References +============== + + +Main Classes +~~~~~~~~~~~~ + +.. doxygenclass:: SiftJob + :members: + +.. doxygenclass:: PopSift + :members: + +.. doxygenstruct:: popsift::Config + :members: + + +Functions +~~~~~~~~~ + + + + +Utility Classes +~~~~~~~~~~~~~~~ diff --git a/doc/sphinx/source/api/usage.rst b/doc/sphinx/source/api/usage.rst new file mode 100644 index 00000000..b226d240 --- /dev/null +++ b/doc/sphinx/source/api/usage.rst @@ -0,0 +1,13 @@ +Library usage +============= + + + + +Detection +~~~~~~~~~ + + + + + diff --git a/doc/sphinx/source/biblio.bib b/doc/sphinx/source/biblio.bib new file mode 100644 index 00000000..f57013dd --- /dev/null +++ b/doc/sphinx/source/biblio.bib @@ -0,0 +1,25 @@ +@inproceedings{Griwodz2018Popsift, + author = {Griwodz, Carsten and Calvet, Lilian and Halvorsen, P{\aa}l}, + title = {Popsift: A Faithful SIFT Implementation for Real-time Applications}, + booktitle = {Proceedings of the 9th {ACM} Multimedia Systems Conference}, + series = {MMSys '18}, + year = {2018}, + isbn = {978-1-4503-5192-8}, + location = {Amsterdam, Netherlands}, + pages = {415--420}, + numpages = {6}, + doi = {10.1145/3204949.3208136}, + acmid = {3208136}, + publisher = {ACM}, + address = {New York, NY, USA}, +} + +@article{Lowe2003, + author = {Lowe, DG}, + doi = {10.1023/B:VISI.0000029664.99615.94}, + file = {:home/alcov/.local/share/data/Mendeley Ltd./Mendeley Desktop/Downloaded/Lowe - 2004 - Distinctive image features from scale-invariant keypoints.pdf:pdf}, + journal = {International journal of computer vision}, + pages = {1--29}, + title = {{Distinctive image features from scale-invariant keypoints}}, + year = {2004} +} diff --git a/doc/sphinx/source/bibliography.rst b/doc/sphinx/source/bibliography.rst new file mode 100644 index 00000000..3e04dc7d --- /dev/null +++ b/doc/sphinx/source/bibliography.rst @@ -0,0 +1,5 @@ +Bibliography +============ + +.. bibliography:: biblio.bib + :all: \ No newline at end of file diff --git a/doc/sphinx/source/conf.py b/doc/sphinx/source/conf.py new file mode 100644 index 00000000..b85cd593 --- /dev/null +++ b/doc/sphinx/source/conf.py @@ -0,0 +1,84 @@ +# Configuration file for the Sphinx documentation builder. +# +# This file only contains a selection of the most common options. For a full +# list see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +# import os +# import sys +# sys.path.insert(0, os.path.abspath('.')) + +import subprocess, os + +def configure_doxyfile(input_dir, output_dir): + with open('Doxyfile.in', 'r') as file : + filedata = file.read() + + filedata = filedata.replace('@DOXYGEN_INPUT_DIR@', input_dir) + filedata = filedata.replace('@DOXYGEN_OUTPUT_DIR@', output_dir) + + with open('Doxyfile', 'w') as file: + file.write(filedata) + +# Check if we're running on Read the Docs' servers +read_the_docs_build = os.environ.get('READTHEDOCS', None) == 'True' + +breathe_projects = {} + +if read_the_docs_build: + # run doxygen before to generate the xml + output_dir = '../build' + subprocess.call('doxygen', shell=True) + breathe_projects['PopSift'] = output_dir + '/xml' + + + + +# -- Project information ----------------------------------------------------- + +project = u'PopSift' +copyright = '2020, AliceVision' +author = 'AliceVision' + + +# -- General configuration --------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = ['breathe', 'sphinxcontrib.bibtex'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = [] + +source_suffix = ['.rst', '.md'] + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = 'sphinx_rtd_theme' + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# breathe_projects = { +# "PopSift": "../../doxygen/xml/", +# } + +# Breathe Configuration +breathe_default_project = 'PopSift' \ No newline at end of file diff --git a/doc/sphinx/source/index.rst b/doc/sphinx/source/index.rst new file mode 100644 index 00000000..457d54ca --- /dev/null +++ b/doc/sphinx/source/index.rst @@ -0,0 +1,36 @@ +PopSift Library +============= + +PopSift is an open-source implementation of the SIFT algorithm in CUDA :cite:`Griwodz2018Popsift`. +PopSift tries to stick as closely as possible to David Lowe's famous paper :cite:`Lowe2003`, while extracting features from an image in real-time at least on an NVidia GTX 980 Ti GPU. + + +.. toctree:: + :maxdepth: 2 + :hidden: + :caption: Install + + install/install + +.. toctree:: + :maxdepth: 2 + :hidden: + :caption: API Documentation + + api/usage + api/api + + +.. toctree:: + :maxdepth: 2 + :hidden: + :caption: About + + about/about + +.. toctree:: + :maxdepth: 2 + :hidden: + :caption: References + + bibliography diff --git a/doc/sphinx/source/install/install.rst b/doc/sphinx/source/install/install.rst new file mode 100644 index 00000000..fb6eb014 --- /dev/null +++ b/doc/sphinx/source/install/install.rst @@ -0,0 +1,250 @@ +Requirements +============ + +Hardware +~~~~~~~~ + +PopSift is a GPU implementation that requires an NVIDIA GPU card with a CUDA compute capability >= 3.0 (including, e.g. the GT 650M). +The code is originally developed with the compute capability 5.2 card GTX 980 Ti in mind. + +You can check your `NVIDIA GPU card CC support here `_ or on the `NVIDIA dev page `_. +If you do not have a NVIDIA card you will still able to compile and use the CPU version. + +Here are the minimum hardware requirements for PopSift: + ++--------------------------------------------------------------------------+ +| Minimum requirements | ++===================+======================================================+ +| Operating systems | Windows x64, Linux, macOS | ++-------------------+------------------------------------------------------+ +| CPU | Recent Intel or AMD cpus | ++-------------------+------------------------------------------------------+ +| RAM Memory | 8 GB | ++-------------------+------------------------------------------------------+ +| Hard Drive | No particular requirements | ++-------------------+------------------------------------------------------+ +| GPU | NVIDIA CUDA-enabled GPU (compute capability >= 3.5) | ++-------------------+------------------------------------------------------+ + + + +Software +~~~~~~~~ + +The core library depends only on Cuda >= 7.0 + +The library includes a few sample applications that show how to use the library. +They require + +* Boost >= 1.55 (required components atomic, chrono, date-time, system, thread) + +* [optionally] DevIL (libdevil-dev) can be used to load a broader range of image formats, otherwise only pgm is supported. + + + +------------ + + +vcpkg +===== + +`vcpkg `_ is a cross-platform (Windows, Linux and MacOS), open-source package manager created by Microsoft. + +We are planning to release a port of the library so that it can be easily built using the package manager on all supported platforms. +Stay tuned! + + +------------ + +Building the library +==================== + +Building tools +~~~~~~~~~~~~~~ + +Required tools: + +* CMake >= 3.14 to build the code +* Git +* C/C++ compiler supporting the C++11 standard (gcc >= 4.6 or visual studio or clang) +* CUDA >= 7.0 + + + +Dependencies +~~~~~~~~~~~~ + +vcpkg ++++++ + +vcpkg can be used to install all the dependencies on all the supported platforms. +This is particularly useful on Windows. +To install the dependencies: + +.. code:: shell + + vcpkg install cuda devil boost-system boost-program-options boost-thread boost-filesystem + +You can add the flag :code:`--triplet` to specify the architecture and the version you want to build. +For example: + +* :code:`--triplet x64-windows` will build the dynamic version for Windows 64 bit + +* :code:`--triplet x64-windows-static` will build the static version for Windows 64 bit + +* :code:`--triplet x64-linux-dynamic` will build the dynamic version for Linux 64 bit + +and so on. +More information can be found `here `_ + +Linux ++++++ + +On Linux you can install from the package manager: + +For Ubuntu/Debian package system: + +.. code:: shell + + sudo apt-get install g++ git-all libboost-all-dev libdevil-dev + + +For CentOS package system: + +.. code:: shell + + sudo yum install gcc-c++ git boost-devel devil + + +MacOS ++++++ + +On MacOs using `Homebrew `_ install the following packages: + +.. code:: shell + + brew install git boost devil + + +Getting the sources +~~~~~~~~~~~~~~~~~~~~ + +.. code:: shell + + git clone https://github.com/alicevision/PopSift.git + + +CMake configuration +~~~~~~~~~~~~~~~~~~~ + +From PopSift root folder you can run cmake: + +.. code:: shell + + mkdir build && cd build + cmake .. + make -j `nproc` + +On Windows add :code:`-G "Visual Studio 16 2019" -A x64` to generate the Visual Studio solution according to your VS version (`see CMake documentation `_). + +If you are using the dependencies built with VCPKG you need to pass :code:`-DCMAKE_TOOLCHAIN_FILE=path/to/vcpkg/scripts/buildsystems/vcpkg.cmake` at cmake step to let it know where to find the dependencies. + + +CMake options ++++++++++++++ + +CMake configuration can be controlled by changing the values of the following variables (here with their default value) + + +* :code:`BUILD_SHARED_LIBS:BOOL=ON` to enable/disable the building shared libraries + +* :code:`PopSift_BUILD_EXAMPLES:BOOL=ON` to enable/disable the building of applications + +* :code:`PopSift_BUILD_DOC:BOOL=OFF` to enable/disable building this documentation and the Doxygen one. + +For example, if you do not want to build the applications, you have to pass :code:`-DPopSift_BUILD_EXAMPLES:BOOL=OFF` and so on. + + +------------ + + +PopSift as third party +==================== + +When you install PopSift a file :code:`PopSiftConfig.cmake` is installed in :code:`/lib/cmake/PopSift/` that allows you to import the library in your CMake project. +In your :code:`CMakeLists.txt` file you can add the dependency in this way: + +.. code-block:: + :linenos: + + # Find the package from the PopSiftConfig.cmake + # in /lib/cmake/PopSift/. Under the namespace PopSift:: + # it exposes the target PopSift that allows you to compile + # and link with the library + find_package(PopSift CONFIG REQUIRED) + ... + # suppose you want to try it out in a executable + add_executable(popsiftTest yourfile.cpp) + # add link to the library + target_link_libraries(popsiftTest PUBLIC PopSift::PopSift) + +Then, in order to build just pass the location of :code:`PopSiftConfig.cmake` from the cmake command line: + +.. code:: shell + + cmake .. -DPopSift_DIR=/lib/cmake/PopSift/ + + +------------ + + + +Docker image +============ + +A docker image can be built using the Ubuntu based :code:`Dockerfile`, which is based on nvidia/cuda image (https://hub.docker.com/r/nvidia/cuda/ ) + + +Building the dependency image +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +We provide a :code:`Dockerfile_deps` containing a cuda image with all the necessary PopSift dependencies installed. + +A parameter :code:`CUDA_TAG` can be passed when building the image to select the cuda version. +Similarly, :code:`OS_TAG` can be passed to select the Ubuntu version. +By default, :code:`CUDA_TAG=10.2` and :code:`OS_TAG=18.04` + +For example to create the dependency image based on ubuntu 18.04 with cuda 8.0 for development, use + +.. code:: shell + + docker build --build-arg CUDA_TAG=8.0 --tag alicevision/popsift-deps:cuda8.0-ubuntu18.04 -f Dockerfile_deps . + +The complete list of available tags can be found on the nvidia [dockerhub page](https://hub.docker.com/r/nvidia/cuda/) + + +Building the PopSift image +~~~~~~~~~~~~~~~~~~~~~~~~ + +Once you built the dependency image, you can build the popsift image in the same manner using :code:`Dockerfile`: + +.. code:: shell + + docker build --tag alicevision/popsift:cuda8.0-ubuntu18.04 . + + +Running the PopSift image +~~~~~~~~~~~~~~~~~~~~~~~ + +In order to run the image nvidia docker is needed: see the `installation instruction `_. +Once installed, the docker can be run, e.g., in interactive mode with + +.. code:: shell + + docker run -it --runtime=nvidia alicevision/popsift:cuda8.0-ubuntu18.04 + + +Official images on DockeHub +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Check the docker hub `PopSift repository `_ for the available images. \ No newline at end of file diff --git a/src/popsift/common/device_prop.h b/src/popsift/common/device_prop.h index 8828fd4a..ed5db2b2 100644 --- a/src/popsift/common/device_prop.h +++ b/src/popsift/common/device_prop.h @@ -10,8 +10,12 @@ #include #include -namespace popsift { namespace cuda { +namespace popsift { +namespace cuda { +/** + * @brief A class to recover, query and print the information about the cuda device. + */ class device_prop_t { int _num_devices; @@ -27,36 +31,48 @@ class device_prop_t device_prop_t( ); ~device_prop_t( ); + /** + * @brief Print the information about the device. + */ void print( ); + + /** + * @brief Set the device to use. + * @param[in] n The index of the device to use. + * @param[in] print_choice Whether to print information about the chosen device. + */ void set( int n, bool print_choice = false ); - /** Check if a request exceeds the current CUDA device's limit in + /** + * @brief Check if a request exceeds the current CUDA device's limit in * texture2Dlinear dimensions. texture2Dlinear is based on CUDA memory that * can be accessed directly (i.e. no CudaArray). * @param[in,out] width Desired width of the texture. * @param[in,out] height Desired height of the texture. * @param[in] printWarn if true, print warnings to cerr if desired width * or height exceeds limits. - * @return { true if the desired width and height are possible. - * false if one or both of the desired width and height are impossible. - * The desired width or height (or both) are replaced by the limit.} + * @return \p true if the desired width and height are possible. + * \p false if one or both of the desired width and height are impossible. + * The desired width or height (or both) are replaced by the limit. */ bool checkLimit_2DtexLinear( int& width, int& height, bool printWarn ) const; - /** Check if a request exceeds the current CUDA device's limit in + /** + * @brief Check if a request exceeds the current CUDA device's limit in * texture2D dimensions. texture2D is based on CUDA Arrays, which have * invisible layout and can only be filled with cudaMemcpy. * @param[in,out] width Desired width of the texture. * @param[in,out] height Desired height of the texture. * @param[in] printWarn if true, print warnings to cerr if desired width * or height exceeds limits. - * @return { true if the desired width and height are possible. - * false if one or both of the desired width and height are impossible. - * The desired width or height (or both) are replaced by the limit.} + * @return \p true if the desired width and height are possible. + * \p false if one or both of the desired width and height are impossible. + * The desired width or height (or both) are replaced by the limit. */ bool checkLimit_2DtexArray( int& width, int& height, bool printWarn ) const; - /** Check if a request exceeds the current CUDA device's limit in + /** + * @brief Check if a request exceeds the current CUDA device's limit in * texture2DLayered dimensions. texture2DLayered refers to a 3D structure, where * interpolation happens only in 3D, effectively creating layers. * @param[in,out] width Desired width of the texture. @@ -64,15 +80,16 @@ class device_prop_t * @param[in,out] layers Desired depth of the texture. * @param[in] printWarn if true, print warnings to cerr if desired width * or height exceeds limits. - * @return { true if the desired width, height and depth are possible. - * false if one or both of the desired width and height are impossible. + * @return \p true if the desired width, height and depth are possible. + * \p false if one or both of the desired width and height are impossible. * The desired width, height and layers are replaced by the limit - * if they exceed it.} + * if they exceed it. */ bool checkLimit_2DtexLayered( int& width, int& height, int& layers, bool printWarn ) const; - /** Check if a request exceeds the current CUDA device's limit in + /** + * @brief Check if a request exceeds the current CUDA device's limit in * surface2DLayered dimensions. surface2DLayered is the writable equivalent * to texture2DLayered, but the width must be given in bytes, not elements. * Since we use float, images cannot be as wide as expected. @@ -81,10 +98,10 @@ class device_prop_t * @param[in,out] layers Desired depth of the texture. * @param[in] printWarn if true, print warnings to cerr if desired width * or height exceeds limits. - * @return { true if the desired width, height and depth are possible. - * false if one or both of the desired width and height are impossible. + * @return \p true if the desired width, height and depth are possible. + * \p false if one or both of the desired width and height are impossible. * The desired width, height and layers are replaced by the limit - * if they exceed it.} + * if they exceed it. */ bool checkLimit_2DsurfLayered( int& width, int& height, int& layers, bool printWarn ) const; diff --git a/src/popsift/features.h b/src/popsift/features.h index 1e1a31dd..3b16f954 100755 --- a/src/popsift/features.h +++ b/src/popsift/features.h @@ -16,7 +16,8 @@ namespace popsift { struct Descriptor; // float features[128]; -/* This is a data structure that is returned to a calling program. +/** + * @brief This is a data structure that is returned to a calling program. * The xpos/ypos information in feature is scale-adapted. */ struct Feature @@ -24,9 +25,11 @@ struct Feature int debug_octave; float xpos; float ypos; - float sigma; // scale; - int num_ori; // number of this extremum's orientations - // remaining entries in desc are 0 + /// scale + float sigma; + /// number of this extremum's orientations + /// remaining entries in desc are 0 + int num_ori; float orientation[ORIENTATION_MAX_COUNT]; Descriptor* desc[ORIENTATION_MAX_COUNT]; @@ -52,7 +55,8 @@ class FeaturesBase inline void setDescriptorCount( int num_ori ) { _num_ori = num_ori; } }; -/* This is a data structure that is returned to a calling program. +/** + * @brief This is a data structure that is returned to a calling program. * _ori is a transparent flat memory holding descriptors * that are referenced by the extrema. * @@ -93,7 +97,7 @@ class FeaturesHost : public FeaturesBase friend class Pyramid; }; -typedef FeaturesHost Features; +using Features = FeaturesHost; std::ostream& operator<<( std::ostream& ostr, const FeaturesHost& feature ); diff --git a/src/popsift/popsift.h b/src/popsift/popsift.h index 631a7196..446e103a 100755 --- a/src/popsift/popsift.h +++ b/src/popsift/popsift.h @@ -52,16 +52,38 @@ class SiftJob #endif public: - /** Constructor for byte images, value range 0..255 */ + + /** + * @brief Constructor for byte images, value range 0..255 + * @param[in] w the width in pixel of the image + * @param[in] h the height in pixel of the image + * @param[in] imageData the image buffer + */ SiftJob( int w, int h, const unsigned char* imageData ); - /** Constructor for float images, value range [0..1[ */ + /** + * @brief Constructor for float images, value range [0..1[ + * @param[in] w the width in pixel of the image + * @param[in] h the height in pixel of the image + * @param[in] imageData the image buffer + */ SiftJob( int w, int h, const float* imageData ); + /** + * @brief Destructor releases all the resources. + */ ~SiftJob( ); - popsift::FeaturesHost* get(); // should be deprecated, same as getHost() + /** + * @deprecated + * @see getHost() + */ + popsift::FeaturesHost* get(); popsift::FeaturesBase* getBase(); + /** + * @brief + * @return + */ popsift::FeaturesHost* getHost(); popsift::FeaturesDev* getDev(); @@ -72,6 +94,9 @@ class SiftJob void setFeatures( popsift::FeaturesBase* f ); }; +/** + * @brief + */ class PopSift { struct Pipe @@ -91,16 +116,28 @@ class PopSift }; public: + + /** + * @brief Image modes + */ enum ImageMode { + /// byte image, value range 0..255 ByteImages, + /// float images, value range [0..1[ FloatImages }; + /** + * @brief Results for the allocation test. + */ enum AllocTest { + /// the image dimensions are supported by this device's CUDA texture engine. Ok, + /// the input image size exceeds the dimensions of the CUDA Texture used for loading. ImageExceedsLinearTextureLimit, + /// the scaled input image exceeds the dimensions of the CUDA Surface used for the image pyramid. ImageExceedsLayeredSurfaceLimit }; @@ -109,27 +146,46 @@ class PopSift PopSift() = delete; PopSift(const PopSift&) = delete; - /* We support more than 1 streams, but we support only one sigma and one + /** + * @brief We support more than 1 streams, but we support only one sigma and one * level parameters. */ explicit PopSift( ImageMode imode = ByteImages ); - explicit PopSift( const popsift::Config& config, - popsift::Config::ProcessingMode mode = popsift::Config::ExtractingMode, - ImageMode imode = ByteImages ); + + /** + * @brief + * @param config + * @param mode + * @param imode + */ + explicit PopSift(const popsift::Config& config, + popsift::Config::ProcessingMode mode = popsift::Config::ExtractingMode, + ImageMode imode = ByteImages); + + /** + * @brief Release all the resources. + */ ~PopSift(); public: - /** Provide the configuration if you used the PopSift default - * constructor */ + /** + * @brief Provide the configuration if you used the PopSift default + * constructor + */ bool configure( const popsift::Config& config, bool force = false ); + /** + * @brief Release the resources. + */ void uninit( ); - /** Check whether the current CUDA device can support the image + /** + * @brief Check whether the current CUDA device can support the image * resolution (width,height) with the current configuration * based on the card's texture engine. * The function does not check if there is sufficient available * memory. + * * The first part of the test depends on the parameters width and * height. It checks whether the image size is supported by CUDA * 2D linear textures on this card. This is used to load the image @@ -142,8 +198,9 @@ class PopSift * "levels", because it determines the number of levels in each * octave. The CUDA 2D layered texture must support enough depth * for each level. - * @param width The width of the input image - * @param height The height of the input image + * + * @param[in] width The width of the input image + * @param[in] height The height of the input image * @return AllocTest::Ok if the image dimensions are supported by this device's * CUDA texture engine, * AllocTest::ImageExceedsLinearTextureLimit if the input image size @@ -152,41 +209,60 @@ class PopSift * AllocTest::ImageExceedsLayeredSurfaceLimit if the scaled input * image exceeds the dimensions of the CUDA Surface used for the * image pyramid. The scaling factor must be changes to fit in. - * @remark { If you want to call configure() before extracting features, - * you should call configure() before textTextureFit(). } - * @remark { The current CUDA device is determined by a call to - * cudaGetDevice(), card properties are only read once. } + * @remark * If you want to call configure() before extracting features, + * you should call configure() before textTextureFit(). + * @remark * The current CUDA device is determined by a call to + * cudaGetDevice(), card properties are only read once. + * @see AllocTest */ AllocTest testTextureFit( int width, int height ); - /** Create a warning string for an AllocTest error code. */ + /** + * @brief Create a warning string for an AllocTest error code. + */ std::string testTextureFitErrorString( AllocTest err, int w, int h ); - /** Enqueue a byte image, value range 0..255 */ + /** + * @brief Enqueue a byte image, value range [0,255]. + * @param[in] w the width of the image. + * @param[in] h the height of the image. + * @param[in] imageData the image buffer. + * @return the associated job + * @see SiftJob + */ SiftJob* enqueue( int w, int h, const unsigned char* imageData ); - /** Enqueue a float image, value range 0..1 */ + /** + * @brief Enqueue a float image, value range [0,1]. + * @param[in] w the width of the image. + * @param[in] h the height of the image. + * @param[in] imageData the image buffer. + * @return the associated job + * @see SiftJob + */ SiftJob* enqueue( int w, int h, const float* imageData ); /** * @deprecated - * */ + */ inline void uninit( int /*pipe*/ ) { uninit(); } /** * @deprecated - **/ + */ inline bool init( int /*pipe*/, int w, int h ) { _last_init_w = w; _last_init_h = h; return true; } - /** deprecated */ + /** + * @deprecated + */ inline popsift::FeaturesBase* execute( int /*pipe*/, const unsigned char* imageData ) { SiftJob* j = enqueue( _last_init_w, _last_init_h, imageData ); @@ -201,7 +277,7 @@ class PopSift void private_apply_scale_factor( int& w, int& h ); void uploadImages( ); - /* The following method are alternative worker functions for Jobs submitted by + /* The following methods are alternative worker functions for Jobs submitted by * a calling application. The choice of method is made by the mode parameter * in the PopSift constructor. */ diff --git a/src/popsift/sift_conf.h b/src/popsift/sift_conf.h index ecb5ea2f..583a958c 100644 --- a/src/popsift/sift_conf.h +++ b/src/popsift/sift_conf.h @@ -21,14 +21,22 @@ #else #endif -namespace popsift -{ +namespace popsift { +/** + * @brief Struct containing the parameters that control the extraction algorithm + */ struct Config { - Config( ); + Config(); - enum GaussMode { + /** + * @brief The way the gaussian mode is compute. + * + * Each setting allows to mimic and reproduce the behaviour of other Sift implementations. + */ + enum GaussMode + { VLFeat_Compute, VLFeat_Relative, VLFeat_Relative_All, @@ -37,68 +45,145 @@ struct Config Fixed15 }; - enum SiftMode { + /** + * @brief General setting to reproduce the results of other Sift implementations. + */ + enum SiftMode + { + /// Popsift implementation PopSift, + /// OpenCV implementation OpenCV, + /// VLFeat implementation VLFeat, + /// Default implementation is PopSift Default = PopSift }; - enum LogMode { + /** + * @brief The logging mode. + */ + enum LogMode + { None, All }; - enum ScalingMode { + /** + * @brief The scaling mode. + */ + enum ScalingMode + { ScaleDirect, - ScaleDefault // Indirect - only working method + /// Indirect - only working method + ScaleDefault }; - /* Modes for descriptor extraction: */ - enum DescMode { - Loop, // scan horizontal, extract valid points - ILoop, // scan horizontal, extract valid points, interpolate with tex engine - Grid, // scan in rotated mode, round pixel address - IGrid, // scan in rotated mode, interpolate with tex engine - NoTile // variant of IGrid, no duplicate gradiant fetching + /** + * @brief Modes for descriptor extraction. + */ + enum DescMode + { + /// scan horizontal, extract valid points + Loop, + /// scan horizontal, extract valid points, interpolate with tex engine + ILoop, + /// scan in rotated mode, round pixel address + Grid, + /// scan in rotated mode, interpolate with tex engine + IGrid, + /// variant of IGrid, no duplicate gradient fetching + NoTile }; - enum NormMode { - RootSift, // The L1-inspired norm, gives better matching results - Classic // The L2-inspired norm, all descriptors on a hypersphere + /** + * @brief Type of norm to use for matching. + */ + enum NormMode + { + /// The L1-inspired norm, gives better matching results ("RootSift") + RootSift, + /// The L2-inspired norm, all descriptors on a hypersphere ("classic") + Classic }; - /* To reduce time used in descriptor extraction, some extrema can be filtered + /** + * @brief Filtering strategy. + * + * To reduce time used in descriptor extraction, some extrema can be filtered * immediately after finding them. It is possible to keep those with the largest * scale (LargestScaleFirst), smallest scale (SmallestScaleFirst), or a random * selection. Note that largest and smallest give a stable result, random does not. */ enum GridFilterMode { + /// keep a random selection RandomScale, + /// keep those with the largest scale LargestScaleFirst, + /// keep those with the smallest scale SmallestScaleFirst }; - /* A parameter for the PopSift constructor. Determines which data is kept in - * the Job data structure after processing, which is downloaded to the host, - * which is invalidated. + /** + * @brief Processing mode. + * + * Determines which data is kept in the Job data structure after processing, which one is downloaded to the host, + * which one is invalidated. */ enum ProcessingMode { ExtractingMode, MatchingMode }; + /** + * @brief Set the Gaussian mode from string. + * @param[in] m The string version of the GaussMode + * @see GaussMode + */ void setGaussMode( const std::string& m ); + /** + * @brief Set the Gaussian mode. + * @param[in] m The Gaussian mode to use. + */ void setGaussMode( GaussMode m ); + + /** + * @brief Set the Sift mode. + * @param[in] m The Sift mode + * @see SiftMode + */ void setMode( SiftMode m ); + + /** + * @brief Set the log mode. + * @param mode The log mode. + * @see LogMode + */ void setLogMode( LogMode mode = All ); void setScalingMode( ScalingMode mode = ScaleDefault ); + + /** + * @brief Enable/desable verbose mode. + * @param[in] on Whether to display additional information . + */ void setVerbose( bool on = true ); + + /** + * @brief Set the descriptor mode by string. + * @param[in] byname The string containing the descriptor mode. + * @see DescMode + */ void setDescMode( const std::string& byname ); + + /** + * @brief Set the descriptor mode. + * @param[in] mode The descriptor mode. + * @see DescMode + */ void setDescMode( DescMode mode = Loop ); - void setGaussGroup( int groupsize ); - int getGaussGroup( ) const; +// void setGaussGroup( int groupsize ); +// int getGaussGroup( ) const; void setDownsampling( float v ); void setOctaves( int v ); @@ -107,9 +192,9 @@ struct Config void setEdgeLimit( float v ); void setThreshold( float v ); void setInitialBlur( float blur ); - void setMaxExtreme( int m ); +// void setMaxExtreme( int m ); void setPrintGaussTables( ); - void setDPOrientation( bool on ); +// void setDPOrientation( bool on ); void setFilterMaxExtrema( int extrema ); void setFilterGridSize( int sz ); void setFilterSorting( const std::string& direction ); @@ -118,63 +203,80 @@ struct Config bool hasInitialBlur( ) const; float getInitialBlur( ) const; - // computes the actual peak threshold depending on the threshold - // parameter and the non-augmented number of levels + /// computes the actual peak threshold depending on the threshold + /// parameter and the non-augmented number of levels float getPeakThreshold() const; - // print Gauss spans and tables? + /// print Gauss spans and tables? bool ifPrintGaussTables() const; - // What Gauss filter scan is desired? + /// What Gauss filter scan is desired? GaussMode getGaussMode( ) const; - // Call this from the constructor. + /// Call this from the constructor. static GaussMode getGaussModeDefault( ); + // Helper functions for the main program's usage string. + /** + * @brief Get a message with the strings to use for setting the values of \p GaussMode + * @return A message with the list of strings + */ static const char* getGaussModeUsage( ); - // get the SIFT mode for more detailed sub-modes + /** + * @brief Get the SIFT mode for more detailed sub-modes + * @return The SiftMode + * @see SiftMode + */ SiftMode getSiftMode() const; - // find out if we should print logging info or not + /// find out if we should print logging info or not LogMode getLogMode() const; - // The number of octaves is chosen freely. If not specified, - // it is: log_2( min(x,y) ) - 3 - start_sampling + /// The number of octaves is chosen freely. If not specified, + /// it is: log_2( min(x,y) ) - 3 - start_sampling int octaves; - // The number of levels per octave. This is actually the - // number of inner DoG levels where we can search for - // feature points. The number of ... - // - // This is the non-augmented number of levels, meaning - // the this is not the number of gauss-filtered picture - // layers (which is levels+3), but the number of DoG - // layers in which we can search for extrema. + /// The number of levels per octave. This is actually the + /// number of inner DoG levels where we can search for + /// feature points. The number of ... + /// + /// This is the non-augmented number of levels, meaning + /// the this is not the number of gauss-filtered picture + /// layers (which is levels+3), but the number of DoG + /// layers in which we can search for extrema. int levels; float sigma; - // default edge_limit 16.0f from Celebrandil - // default edge_limit 10.0f from Bemap + /// default edge_limit 16.0f from Celebrandil + /// default edge_limit 10.0f from Bemap float _edge_limit; /** Functions related to descriptor normalization: L2-like or RootSift */ void setNormMode( NormMode m ); void setNormMode( const std::string& m ); + /** + * @brief Set the normalization mode. + * @param[in] on Use RootSift (\p true) or the L2-norm (\p false). + * @deprecated + * @see NormMode + */ DEPRECATED(void setUseRootSift( bool on )); bool getUseRootSift( ) const; NormMode getNormMode( NormMode m ) const; static NormMode getNormModeDefault( ); // Call this from the constructor. static const char* getNormModeUsage( ); // Helper functions for the main program's usage string. - /** Functions related to descriptor normalization: multiply with a power of 2 + /** + * @brief Functions related to descriptor normalization: multiply with a power of 2 */ int getNormalizationMultiplier( ) const; void setNormalizationMultiplier( int mul ); - /* The input image is stretched by 2^upscale_factor + /** + * @brief The input image is stretched by 2^upscale_factor * before processing. The factor 1 is default. */ inline float getUpscaleFactor( ) const { @@ -185,125 +287,124 @@ struct Config return _max_extrema; } - /* Have we enabled filtering? This is a compile time decision. + /** + * Have we enabled filtering? This is a compile time decision. * The reason is that we use Thrust, which increases compile * considerably and can be deactivated at the CMake level when * you work on something else. */ bool getCanFilterExtrema() const; - /* Set the approximate number of extrema whose orientation and descriptor + /** + * Set the approximate number of extrema whose orientation and descriptor * should be computed. Default is -1, which sets the hard limit defined * by "number of octaves * getMaxExtrema()". */ - int getFilterMaxExtrema( ) const { - return _filter_max_extrema; - } + int getFilterMaxExtrema() const { return _filter_max_extrema; } - /* To avoid that grid filtering happens only in a tiny piece of an image, + /** + * @brief Get the grid size for filtering. + * + * To avoid that grid filtering happens only in a tiny piece of an image, * the image is split into getFilterGridSize() X getFilterGridSize() tiles * and we allow getFilterMaxExtrema() / getFilterGridSize() extrema in * each tile. */ - int getFilterGridSize( ) const { - return _filter_grid_size; - } + int getFilterGridSize() const { return _filter_grid_size; } - /* See enum GridFilterMode */ - GridFilterMode getFilterSorting() const { - return _grid_filter_mode; - } + /** + * @brief Get the filtering mode. + * @return the filtering mode. + * @see GridFilterMode + */ + GridFilterMode getFilterSorting() const { return _grid_filter_mode; } - // check if we use direct downscaling from input image - // for all octaves - inline ScalingMode getScalingMode() const { - return _scaling_mode; - } + /** + * @brief Get the scaling mode. + * @return the descriptor extraction mode. + * @see ScalingMode + */ + inline ScalingMode getScalingMode() const { return _scaling_mode; } - inline DescMode getDescMode() const { - return _desc_mode; - } + /** + * @brief Get the descriptor extraction mode + * @return the descriptor extraction mode + * @see DescMode + */ + inline DescMode getDescMode() const { return _desc_mode; } bool equal( const Config& other ) const; private: - // default threshold 0.0 default of vlFeat - // default threshold 5.0 / 256.0 - // default threshold 15.0 / 256.0 - it seems our DoG is really small ??? - // default threshold 5.0 from Celebrandil, not happening in our data - // default threshold 0.04 / (_levels-3.0) / 2.0f * 255 - // from Bemap -> 1.69 (makes no sense) + /// default threshold 0.0 default of vlFeat + /// default threshold 5.0 / 256.0 + /// default threshold 15.0 / 256.0 - it seems our DoG is really small ??? + /// default threshold 5.0 from Celebrandil, not happening in our data + /// default threshold 0.04 / (_levels-3.0) / 2.0f * 255 + /// from Bemap -> 1.69 (makes no sense) float _threshold; - // determine the image format of the first octave - // relative to the input image's size (x,y) as follows: - // (x / 2^start_sampling, y / 2^start_sampling ) + /// determine the image format of the first octave + /// relative to the input image's size (x,y) as follows: + /// (x / 2^start_sampling, y / 2^start_sampling ) float _upscale_factor; - // default LogMode::None + /// default LogMode::None LogMode _log_mode; - // default: ScalingMode::DownscaledOctaves + /// default: ScalingMode::DownscaledOctaves ScalingMode _scaling_mode; - // default: DescMode::Loop + /// default: DescMode::Loop DescMode _desc_mode; - // default: RandomScale + /// default: RandomScale GridFilterMode _grid_filter_mode; public: bool verbose; private: - /* The number of initial extrema that can be discovered in an octave. - * This parameter changes memory requirements. - */ + /// The number of initial extrema that can be discovered in an octave. + /// This parameter changes memory requirements. int _max_extrema; - /* The maximum number of extrema that are returned. There may be - * several descriptors for each extremum. - */ + /// The maximum number of extrema that are returned. There may be + /// several descriptors for each extremum. int _filter_max_extrema; - // Used to achieve an approximation of _max_entrema - // Subdivide the image in this number of vertical and horizontal tiles, - // i.e. the grid is actually _grid_size X _grid_size tiles. - // default: 1 + /// Used to achieve an approximation of _max_entrema + /// Subdivide the image in this number of vertical and horizontal tiles, + /// i.e. the grid is actually _grid_size X _grid_size tiles. + /// default: 1 int _filter_grid_size; - /* Modes are computation according to VLFeat or OpenCV, - * or fixed size. Default is VLFeat mode. - */ + /// Modes are computation according to VLFeat or OpenCV, + /// or fixed size. Default is VLFeat mode. GaussMode _gauss_mode; - /* Modes are PopSift, OpenCV and VLFeat. - * Default is currently identical to PopSift. - */ + /// Modes are PopSift, OpenCV and VLFeat. + /// Default is currently identical to PopSift. SiftMode _sift_mode; - /* VLFeat code assumes that an initial input image is partially blurred. - * This changes the blur computation for the very first level of the first - * octave, turning it into a special case. - */ + /// VLFeat code assumes that an initial input image is partially blurred. + /// This changes the blur computation for the very first level of the first + /// octave, turning it into a special case. bool _assume_initial_blur; float _initial_blur; - /* OpenMVG requires a normalization named rootSift, the - * classical L2-inspired mode is also supported. - */ + /// OpenMVG requires a normalization named rootSift, the + /// classical L2-inspired mode is also supported. NormMode _normalization_mode; - /* SIFT descriptors are normalized in a final step. - * The values of the descriptor can also be multiplied - * by a power of 2 if required. - * Specify the exponent. - */ + /// SIFT descriptors are normalized in a final step. + /// The values of the descriptor can also be multiplied + /// by a power of 2 if required. + /// Specify the exponent. int _normalization_multiplier; - /* Call the debug functions in gauss_filter.cu to print Gauss - * filter width and Gauss tables in use. - */ + /// Call the debug functions in gauss_filter.cu to print Gauss + /// filter width and Gauss tables in use. bool _print_gauss_tables; }; diff --git a/src/popsift/sift_extremum.h b/src/popsift/sift_extremum.h index c3e41954..0363a02e 100755 --- a/src/popsift/sift_extremum.h +++ b/src/popsift/sift_extremum.h @@ -14,7 +14,8 @@ namespace popsift { -/* This is an internal data structure. +/** + * @brief This is an internal data structure. * Separated from the final Extremum data structure to implement * grid filtering in a space-efficient manner. In grid filtering, * extrema are first found, after that some may be discarded in @@ -25,14 +26,20 @@ struct InitialExtremum { float xpos; float ypos; - int lpos; // extremum refined into this level - float sigma; // scale; - int cell; // index into the grid for grid-based extrema filtering - bool ignore; // true if this extremum has been filtered - int write_index; // if any initial extrema are ignored, new index for Extremum + /// extremum refined into this level + int lpos; + /// scale + float sigma; + /// index into the grid for grid-based extrema filtering + int cell; + /// true if this extremum has been filtered + bool ignore; + /// if any initial extrema are ignored, new index for Extremum + int write_index; }; -/* This is an internal data structure. +/** + * @brief This is an internal data structure. * For performance reasons, it would be appropriate to split * the first 4 values from the rest of this structure. Right * now, descriptor computation is a bigger concern. @@ -41,16 +48,22 @@ struct Extremum { float xpos; float ypos; - int lpos; // extremum refined into this level - float sigma; // scale; + /// extremum refined into this level + int lpos; + /// scale + float sigma; - int octave; // belonging to this octave - int num_ori; // number of this extremum's orientations - int idx_ori; // exclusive prefix sum of the layer's orientations + /// belonging to this octave + int octave; + /// number of this extremum's orientations + int num_ori; + /// exclusive prefix sum of the layer's orientations + int idx_ori; float orientation[ORIENTATION_MAX_COUNT]; }; -/* This is a data structure that is returned to a calling program. +/** + * @brief This is a data structure that is returned to a calling program. * This is the SIFT descriptor itself. */ struct Descriptor diff --git a/src/popsift/sift_octave.h b/src/popsift/sift_octave.h index 927b1cb1..fc2ad13b 100755 --- a/src/popsift/sift_octave.h +++ b/src/popsift/sift_octave.h @@ -131,10 +131,14 @@ class Octave return _dog_3d_tex_linear; } - /** - * alloc() - allocates all GPU memories for one octave - * @param width in floats, not bytes!!! - */ + /** + * @brief Allocates all GPU memories for one octave. + * @param conf + * @param width in floats + * @param height + * @param levels + * @param gauss_group + */ void alloc( const Config& conf, int width, int height,