init
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
build/
|
110
BUILD.md
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
# An Augmented Reality application
|
||||||
|
|
||||||
|
## Building instructions
|
||||||
|
|
||||||
|
Required tools:
|
||||||
|
* C/C++ compiler (gcc >= 4.6 or visual studio or clang)
|
||||||
|
* cmake
|
||||||
|
* [optional] Doxygen and graphviz to generate the htlm documentation
|
||||||
|
|
||||||
|
|
||||||
|
### Dependencies
|
||||||
|
|
||||||
|
The project depends on:
|
||||||
|
|
||||||
|
- OpenCV 2.4.9
|
||||||
|
- OpenGL
|
||||||
|
- GLM ([webpage](http://devernay.free.fr/hacks/glm/)) which provides a more complete interface to the OBJ format (i.e. it manages textures, materials etc.).
|
||||||
|
|
||||||
|
If at any stage you get an error about missing ``Xi`` and ``Xmu`` library, you need to install them. In linux you can do
|
||||||
|
|
||||||
|
```shell
|
||||||
|
sudo apt-get install libxi-dev libxmu-dev.
|
||||||
|
```
|
||||||
|
|
||||||
|
### Setting up and building:
|
||||||
|
|
||||||
|
OpenCV and OpenGL are normally already installed on your machine. In case you may have a look at the next section to install OpenCV on your own machine. As for GLM, it comes with the project, so it will be compiled and built the first time it is needed.
|
||||||
|
|
||||||
|
In order to setting up the project, from the root of the project do:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake ..
|
||||||
|
```
|
||||||
|
|
||||||
|
Then each application can be compiled by simply doing a
|
||||||
|
|
||||||
|
```shell
|
||||||
|
make <filename_without_extension>
|
||||||
|
```
|
||||||
|
|
||||||
|
If you run
|
||||||
|
```shell
|
||||||
|
make help
|
||||||
|
```
|
||||||
|
a list of all possible targets is displayed.
|
||||||
|
|
||||||
|
Remember to set the ``LD_LIBRARY_PATH`` to allow your application to access the ``GLM`` library:
|
||||||
|
```shell
|
||||||
|
export $LD_LIBRARY_PATH=/home/<yourhome>/<path/to/code>/3dparty/glm/build/lib:$LD_LIBRARY_PATH
|
||||||
|
```
|
||||||
|
Also you may want to add the path to OpenCV if they are not installed in the system.
|
||||||
|
|
||||||
|
Finally, as usual, running
|
||||||
|
|
||||||
|
```shell
|
||||||
|
make clean
|
||||||
|
```
|
||||||
|
|
||||||
|
will delete all the executable and the compilation objects.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
In case you want to try the code on a different machine, you need to first install the OpenCV libraries (see next section) and then do
|
||||||
|
|
||||||
|
```shell
|
||||||
|
cmake .. -DOpenCV_DIR=path/to/OpenCVConfig.cmake
|
||||||
|
```
|
||||||
|
|
||||||
|
in order to specify the directory where you build them. More in general, you need to provide the path to the file ``OpenCVConfig.cmake``, which you can find e.g. with
|
||||||
|
|
||||||
|
```shell
|
||||||
|
locate OpenCVConfig.cmake
|
||||||
|
```
|
||||||
|
from your shell.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### Code Documentation
|
||||||
|
|
||||||
|
In order to generate the documentation you need have doxygen and graphviz installed. On linux:
|
||||||
|
```shell
|
||||||
|
sudo apt-get install doxygen graphviz.
|
||||||
|
```
|
||||||
|
|
||||||
|
On Mac OSX with homebrew
|
||||||
|
```shell
|
||||||
|
brew install doxygen graphviz.
|
||||||
|
```
|
||||||
|
|
||||||
|
Then a
|
||||||
|
```shell
|
||||||
|
make doc
|
||||||
|
```
|
||||||
|
will generate the documentation in the ``doc`` folder of your build.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### Installing OpenCV
|
||||||
|
|
||||||
|
You can download the code from [here](http://opencv.org/downloads.html) or clone the [github repository](https://github.com/itseez/opencv)
|
||||||
|
Create a `build` directory where to build the library. It also advisable to set an non-system install directory, so that it will be easier to set up the environment later:
|
||||||
|
|
||||||
|
```
|
||||||
|
mkdir build && cd build && cmake .. -DCMAKE_INSTALL_PREFIX=`pwd`/install
|
||||||
|
make install -j n
|
||||||
|
```
|
||||||
|
|
||||||
|
You can even run ``ccmake ..`` to set up other options (eg. CUDA support).
|
191
CMakeLists.txt
Normal file
|
@ -0,0 +1,191 @@
|
||||||
|
cmake_minimum_required(VERSION 3.1)
|
||||||
|
include(ExternalProject)
|
||||||
|
|
||||||
|
project( TP_Interface_AR VERSION 2020.1.0 LANGUAGES CXX)
|
||||||
|
|
||||||
|
# guard against in-source builds
|
||||||
|
if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR})
|
||||||
|
message(FATAL_ERROR "In-source builds not allowed.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# set the path where we can find the findXXX.cmake
|
||||||
|
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/.cmake)
|
||||||
|
|
||||||
|
# add a search path for the glm libraries
|
||||||
|
# it will work if they are already compiled in /3rdparty
|
||||||
|
if(NOT DEFINED GLM_DIR)
|
||||||
|
set(GLM_DIR ${PROJECT_SOURCE_DIR}/3rdparty/glm/build)
|
||||||
|
endif()
|
||||||
|
list(APPEND CMAKE_LIBRARY_PATH "${GLM_DIR}/lib")
|
||||||
|
list(APPEND CMAKE_INCLUDE_PATH "${GLM_DIR}/include")
|
||||||
|
|
||||||
|
|
||||||
|
# set the output path for the generated files
|
||||||
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
|
||||||
|
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
|
||||||
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib )
|
||||||
|
|
||||||
|
#########################################################
|
||||||
|
# SET COMPILATION FLAGS FOR C++11
|
||||||
|
#########################################################
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
|
#########################################################
|
||||||
|
#
|
||||||
|
# EXTERNAL LIBRARIES
|
||||||
|
#
|
||||||
|
#########################################################
|
||||||
|
|
||||||
|
#########################################################
|
||||||
|
# LIB GLM
|
||||||
|
#########################################################
|
||||||
|
|
||||||
|
#try to find the libraries
|
||||||
|
find_package(GLM )
|
||||||
|
|
||||||
|
if(NOT GLM_FOUND)
|
||||||
|
|
||||||
|
# Fallback is only for *nix systems
|
||||||
|
if(MSVC)
|
||||||
|
message(FATAL_ERROR "You need to provide the location of the GLM library through the GLM_DIR
|
||||||
|
variable, e.g. -DGLM_DIR:PATH=<install path>")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#just to be sure
|
||||||
|
set(GLM_DIR ${PROJECT_SOURCE_DIR}/3rdparty/glm)
|
||||||
|
|
||||||
|
# set(EP_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/3rdpary)
|
||||||
|
# set_property(DIRECTORY PROPERTY EP_BASE ${PROJECT_SOURCE_DIR}/3rdparty)
|
||||||
|
ExternalProject_Add( glm
|
||||||
|
URL http://devernay.free.fr/hacks/glm/glm-0.3.2.tar.gz
|
||||||
|
PREFIX ${GLM_DIR}
|
||||||
|
BUILD_IN_SOURCE 1
|
||||||
|
INSTALL_DIR ${GLM_DIR}/build
|
||||||
|
CONFIGURE_COMMAND ./configure --prefix=${GLM_DIR}/build --enable-shared
|
||||||
|
BUILD_COMMAND make -j 4
|
||||||
|
INSTALL_COMMAND make install)
|
||||||
|
|
||||||
|
ExternalProject_Get_Property(glm install_dir)
|
||||||
|
message( "lib glm has not be found, it will be installed in: ${install_dir}")
|
||||||
|
set(LIBGLM_INCLUDE_DIRS ${install_dir}/include)
|
||||||
|
# message( "lib glm has not be found, it will be installed in: ${LIBGLM_INCLUDE_DIRS}")
|
||||||
|
|
||||||
|
add_library(glm_lib SHARED IMPORTED)
|
||||||
|
set_property(TARGET glm_lib PROPERTY IMPORTED_LOCATION ${install_dir}/lib/libglm${CMAKE_SHARED_LIBRARY_SUFFIX})
|
||||||
|
add_dependencies(glm_lib glm)
|
||||||
|
|
||||||
|
set(LIBGLM_LIBRARIES glm_lib)
|
||||||
|
|
||||||
|
set(GLM_FOUND ON)
|
||||||
|
|
||||||
|
else()
|
||||||
|
message( "-- Found glm" )
|
||||||
|
message( STATUS "LIBGLM_INCLUDE_DIRS ${LIBGLM_INCLUDE_DIRS}" )
|
||||||
|
message( STATUS "LIBGLM_LIBRARIES ${LIBGLM_LIBRARIES}" )
|
||||||
|
endif(NOT GLM_FOUND)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#########################################################
|
||||||
|
# FIND OPENCV
|
||||||
|
#########################################################
|
||||||
|
if(MSVC)
|
||||||
|
set(OpenCV_STATIC ON)
|
||||||
|
endif()
|
||||||
|
find_package(OpenCV 2.4 REQUIRED)
|
||||||
|
include_directories(${OpenCV_INCLUDE_DIRS})
|
||||||
|
link_directories(${OpenCV_LIB_DIR})
|
||||||
|
add_definitions(${OpenCV_DEFINITIONS})
|
||||||
|
# message( STATUS "OpenCV_LIB_DIR ${OpenCV_LIB_DIR}" )
|
||||||
|
# message( STATUS "OpenCV_VERSION ${OpenCV_INCLUDE_DIRS}" )
|
||||||
|
# message( STATUS "OpenCV_VERSION ${OpenCV_VERSION}" )
|
||||||
|
# message( STATUS "OpenCV_FOUND ${OpenCV_FOUND}" )
|
||||||
|
|
||||||
|
if(NOT OpenCV_FOUND)
|
||||||
|
message(ERROR " OpenCV not found!")
|
||||||
|
else()
|
||||||
|
message( "-- Found OpenCV version: ${OpenCV_VERSION}" )
|
||||||
|
endif(NOT OpenCV_FOUND)
|
||||||
|
|
||||||
|
#########################################################
|
||||||
|
# FIND OPENGL
|
||||||
|
#########################################################
|
||||||
|
find_package(OpenGL REQUIRED)
|
||||||
|
include_directories(${OpenGL_INCLUDE_DIRS})
|
||||||
|
link_directories(${OpenGL_LIBRARY_DIRS})
|
||||||
|
add_definitions(${OpenGL_DEFINITIONS})
|
||||||
|
# MESSAGE( "${OPENGL_LIBRARIES}" )
|
||||||
|
# MESSAGE( "${OPENGL_LIBRARIES_DIRS}" )
|
||||||
|
# MESSAGE( "${OPENGL_DEFINITIONS}" )
|
||||||
|
if(NOT OPENGL_FOUND)
|
||||||
|
message(ERROR " OPENGL not found!")
|
||||||
|
endif(NOT OPENGL_FOUND)
|
||||||
|
|
||||||
|
#########################################################
|
||||||
|
# FIND GLUT
|
||||||
|
#########################################################
|
||||||
|
if(MSVC)
|
||||||
|
message(STATUS "GLUT_ROOT_PATH: ${GLUT_ROOT_PATH}")
|
||||||
|
endif()
|
||||||
|
find_package(GLUT REQUIRED)
|
||||||
|
message(STATUS "GLUT_FOUND: ${GLUT_FOUND}")
|
||||||
|
message(STATUS "GLUT_INCLUDE_DIR: ${GLUT_INCLUDE_DIR}")
|
||||||
|
message(STATUS "GLUT_LIBRARIES: ${GLUT_LIBRARIES}")
|
||||||
|
include_directories(${GLUT_INCLUDE_DIR})
|
||||||
|
link_directories(${GLUT_LIBRARY_DIRS})
|
||||||
|
add_definitions(${GLUT_DEFINITIONS})
|
||||||
|
# message( "glut ${GLUT_INCLUDE_DIR}" )
|
||||||
|
if(NOT GLUT_FOUND)
|
||||||
|
message(ERROR " GLUT not found!")
|
||||||
|
else()
|
||||||
|
message( "-- Found GLUT" )
|
||||||
|
endif(NOT GLUT_FOUND)
|
||||||
|
|
||||||
|
|
||||||
|
## FreeGLUT ?
|
||||||
|
# find_package(FreeGLUT REQUIRED)
|
||||||
|
# include_directories(${FreeGLUT_INCLUDE_DIRS})
|
||||||
|
# link_directories(${FreeGLUT_LIBRARY_DIRS})
|
||||||
|
# add_definitions(${FreeGLUT_DEFINITIONS})
|
||||||
|
# MESSAGE( "${FREEGLUT_INCLUDE_PATH}" )
|
||||||
|
# MESSAGE( "${FREEGLUT_LIBRARY}" )
|
||||||
|
# MESSAGE( "${FreeGLUT_DEFINITIONS}" )
|
||||||
|
# if(NOT FREEGLUT_FOUND)
|
||||||
|
# message(ERROR " FreeGLUT not found!")
|
||||||
|
# endif(NOT FREEGLUT_FOUND)
|
||||||
|
|
||||||
|
#########################################################
|
||||||
|
# Doxygen
|
||||||
|
#########################################################
|
||||||
|
|
||||||
|
# add a target to generate API documentation with Doxygen
|
||||||
|
find_package(Doxygen QUIET)
|
||||||
|
# message( "${DOXYGEN_EXECUTABLE}" )
|
||||||
|
if(DOXYGEN_FOUND)
|
||||||
|
set(CMAKE_DOC_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc)
|
||||||
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/doc/Doxyfile.in ${CMAKE_DOC_OUTPUT_DIRECTORY}/Doxyfile @ONLY)
|
||||||
|
add_custom_target(doc
|
||||||
|
${DOXYGEN_EXECUTABLE} ${CMAKE_DOC_OUTPUT_DIRECTORY}/Doxyfile
|
||||||
|
WORKING_DIRECTORY ${CMAKE_DOC_OUTPUT_DIRECTORY}
|
||||||
|
COMMENT "Generating API documentation with Doxygen" VERBATIM)
|
||||||
|
endif(DOXYGEN_FOUND)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#########################################################
|
||||||
|
#
|
||||||
|
# PROJECT LIBRARIES
|
||||||
|
#
|
||||||
|
#########################################################
|
||||||
|
|
||||||
|
#########################################################
|
||||||
|
# TRACKER LIBRARY
|
||||||
|
#########################################################
|
||||||
|
|
||||||
|
add_subdirectory(src)
|
||||||
|
|
||||||
|
|
||||||
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/tracker)
|
||||||
|
|
362
LICENSE
Normal file
|
@ -0,0 +1,362 @@
|
||||||
|
Mozilla Public License, version 2.0
|
||||||
|
|
||||||
|
1. Definitions
|
||||||
|
|
||||||
|
1.1. "Contributor"
|
||||||
|
|
||||||
|
means each individual or legal entity that creates, contributes to the
|
||||||
|
creation of, or owns Covered Software.
|
||||||
|
|
||||||
|
1.2. "Contributor Version"
|
||||||
|
|
||||||
|
means the combination of the Contributions of others (if any) used by a
|
||||||
|
Contributor and that particular Contributor's Contribution.
|
||||||
|
|
||||||
|
1.3. "Contribution"
|
||||||
|
|
||||||
|
means Covered Software of a particular Contributor.
|
||||||
|
|
||||||
|
1.4. "Covered Software"
|
||||||
|
|
||||||
|
means Source Code Form to which the initial Contributor has attached the
|
||||||
|
notice in Exhibit A, the Executable Form of such Source Code Form, and
|
||||||
|
Modifications of such Source Code Form, in each case including portions
|
||||||
|
thereof.
|
||||||
|
|
||||||
|
1.5. "Incompatible With Secondary Licenses"
|
||||||
|
means
|
||||||
|
|
||||||
|
a. that the initial Contributor has attached the notice described in
|
||||||
|
Exhibit B to the Covered Software; or
|
||||||
|
|
||||||
|
b. that the Covered Software was made available under the terms of
|
||||||
|
version 1.1 or earlier of the License, but not also under the terms of
|
||||||
|
a Secondary License.
|
||||||
|
|
||||||
|
1.6. "Executable Form"
|
||||||
|
|
||||||
|
means any form of the work other than Source Code Form.
|
||||||
|
|
||||||
|
1.7. "Larger Work"
|
||||||
|
|
||||||
|
means a work that combines Covered Software with other material, in a
|
||||||
|
separate file or files, that is not Covered Software.
|
||||||
|
|
||||||
|
1.8. "License"
|
||||||
|
|
||||||
|
means this document.
|
||||||
|
|
||||||
|
1.9. "Licensable"
|
||||||
|
|
||||||
|
means having the right to grant, to the maximum extent possible, whether
|
||||||
|
at the time of the initial grant or subsequently, any and all of the
|
||||||
|
rights conveyed by this License.
|
||||||
|
|
||||||
|
1.10. "Modifications"
|
||||||
|
|
||||||
|
means any of the following:
|
||||||
|
|
||||||
|
a. any file in Source Code Form that results from an addition to,
|
||||||
|
deletion from, or modification of the contents of Covered Software; or
|
||||||
|
|
||||||
|
b. any new file in Source Code Form that contains any Covered Software.
|
||||||
|
|
||||||
|
1.11. "Patent Claims" of a Contributor
|
||||||
|
|
||||||
|
means any patent claim(s), including without limitation, method,
|
||||||
|
process, and apparatus claims, in any patent Licensable by such
|
||||||
|
Contributor that would be infringed, but for the grant of the License,
|
||||||
|
by the making, using, selling, offering for sale, having made, import,
|
||||||
|
or transfer of either its Contributions or its Contributor Version.
|
||||||
|
|
||||||
|
1.12. "Secondary License"
|
||||||
|
|
||||||
|
means either the GNU General Public License, Version 2.0, the GNU Lesser
|
||||||
|
General Public License, Version 2.1, the GNU Affero General Public
|
||||||
|
License, Version 3.0, or any later versions of those licenses.
|
||||||
|
|
||||||
|
1.13. "Source Code Form"
|
||||||
|
|
||||||
|
means the form of the work preferred for making modifications.
|
||||||
|
|
||||||
|
1.14. "You" (or "Your")
|
||||||
|
|
||||||
|
means an individual or a legal entity exercising rights under this
|
||||||
|
License. For legal entities, "You" includes any entity that controls, is
|
||||||
|
controlled by, or is under common control with You. For purposes of this
|
||||||
|
definition, "control" means (a) the power, direct or indirect, to cause
|
||||||
|
the direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (b) ownership of more than fifty percent (50%) of the
|
||||||
|
outstanding shares or beneficial ownership of such entity.
|
||||||
|
|
||||||
|
|
||||||
|
2. License Grants and Conditions
|
||||||
|
|
||||||
|
2.1. Grants
|
||||||
|
|
||||||
|
Each Contributor hereby grants You a world-wide, royalty-free,
|
||||||
|
non-exclusive license:
|
||||||
|
|
||||||
|
a. under intellectual property rights (other than patent or trademark)
|
||||||
|
Licensable by such Contributor to use, reproduce, make available,
|
||||||
|
modify, display, perform, distribute, and otherwise exploit its
|
||||||
|
Contributions, either on an unmodified basis, with Modifications, or
|
||||||
|
as part of a Larger Work; and
|
||||||
|
|
||||||
|
b. under Patent Claims of such Contributor to make, use, sell, offer for
|
||||||
|
sale, have made, import, and otherwise transfer either its
|
||||||
|
Contributions or its Contributor Version.
|
||||||
|
|
||||||
|
2.2. Effective Date
|
||||||
|
|
||||||
|
The licenses granted in Section 2.1 with respect to any Contribution
|
||||||
|
become effective for each Contribution on the date the Contributor first
|
||||||
|
distributes such Contribution.
|
||||||
|
|
||||||
|
2.3. Limitations on Grant Scope
|
||||||
|
|
||||||
|
The licenses granted in this Section 2 are the only rights granted under
|
||||||
|
this License. No additional rights or licenses will be implied from the
|
||||||
|
distribution or licensing of Covered Software under this License.
|
||||||
|
Notwithstanding Section 2.1(b) above, no patent license is granted by a
|
||||||
|
Contributor:
|
||||||
|
|
||||||
|
a. for any code that a Contributor has removed from Covered Software; or
|
||||||
|
|
||||||
|
b. for infringements caused by: (i) Your and any other third party's
|
||||||
|
modifications of Covered Software, or (ii) the combination of its
|
||||||
|
Contributions with other software (except as part of its Contributor
|
||||||
|
Version); or
|
||||||
|
|
||||||
|
c. under Patent Claims infringed by Covered Software in the absence of
|
||||||
|
its Contributions.
|
||||||
|
|
||||||
|
This License does not grant any rights in the trademarks, service marks,
|
||||||
|
or logos of any Contributor (except as may be necessary to comply with
|
||||||
|
the notice requirements in Section 3.4).
|
||||||
|
|
||||||
|
2.4. Subsequent Licenses
|
||||||
|
|
||||||
|
No Contributor makes additional grants as a result of Your choice to
|
||||||
|
distribute the Covered Software under a subsequent version of this
|
||||||
|
License (see Section 10.2) or under the terms of a Secondary License (if
|
||||||
|
permitted under the terms of Section 3.3).
|
||||||
|
|
||||||
|
2.5. Representation
|
||||||
|
|
||||||
|
Each Contributor represents that the Contributor believes its
|
||||||
|
Contributions are its original creation(s) or it has sufficient rights to
|
||||||
|
grant the rights to its Contributions conveyed by this License.
|
||||||
|
|
||||||
|
2.6. Fair Use
|
||||||
|
|
||||||
|
This License is not intended to limit any rights You have under
|
||||||
|
applicable copyright doctrines of fair use, fair dealing, or other
|
||||||
|
equivalents.
|
||||||
|
|
||||||
|
2.7. Conditions
|
||||||
|
|
||||||
|
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
|
||||||
|
Section 2.1.
|
||||||
|
|
||||||
|
|
||||||
|
3. Responsibilities
|
||||||
|
|
||||||
|
3.1. Distribution of Source Form
|
||||||
|
|
||||||
|
All distribution of Covered Software in Source Code Form, including any
|
||||||
|
Modifications that You create or to which You contribute, must be under
|
||||||
|
the terms of this License. You must inform recipients that the Source
|
||||||
|
Code Form of the Covered Software is governed by the terms of this
|
||||||
|
License, and how they can obtain a copy of this License. You may not
|
||||||
|
attempt to alter or restrict the recipients' rights in the Source Code
|
||||||
|
Form.
|
||||||
|
|
||||||
|
3.2. Distribution of Executable Form
|
||||||
|
|
||||||
|
If You distribute Covered Software in Executable Form then:
|
||||||
|
|
||||||
|
a. such Covered Software must also be made available in Source Code Form,
|
||||||
|
as described in Section 3.1, and You must inform recipients of the
|
||||||
|
Executable Form how they can obtain a copy of such Source Code Form by
|
||||||
|
reasonable means in a timely manner, at a charge no more than the cost
|
||||||
|
of distribution to the recipient; and
|
||||||
|
|
||||||
|
b. You may distribute such Executable Form under the terms of this
|
||||||
|
License, or sublicense it under different terms, provided that the
|
||||||
|
license for the Executable Form does not attempt to limit or alter the
|
||||||
|
recipients' rights in the Source Code Form under this License.
|
||||||
|
|
||||||
|
3.3. Distribution of a Larger Work
|
||||||
|
|
||||||
|
You may create and distribute a Larger Work under terms of Your choice,
|
||||||
|
provided that You also comply with the requirements of this License for
|
||||||
|
the Covered Software. If the Larger Work is a combination of Covered
|
||||||
|
Software with a work governed by one or more Secondary Licenses, and the
|
||||||
|
Covered Software is not Incompatible With Secondary Licenses, this
|
||||||
|
License permits You to additionally distribute such Covered Software
|
||||||
|
under the terms of such Secondary License(s), so that the recipient of
|
||||||
|
the Larger Work may, at their option, further distribute the Covered
|
||||||
|
Software under the terms of either this License or such Secondary
|
||||||
|
License(s).
|
||||||
|
|
||||||
|
3.4. Notices
|
||||||
|
|
||||||
|
You may not remove or alter the substance of any license notices
|
||||||
|
(including copyright notices, patent notices, disclaimers of warranty, or
|
||||||
|
limitations of liability) contained within the Source Code Form of the
|
||||||
|
Covered Software, except that You may alter any license notices to the
|
||||||
|
extent required to remedy known factual inaccuracies.
|
||||||
|
|
||||||
|
3.5. Application of Additional Terms
|
||||||
|
|
||||||
|
You may choose to offer, and to charge a fee for, warranty, support,
|
||||||
|
indemnity or liability obligations to one or more recipients of Covered
|
||||||
|
Software. However, You may do so only on Your own behalf, and not on
|
||||||
|
behalf of any Contributor. You must make it absolutely clear that any
|
||||||
|
such warranty, support, indemnity, or liability obligation is offered by
|
||||||
|
You alone, and You hereby agree to indemnify every Contributor for any
|
||||||
|
liability incurred by such Contributor as a result of warranty, support,
|
||||||
|
indemnity or liability terms You offer. You may include additional
|
||||||
|
disclaimers of warranty and limitations of liability specific to any
|
||||||
|
jurisdiction.
|
||||||
|
|
||||||
|
4. Inability to Comply Due to Statute or Regulation
|
||||||
|
|
||||||
|
If it is impossible for You to comply with any of the terms of this License
|
||||||
|
with respect to some or all of the Covered Software due to statute,
|
||||||
|
judicial order, or regulation then You must: (a) comply with the terms of
|
||||||
|
this License to the maximum extent possible; and (b) describe the
|
||||||
|
limitations and the code they affect. Such description must be placed in a
|
||||||
|
text file included with all distributions of the Covered Software under
|
||||||
|
this License. Except to the extent prohibited by statute or regulation,
|
||||||
|
such description must be sufficiently detailed for a recipient of ordinary
|
||||||
|
skill to be able to understand it.
|
||||||
|
|
||||||
|
5. Termination
|
||||||
|
|
||||||
|
5.1. The rights granted under this License will terminate automatically if You
|
||||||
|
fail to comply with any of its terms. However, if You become compliant,
|
||||||
|
then the rights granted under this License from a particular Contributor
|
||||||
|
are reinstated (a) provisionally, unless and until such Contributor
|
||||||
|
explicitly and finally terminates Your grants, and (b) on an ongoing
|
||||||
|
basis, if such Contributor fails to notify You of the non-compliance by
|
||||||
|
some reasonable means prior to 60 days after You have come back into
|
||||||
|
compliance. Moreover, Your grants from a particular Contributor are
|
||||||
|
reinstated on an ongoing basis if such Contributor notifies You of the
|
||||||
|
non-compliance by some reasonable means, this is the first time You have
|
||||||
|
received notice of non-compliance with this License from such
|
||||||
|
Contributor, and You become compliant prior to 30 days after Your receipt
|
||||||
|
of the notice.
|
||||||
|
|
||||||
|
5.2. If You initiate litigation against any entity by asserting a patent
|
||||||
|
infringement claim (excluding declaratory judgment actions,
|
||||||
|
counter-claims, and cross-claims) alleging that a Contributor Version
|
||||||
|
directly or indirectly infringes any patent, then the rights granted to
|
||||||
|
You by any and all Contributors for the Covered Software under Section
|
||||||
|
2.1 of this License shall terminate.
|
||||||
|
|
||||||
|
5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
|
||||||
|
license agreements (excluding distributors and resellers) which have been
|
||||||
|
validly granted by You or Your distributors under this License prior to
|
||||||
|
termination shall survive termination.
|
||||||
|
|
||||||
|
6. Disclaimer of Warranty
|
||||||
|
|
||||||
|
Covered Software is provided under this License on an "as is" basis,
|
||||||
|
without warranty of any kind, either expressed, implied, or statutory,
|
||||||
|
including, without limitation, warranties that the Covered Software is free
|
||||||
|
of defects, merchantable, fit for a particular purpose or non-infringing.
|
||||||
|
The entire risk as to the quality and performance of the Covered Software
|
||||||
|
is with You. Should any Covered Software prove defective in any respect,
|
||||||
|
You (not any Contributor) assume the cost of any necessary servicing,
|
||||||
|
repair, or correction. This disclaimer of warranty constitutes an essential
|
||||||
|
part of this License. No use of any Covered Software is authorized under
|
||||||
|
this License except under this disclaimer.
|
||||||
|
|
||||||
|
7. Limitation of Liability
|
||||||
|
|
||||||
|
Under no circumstances and under no legal theory, whether tort (including
|
||||||
|
negligence), contract, or otherwise, shall any Contributor, or anyone who
|
||||||
|
distributes Covered Software as permitted above, be liable to You for any
|
||||||
|
direct, indirect, special, incidental, or consequential damages of any
|
||||||
|
character including, without limitation, damages for lost profits, loss of
|
||||||
|
goodwill, work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses, even if such party shall have been
|
||||||
|
informed of the possibility of such damages. This limitation of liability
|
||||||
|
shall not apply to liability for death or personal injury resulting from
|
||||||
|
such party's negligence to the extent applicable law prohibits such
|
||||||
|
limitation. Some jurisdictions do not allow the exclusion or limitation of
|
||||||
|
incidental or consequential damages, so this exclusion and limitation may
|
||||||
|
not apply to You.
|
||||||
|
|
||||||
|
8. Litigation
|
||||||
|
|
||||||
|
Any litigation relating to this License may be brought only in the courts
|
||||||
|
of a jurisdiction where the defendant maintains its principal place of
|
||||||
|
business and such litigation shall be governed by laws of that
|
||||||
|
jurisdiction, without reference to its conflict-of-law provisions. Nothing
|
||||||
|
in this Section shall prevent a party's ability to bring cross-claims or
|
||||||
|
counter-claims.
|
||||||
|
|
||||||
|
9. Miscellaneous
|
||||||
|
|
||||||
|
This License represents the complete agreement concerning the subject
|
||||||
|
matter hereof. If any provision of this License is held to be
|
||||||
|
unenforceable, such provision shall be reformed only to the extent
|
||||||
|
necessary to make it enforceable. Any law or regulation which provides that
|
||||||
|
the language of a contract shall be construed against the drafter shall not
|
||||||
|
be used to construe this License against a Contributor.
|
||||||
|
|
||||||
|
|
||||||
|
10. Versions of the License
|
||||||
|
|
||||||
|
10.1. New Versions
|
||||||
|
|
||||||
|
Mozilla Foundation is the license steward. Except as provided in Section
|
||||||
|
10.3, no one other than the license steward has the right to modify or
|
||||||
|
publish new versions of this License. Each version will be given a
|
||||||
|
distinguishing version number.
|
||||||
|
|
||||||
|
10.2. Effect of New Versions
|
||||||
|
|
||||||
|
You may distribute the Covered Software under the terms of the version
|
||||||
|
of the License under which You originally received the Covered Software,
|
||||||
|
or under the terms of any subsequent version published by the license
|
||||||
|
steward.
|
||||||
|
|
||||||
|
10.3. Modified Versions
|
||||||
|
|
||||||
|
If you create software not governed by this License, and you want to
|
||||||
|
create a new license for such software, you may create and use a
|
||||||
|
modified version of this License if you rename the license and remove
|
||||||
|
any references to the name of the license steward (except to note that
|
||||||
|
such modified license differs from this License).
|
||||||
|
|
||||||
|
10.4. Distributing Source Code Form that is Incompatible With Secondary
|
||||||
|
Licenses If You choose to distribute Source Code Form that is
|
||||||
|
Incompatible With Secondary Licenses under the terms of this version of
|
||||||
|
the License, the notice described in Exhibit B of this License must be
|
||||||
|
attached.
|
||||||
|
|
||||||
|
Exhibit A - Source Code Form License Notice
|
||||||
|
|
||||||
|
This Source Code Form is subject to the
|
||||||
|
terms of the Mozilla Public License, v.
|
||||||
|
2.0. If a copy of the MPL was not
|
||||||
|
distributed with this file, You can
|
||||||
|
obtain one at
|
||||||
|
http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
If it is not possible or desirable to put the notice in a particular file,
|
||||||
|
then You may include the notice in a location (such as a LICENSE file in a
|
||||||
|
relevant directory) where a recipient would be likely to look for such a
|
||||||
|
notice.
|
||||||
|
|
||||||
|
You may add additional accurate notices of copyright ownership.
|
||||||
|
|
||||||
|
Exhibit B - "Incompatible With Secondary Licenses" Notice
|
||||||
|
|
||||||
|
This Source Code Form is "Incompatible
|
||||||
|
With Secondary Licenses", as defined by
|
||||||
|
the Mozilla Public License, v. 2.0.
|
52
README.md
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
An Augmented Reality application
|
||||||
|
===========================================
|
||||||
|
|
||||||
|
------------
|
||||||
|
Introduction
|
||||||
|
------------
|
||||||
|
|
||||||
|
The objective of these TP sessions is to build a simple augmented reality application using OpenCV for the camera tracking part and OpenGL for the rendering. The exercises that will be proposed are meant to gradually introduce you to the OpenCV libraries and build all the function that are needed for a camera tracker in an incremental way, so that you will be able to test and debug each function, before plugging all together in the camera tracker class.
|
||||||
|
The main idea is to use a chessboard as a marker and render on top of that the augmented reality. The final application should render an OpenGL teapot on top of the chessboard. We will get there step by step, first detecting the chessboard, then create some basic rendering in OpenCV, and at last plugging everything in the OpenGL pipeline.
|
||||||
|
|
||||||
|
-----------------
|
||||||
|
Code Organization
|
||||||
|
-----------------
|
||||||
|
The directories are organized as follows:
|
||||||
|
|
||||||
|
* ``doc`` contains a pdf copy of this text, a pdf copy of the reduced opencv tutorials, a pdf copy of the full, original opencv tutorial, and a pdf copy of the API reference manual of opencv (ie the copy of the online documentation).
|
||||||
|
|
||||||
|
* ``data`` contains some images, videos and other data that will be used through the TP.
|
||||||
|
|
||||||
|
* ``src`` contains the source files that you have to modify and complete; they are organize in directories:
|
||||||
|
|
||||||
|
* ``tutorials`` contains the code used in the tutorials, in case you need to try it;
|
||||||
|
* ``tp`` contains the files that you need to modify and complete through all the sessions of the TP.
|
||||||
|
|
||||||
|
* ``3dparty`` this directory contains a library that will be used at the end of the TP. You don't have to worry (or do anything...) about this directory.
|
||||||
|
|
||||||
|
|
||||||
|
--------
|
||||||
|
Building
|
||||||
|
--------
|
||||||
|
|
||||||
|
See [BUILD](BUILD.md) text file
|
||||||
|
|
||||||
|
|
||||||
|
-------
|
||||||
|
License
|
||||||
|
-------
|
||||||
|
|
||||||
|
See [LICENSE](LICENSE) text file
|
||||||
|
|
||||||
|
-------
|
||||||
|
Authors
|
||||||
|
-------
|
||||||
|
|
||||||
|
Simone Gasparini
|
||||||
|
|
||||||
|
|
||||||
|
---------
|
||||||
|
Contact
|
||||||
|
---------
|
||||||
|
|
||||||
|
Simone Gasparini simone.gasparini@enseeiht.fr
|
BIN
data/images/HappyFish.png
Normal file
After Width: | Height: | Size: 42 KiB |
BIN
data/images/cat.jpg
Normal file
After Width: | Height: | Size: 64 KiB |
BIN
data/images/left01re.jpg
Normal file
After Width: | Height: | Size: 102 KiB |
BIN
data/images/re_circles2.jpg
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
data/images/re_circles3.jpg
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
data/images/re_left01.jpg
Normal file
After Width: | Height: | Size: 98 KiB |
BIN
data/images/re_left02.jpg
Normal file
After Width: | Height: | Size: 121 KiB |
BIN
data/images/re_left06.jpg
Normal file
After Width: | Height: | Size: 117 KiB |
BIN
data/images/re_left08.jpg
Normal file
After Width: | Height: | Size: 125 KiB |
BIN
data/images/re_left30.jpg
Normal file
After Width: | Height: | Size: 105 KiB |
BIN
data/images/re_left38.jpg
Normal file
After Width: | Height: | Size: 103 KiB |
BIN
data/images/re_left39.jpg
Normal file
After Width: | Height: | Size: 108 KiB |
BIN
data/images/re_left44.jpg
Normal file
After Width: | Height: | Size: 107 KiB |
26
data/models/calib.xml
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<opencv_storage>
|
||||||
|
<calibration_time>"Mon 21 Oct 2013 07:16:31 PM CEST"</calibration_time>
|
||||||
|
<image_width>640</image_width>
|
||||||
|
<image_height>360</image_height>
|
||||||
|
<board_width>9</board_width>
|
||||||
|
<board_height>6</board_height>
|
||||||
|
<square_size>1.</square_size>
|
||||||
|
<!-- flags: +zero_tangent_dist -->
|
||||||
|
<flags>8</flags>
|
||||||
|
<camera_matrix type_id="opencv-matrix">
|
||||||
|
<rows>3</rows>
|
||||||
|
<cols>3</cols>
|
||||||
|
<dt>d</dt>
|
||||||
|
<data>
|
||||||
|
4.8428509485313901e+02 0. 3.2009932991075260e+02 0.
|
||||||
|
4.8365482958967795e+02 1.6283922248766723e+02 0. 0. 1.</data></camera_matrix>
|
||||||
|
<distortion_coefficients type_id="opencv-matrix">
|
||||||
|
<rows>5</rows>
|
||||||
|
<cols>1</cols>
|
||||||
|
<dt>d</dt>
|
||||||
|
<data>
|
||||||
|
-9.3396873795605365e-02 2.3550692129669618e-01 0. 0.
|
||||||
|
-3.8791765186556898e-01</data></distortion_coefficients>
|
||||||
|
<avg_reprojection_error>1.7869347177607542e-01</avg_reprojection_error>
|
||||||
|
</opencv_storage>
|
7886
data/models/cessna.obj
Normal file
BIN
data/models/knight.aoi
Normal file
29
data/models/knight.mtl
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
#Produced by Art of Illusion 2.8.1, Thu Apr 01 23:51:44 PDT 2010
|
||||||
|
newmtl Sword
|
||||||
|
Kd 1 1 1
|
||||||
|
Ks 0 0 0
|
||||||
|
Ka 1 1 1
|
||||||
|
illum 1
|
||||||
|
newmtl Armor
|
||||||
|
Kd 0.45 0.4275 0.225
|
||||||
|
Ks 1 1 1
|
||||||
|
Ka 0.45 0.4275 0.225
|
||||||
|
illum 2
|
||||||
|
Ns 57
|
||||||
|
newmtl Armor_3
|
||||||
|
Kd 0.45 0.405 0
|
||||||
|
Ks 1 1 1
|
||||||
|
Ka 0.45 0.405 0
|
||||||
|
illum 2
|
||||||
|
Ns 57
|
||||||
|
newmtl Face
|
||||||
|
Kd 0 0 0
|
||||||
|
Ks 0 0 0
|
||||||
|
Ka 0 0 0
|
||||||
|
illum 1
|
||||||
|
newmtl Armor_2
|
||||||
|
Kd 0.33 0.33 0.33
|
||||||
|
Ks 1 1 1
|
||||||
|
Ka 0.33 0.33 0.33
|
||||||
|
illum 2
|
||||||
|
Ns 50
|
2835
data/models/knight.obj
Normal file
8863
data/models/lamp.obj
Normal file
744
data/models/shuttle.obj
Normal file
|
@ -0,0 +1,744 @@
|
||||||
|
# Viewpoint Datalabs International, Inc. Copyright 1996
|
||||||
|
|
||||||
|
|
||||||
|
# mtllib ./vp.mtl
|
||||||
|
|
||||||
|
g
|
||||||
|
v 3.070224 -0.119728 0.996443
|
||||||
|
v 5.942016 -0.012019 4.157199
|
||||||
|
v 6.614015 -0.063428 4.157199
|
||||||
|
v 5.759114 0.000000 1.664500
|
||||||
|
v 3.070224 -0.449143 0.929434
|
||||||
|
v 5.000295 -0.539011 1.315104
|
||||||
|
v 3.070224 -0.604752 0.872464
|
||||||
|
v 3.070224 -0.866525 0.730690
|
||||||
|
v 3.070224 -0.959007 0.650256
|
||||||
|
v 3.070224 -1.053631 0.163277
|
||||||
|
v 2.983248 -1.080021 -0.880639
|
||||||
|
v 6.130317 -1.100022 -1.106943
|
||||||
|
v 3.739287 -4.334102 -0.876958
|
||||||
|
v 4.400283 -4.682100 -0.952940
|
||||||
|
v 3.038248 -4.334102 -0.811319
|
||||||
|
v 3.180259 -4.550090 -0.921939
|
||||||
|
v 2.700250 -4.334102 -0.947940
|
||||||
|
v 0.840214 -2.480049 -1.050312
|
||||||
|
v 1.208789 -1.060728 0.203820
|
||||||
|
v 1.208789 -1.054148 0.411073
|
||||||
|
v 1.208789 -0.958092 0.610367
|
||||||
|
v 1.208789 -0.875165 0.685964
|
||||||
|
v 1.208789 -0.621528 0.854704
|
||||||
|
v 1.208789 -0.467365 0.922276
|
||||||
|
v -4.649089 -1.039587 0.209476
|
||||||
|
v -4.649345 -0.922345 0.432259
|
||||||
|
v -4.649708 -0.652575 0.753550
|
||||||
|
v -4.999902 -1.012545 0.094530
|
||||||
|
v -4.999240 -0.870266 0.347384
|
||||||
|
v -4.999321 -0.802315 0.416133
|
||||||
|
v -4.906714 -0.620194 0.686502
|
||||||
|
v -4.999759 -0.491153 0.805206
|
||||||
|
v -5.568033 -0.119200 0.568687
|
||||||
|
v -5.349121 -0.814175 0.247113
|
||||||
|
v -5.348800 -0.938377 -0.030175
|
||||||
|
v -6.499984 -0.676000 -0.433500
|
||||||
|
v -6.499984 -0.610000 -0.164800
|
||||||
|
v -6.499984 -0.240000 0.109600
|
||||||
|
v -7.649984 0.000000 -0.620000
|
||||||
|
v 1.209237 -1.080021 -1.321617
|
||||||
|
v 3.070224 0.119728 0.996443
|
||||||
|
v 3.093016 0.040804 1.276300
|
||||||
|
v 6.614015 0.063428 4.157199
|
||||||
|
v 3.070224 0.449143 0.929434
|
||||||
|
v 5.000295 0.539011 1.315104
|
||||||
|
v 3.070224 0.604752 0.872464
|
||||||
|
v 3.070224 0.866525 0.730690
|
||||||
|
v 5.000295 1.149023 1.260104
|
||||||
|
v 3.070224 0.959007 0.650256
|
||||||
|
v 3.070224 1.053627 0.449897
|
||||||
|
v 5.000295 1.428028 0.442095
|
||||||
|
v 3.070224 1.053631 0.163277
|
||||||
|
v 2.983248 1.080021 -0.880639
|
||||||
|
v 5.000295 1.302926 -1.259946
|
||||||
|
v 3.739287 4.334102 -0.876958
|
||||||
|
v 4.400283 4.682100 -0.952940
|
||||||
|
v 3.038248 4.334102 -0.811319
|
||||||
|
v 3.180259 4.550090 -0.921939
|
||||||
|
v 1.209237 1.080021 -0.636414
|
||||||
|
v 2.700250 4.334102 -0.947940
|
||||||
|
v 0.169216 1.990039 -1.063281
|
||||||
|
v 1.208789 1.060728 0.203820
|
||||||
|
v 1.208789 1.054148 0.411073
|
||||||
|
v 1.208789 0.958092 0.610367
|
||||||
|
v 1.208789 0.875165 0.685964
|
||||||
|
v 1.208789 0.621528 0.854704
|
||||||
|
v 1.208789 0.467365 0.922276
|
||||||
|
v -4.649089 1.039587 0.209476
|
||||||
|
v -4.649345 0.922345 0.432259
|
||||||
|
v -4.649708 0.652575 0.753550
|
||||||
|
v -4.649856 0.514670 0.885149
|
||||||
|
v -4.649964 0.160748 0.994500
|
||||||
|
v -4.999902 1.012545 0.094530
|
||||||
|
v -4.999240 0.870266 0.347384
|
||||||
|
v -4.999321 0.802315 0.416133
|
||||||
|
v -4.999759 0.491153 0.805206
|
||||||
|
v -4.999948 0.160720 0.980689
|
||||||
|
v -5.299752 0.147914 0.811038
|
||||||
|
v -5.349121 0.814175 0.247113
|
||||||
|
v -5.348800 0.938377 -0.030175
|
||||||
|
v -6.499984 0.676000 -0.433500
|
||||||
|
v -6.499931 0.693962 -0.748535
|
||||||
|
v -6.499984 0.610000 -0.164800
|
||||||
|
v -6.499984 0.523000 -0.048800
|
||||||
|
v -6.499984 0.240000 0.109600
|
||||||
|
v 1.209237 1.080021 -1.321617
|
||||||
|
v -5.568033 0.119200 0.568687
|
||||||
|
v -5.299752 -0.147914 0.811038
|
||||||
|
v -4.999948 -0.160720 0.980689
|
||||||
|
v -4.649964 -0.160748 0.994500
|
||||||
|
v 1.208789 -0.130179 0.996071
|
||||||
|
v 1.208789 0.130179 0.996071
|
||||||
|
v 3.093016 -0.040804 1.276300
|
||||||
|
v 5.942016 0.012019 4.157199
|
||||||
|
v 7.043714 0.000000 4.157199
|
||||||
|
v 4.998233 -0.130896 1.193100
|
||||||
|
v 5.171283 -1.310384 -1.055942
|
||||||
|
v 6.130317 1.100022 -1.106943
|
||||||
|
v 2.983248 -1.080021 -1.351649
|
||||||
|
v 2.983248 1.080021 -1.351649
|
||||||
|
v -6.499931 -0.693962 -0.748535
|
||||||
|
v -4.999902 -1.000020 -0.943979
|
||||||
|
v 0.169216 -1.990039 -1.063281
|
||||||
|
v 5.000295 -1.510030 0.750093
|
||||||
|
v 5.000295 -0.874017 1.399122
|
||||||
|
v 5.000295 -1.149023 1.260104
|
||||||
|
v 5.000295 0.874017 1.399122
|
||||||
|
v -7.074984 -0.304058 -0.264426
|
||||||
|
v -7.074984 0.139529 -0.169387
|
||||||
|
v -7.074984 0.304058 -0.264426
|
||||||
|
v -7.074957 0.403450 -0.684268
|
||||||
|
v -7.074984 0.393008 -0.495246
|
||||||
|
v -7.074984 0.354637 -0.334026
|
||||||
|
v -7.074984 0.057454 -0.155083
|
||||||
|
v -7.074984 -0.354637 -0.334026
|
||||||
|
v -7.074984 -0.393008 -0.495246
|
||||||
|
v -7.074957 -0.403450 -0.684268
|
||||||
|
v -7.074984 -0.139529 -0.169387
|
||||||
|
v -7.074984 -0.057454 -0.155083
|
||||||
|
v 5.257180 -0.244260 -0.448877
|
||||||
|
v 5.275361 -0.389797 -0.446328
|
||||||
|
v 5.534085 -0.255527 -0.410058
|
||||||
|
v 5.858724 -0.171973 -0.364548
|
||||||
|
v 6.246687 -0.127423 -0.310161
|
||||||
|
v 6.245811 -0.209802 -0.310283
|
||||||
|
v 5.957494 -0.242908 -0.350702
|
||||||
|
v 5.684797 -0.367023 -0.388930
|
||||||
|
v 5.030259 -0.310424 -0.039389
|
||||||
|
v 5.218888 -0.403501 -0.175729
|
||||||
|
v 5.254566 -0.476272 -0.297997
|
||||||
|
v 5.497149 -0.409135 -0.146573
|
||||||
|
v 5.811742 -0.367356 -0.029404
|
||||||
|
v 6.194348 -0.345081 0.063191
|
||||||
|
v 6.203377 -0.386271 -0.007583
|
||||||
|
v 5.919040 -0.402825 -0.076394
|
||||||
|
v 5.661265 -0.464884 -0.221067
|
||||||
|
v 5.030257 -0.815056 -0.039376
|
||||||
|
v 5.218887 -0.721987 -0.175721
|
||||||
|
v 5.254566 -0.649223 -0.297993
|
||||||
|
v 5.497147 -0.716354 -0.146565
|
||||||
|
v 5.811740 -0.758129 -0.029394
|
||||||
|
v 6.194347 -0.780403 0.063202
|
||||||
|
v 6.203376 -0.739216 -0.007574
|
||||||
|
v 5.919039 -0.722663 -0.076386
|
||||||
|
v 5.661264 -0.660610 -0.221062
|
||||||
|
v 5.533661 -0.562752 -0.410117
|
||||||
|
v 5.257178 -0.881243 -0.448860
|
||||||
|
v 5.275359 -0.735706 -0.446319
|
||||||
|
v 5.534083 -0.869976 -0.410042
|
||||||
|
v 5.858722 -0.953530 -0.364528
|
||||||
|
v 6.246684 -0.998080 -0.310138
|
||||||
|
v 6.245809 -0.915701 -0.310265
|
||||||
|
v 5.957492 -0.882595 -0.350685
|
||||||
|
v 5.684796 -0.758480 -0.388920
|
||||||
|
v 5.151601 -0.815102 -0.904963
|
||||||
|
v 5.295470 -0.722016 -0.722016
|
||||||
|
v 5.296154 -0.649239 -0.594654
|
||||||
|
v 5.571022 -0.716382 -0.673535
|
||||||
|
v 5.905705 -0.758165 -0.699682
|
||||||
|
v 6.299025 -0.780442 -0.683500
|
||||||
|
v 6.288245 -0.739248 -0.612975
|
||||||
|
v 5.995947 -0.722692 -0.625000
|
||||||
|
v 5.708329 -0.660628 -0.556788
|
||||||
|
v 5.295474 -0.403530 -0.722041
|
||||||
|
v 5.296155 -0.476288 -0.594668
|
||||||
|
v 5.571025 -0.409163 -0.673559
|
||||||
|
v 5.905710 -0.367392 -0.699712
|
||||||
|
v 6.299029 -0.345120 -0.683534
|
||||||
|
v 6.288249 -0.386303 -0.613002
|
||||||
|
v 5.995951 -0.402854 -0.625025
|
||||||
|
v 5.708331 -0.464902 -0.556803
|
||||||
|
v 5.218888 0.403501 -0.175729
|
||||||
|
v 5.257180 0.244260 -0.448877
|
||||||
|
v 5.254566 0.476272 -0.297997
|
||||||
|
v 5.275361 0.389797 -0.446328
|
||||||
|
v 5.497149 0.409135 -0.146573
|
||||||
|
v 5.534085 0.255527 -0.410058
|
||||||
|
v 5.811742 0.367356 -0.029404
|
||||||
|
v 5.858724 0.171973 -0.364548
|
||||||
|
v 6.194348 0.345081 0.063191
|
||||||
|
v 6.246687 0.127423 -0.310161
|
||||||
|
v 6.203377 0.386271 -0.007583
|
||||||
|
v 6.245811 0.209802 -0.310283
|
||||||
|
v 5.919040 0.402825 -0.076394
|
||||||
|
v 5.957494 0.242908 -0.350702
|
||||||
|
v 5.661265 0.464884 -0.221067
|
||||||
|
v 5.684797 0.367023 -0.388930
|
||||||
|
v 5.218887 0.721987 -0.175721
|
||||||
|
v 5.254566 0.649223 -0.297993
|
||||||
|
v 5.497147 0.716354 -0.146565
|
||||||
|
v 5.811740 0.758129 -0.029394
|
||||||
|
v 6.194347 0.780403 0.063202
|
||||||
|
v 6.203376 0.739216 -0.007574
|
||||||
|
v 5.919039 0.722663 -0.076386
|
||||||
|
v 5.661264 0.660610 -0.221062
|
||||||
|
v 5.257178 0.881243 -0.448860
|
||||||
|
v 5.275359 0.735706 -0.446319
|
||||||
|
v 5.534083 0.869976 -0.410042
|
||||||
|
v 5.858722 0.953530 -0.364528
|
||||||
|
v 6.246684 0.998080 -0.310138
|
||||||
|
v 6.245809 0.915701 -0.310265
|
||||||
|
v 5.957492 0.882595 -0.350685
|
||||||
|
v 5.684796 0.758480 -0.388920
|
||||||
|
v 5.533661 0.562752 -0.410117
|
||||||
|
v 5.295470 0.722016 -0.722016
|
||||||
|
v 5.296154 0.649239 -0.594654
|
||||||
|
v 5.571022 0.716382 -0.673535
|
||||||
|
v 5.905705 0.758165 -0.699682
|
||||||
|
v 6.299025 0.780442 -0.683500
|
||||||
|
v 6.288245 0.739248 -0.612975
|
||||||
|
v 5.995947 0.722692 -0.625000
|
||||||
|
v 5.708329 0.660628 -0.556788
|
||||||
|
v 5.295474 0.403530 -0.722041
|
||||||
|
v 5.296155 0.476288 -0.594668
|
||||||
|
v 5.571025 0.409163 -0.673559
|
||||||
|
v 5.905710 0.367392 -0.699712
|
||||||
|
v 6.299029 0.345120 -0.683534
|
||||||
|
v 6.288249 0.386303 -0.613002
|
||||||
|
v 5.995951 0.402854 -0.625025
|
||||||
|
v 5.708331 0.464902 -0.556803
|
||||||
|
v 5.165639 -0.318491 0.637328
|
||||||
|
v 5.166101 -0.159250 0.913146
|
||||||
|
v 4.998497 -0.252327 1.074635
|
||||||
|
v 5.183997 -0.172954 0.637297
|
||||||
|
v 5.184248 -0.086480 0.787078
|
||||||
|
v 5.445252 -0.307224 0.636859
|
||||||
|
v 5.445698 -0.153617 0.902920
|
||||||
|
v 5.773065 -0.390779 0.636310
|
||||||
|
v 5.773632 -0.195395 0.974730
|
||||||
|
v 6.164821 -0.435329 0.635652
|
||||||
|
v 6.165453 -0.217671 1.012654
|
||||||
|
v 6.163937 -0.352950 0.635654
|
||||||
|
v 6.164450 -0.176480 0.941314
|
||||||
|
v 5.872800 -0.319843 0.636142
|
||||||
|
v 5.873264 -0.159926 0.913131
|
||||||
|
v 5.597437 -0.195729 0.636604
|
||||||
|
v 5.597722 -0.097867 0.806108
|
||||||
|
v 5.444824 0.000000 0.636860
|
||||||
|
v 5.166102 0.159236 0.913155
|
||||||
|
v 5.184248 0.086472 0.787083
|
||||||
|
v 5.445698 0.153603 0.902928
|
||||||
|
v 5.773632 0.195378 0.974740
|
||||||
|
v 6.165453 0.217651 1.012665
|
||||||
|
v 6.164450 0.176464 0.941323
|
||||||
|
v 5.873265 0.159912 0.913140
|
||||||
|
v 5.597722 0.097858 0.806113
|
||||||
|
v 5.165639 0.318491 0.637345
|
||||||
|
v 4.997765 0.504639 0.637636
|
||||||
|
v 5.183997 0.172954 0.637307
|
||||||
|
v 5.445252 0.307224 0.636875
|
||||||
|
v 5.773065 0.390779 0.636330
|
||||||
|
v 6.164821 0.435329 0.635675
|
||||||
|
v 6.163937 0.352950 0.635673
|
||||||
|
v 5.872800 0.319843 0.636159
|
||||||
|
v 5.597437 0.195729 0.636614
|
||||||
|
v 5.165176 0.159265 0.361518
|
||||||
|
v 4.997031 0.252350 0.200598
|
||||||
|
v 5.183746 0.086488 0.487521
|
||||||
|
v 5.444806 0.153631 0.370806
|
||||||
|
v 5.772497 0.195413 0.297899
|
||||||
|
v 6.164188 0.217691 0.258662
|
||||||
|
v 6.163424 0.176496 0.330003
|
||||||
|
v 5.872335 0.159941 0.359162
|
||||||
|
v 5.597153 0.097876 0.467105
|
||||||
|
v 5.165176 -0.159221 0.361493
|
||||||
|
v 4.997031 -0.252281 0.200558
|
||||||
|
v 5.183746 -0.086464 0.487507
|
||||||
|
v 5.444806 -0.153589 0.370782
|
||||||
|
v 5.772497 -0.195360 0.297868
|
||||||
|
v 6.164188 -0.217631 0.258628
|
||||||
|
v 6.163424 -0.176448 0.329975
|
||||||
|
v 5.872335 -0.159897 0.359136
|
||||||
|
v 5.597153 -0.097850 0.467090
|
||||||
|
v 5.090927 -1.067391 -0.472156
|
||||||
|
v 5.171283 1.310384 -1.055942
|
||||||
|
v 5.151606 0.310470 -0.905003
|
||||||
|
v 5.151606 -0.310470 -0.905003
|
||||||
|
v 5.030257 0.815056 -0.039376
|
||||||
|
v 5.030259 0.310424 -0.039389
|
||||||
|
v 5.090930 -0.058113 -0.472183
|
||||||
|
v 5.090930 0.058113 -0.472183
|
||||||
|
v 5.000295 -1.210004 0.173074
|
||||||
|
v 5.000295 1.210004 0.173074
|
||||||
|
v 5.000295 -1.428028 0.442095
|
||||||
|
v 4.997764 -0.504639 0.637610
|
||||||
|
v 4.998497 0.252304 1.074648
|
||||||
|
v 4.998233 0.130896 1.193100
|
||||||
|
v 5.000295 1.510030 0.750093
|
||||||
|
v 5.151601 0.815102 -0.904963
|
||||||
|
v 5.090927 1.067391 -0.472156
|
||||||
|
v 3.070224 -1.053627 0.449897
|
||||||
|
v -5.349205 0.737229 0.323968
|
||||||
|
v -5.349205 -0.737229 0.323968
|
||||||
|
v -5.349476 -0.470935 0.566062
|
||||||
|
v -6.499984 -0.098825 0.133439
|
||||||
|
v -6.499984 0.098825 0.133439
|
||||||
|
v -6.499984 -0.523000 -0.048800
|
||||||
|
v -5.349476 0.470935 0.566062
|
||||||
|
v -4.999902 1.000020 -0.943979
|
||||||
|
v 0.840214 2.480049 -1.050312
|
||||||
|
v 1.209237 -1.080021 -0.636414
|
||||||
|
v 3.804262 4.682100 -0.938960
|
||||||
|
v 5.000295 -1.302926 -1.259946
|
||||||
|
v 3.804262 -4.682100 -0.938960
|
||||||
|
v -4.649856 -0.514670 0.885149
|
||||||
|
v -4.999492 0.681710 0.569242
|
||||||
|
v -4.649417 0.860391 0.497003
|
||||||
|
v -4.906714 0.620194 0.686502
|
||||||
|
v -4.649417 -0.860391 0.497003
|
||||||
|
v -4.999492 -0.681710 0.569242
|
||||||
|
# 310 vertices
|
||||||
|
|
||||||
|
# 0 vertex parms
|
||||||
|
|
||||||
|
# 0 texture vertices
|
||||||
|
|
||||||
|
# 0 normals
|
||||||
|
|
||||||
|
g windows
|
||||||
|
# usemtl glass
|
||||||
|
s 1
|
||||||
|
f 310 32 294
|
||||||
|
f 76 308 306
|
||||||
|
f 294 88 33
|
||||||
|
f 310 31 32
|
||||||
|
f 88 294 32
|
||||||
|
f 87 33 88 78
|
||||||
|
f 87 78 298
|
||||||
|
f 298 76 306
|
||||||
|
f 298 78 76
|
||||||
|
g tail
|
||||||
|
# usemtl bone
|
||||||
|
s 4
|
||||||
|
f 95 3 96 4
|
||||||
|
f 4 287 43 95
|
||||||
|
f 94 2 3 43
|
||||||
|
f 3 2 93 96
|
||||||
|
f 41 1 93 42
|
||||||
|
f 41 42 287
|
||||||
|
f 43 3 95
|
||||||
|
f 287 42 94 43
|
||||||
|
f 42 93 2 94
|
||||||
|
f 96 93 1
|
||||||
|
g rearbody
|
||||||
|
s 6
|
||||||
|
f 275 98 54
|
||||||
|
f 96 223 286 287
|
||||||
|
f 97 277 155
|
||||||
|
f 276 281 280 277
|
||||||
|
f 276 275 289
|
||||||
|
f 283 282 128 279
|
||||||
|
f 283 290 275
|
||||||
|
f 257 51 248
|
||||||
|
f 282 303 97
|
||||||
|
f 96 6 106
|
||||||
|
f 303 12 97
|
||||||
|
f 104 285 223
|
||||||
|
f 97 155 274
|
||||||
|
f 284 282 266
|
||||||
|
f 286 288 287
|
||||||
|
f 137 128 282
|
||||||
|
f 283 279 278
|
||||||
|
f 248 288 286
|
||||||
|
f 6 105 106
|
||||||
|
f 275 54 283
|
||||||
|
f 284 266 285
|
||||||
|
f 96 287 4
|
||||||
|
f 284 285 104
|
||||||
|
f 248 51 288
|
||||||
|
f 283 278 290
|
||||||
|
f 274 137 282
|
||||||
|
f 289 275 290
|
||||||
|
f 97 12 98 275
|
||||||
|
f 48 107 45
|
||||||
|
f 96 106 104
|
||||||
|
f 282 283 257 266
|
||||||
|
f 97 275 276 277
|
||||||
|
f 104 223 96
|
||||||
|
f 257 283 51
|
||||||
|
f 97 274 282
|
||||||
|
f 128 280 281 279
|
||||||
|
f 287 288 48
|
||||||
|
f 287 48 45
|
||||||
|
g body
|
||||||
|
s 7
|
||||||
|
f 309 31 310
|
||||||
|
f 294 33 295
|
||||||
|
f 108 118 39
|
||||||
|
f 80 79 74 73
|
||||||
|
f 49 47 48
|
||||||
|
f 5 1 91 24
|
||||||
|
f 10 291 20 19
|
||||||
|
f 294 295 38
|
||||||
|
f 78 77 76
|
||||||
|
f 81 82 111 112
|
||||||
|
f 65 66 46 47
|
||||||
|
f 30 309 310
|
||||||
|
f 5 105 6
|
||||||
|
f 30 29 26 309
|
||||||
|
f 68 62 59 299
|
||||||
|
f 78 88 89 77
|
||||||
|
f 118 38 295 119
|
||||||
|
f 83 81 112 113
|
||||||
|
f 64 65 47 49
|
||||||
|
f 35 37 36
|
||||||
|
f 23 8 7
|
||||||
|
f 24 91 90 305
|
||||||
|
f 62 52 53 59
|
||||||
|
f 296 85 109 114
|
||||||
|
f 79 292 75 74
|
||||||
|
f 50 49 288
|
||||||
|
f 22 23 27
|
||||||
|
f 282 10 11 303
|
||||||
|
f 293 294 297
|
||||||
|
f 71 72 92 67
|
||||||
|
f 112 39 113
|
||||||
|
f 310 294 293
|
||||||
|
f 305 90 89
|
||||||
|
f 308 70 307
|
||||||
|
f 296 87 298
|
||||||
|
f 114 39 119
|
||||||
|
f 71 77 72
|
||||||
|
f 45 107 44
|
||||||
|
f 8 23 22
|
||||||
|
f 7 5 24 23
|
||||||
|
f 287 44 41
|
||||||
|
f 307 69 74 75
|
||||||
|
f 92 91 1 41
|
||||||
|
f 63 62 68
|
||||||
|
f 28 29 34 35
|
||||||
|
f 105 7 8 106
|
||||||
|
f 32 89 88
|
||||||
|
f 49 48 288
|
||||||
|
f 82 81 299
|
||||||
|
f 115 37 297 108
|
||||||
|
f 113 39 110
|
||||||
|
f 73 74 69 68
|
||||||
|
f 29 30 293 34
|
||||||
|
f 291 104 9
|
||||||
|
f 22 27 309
|
||||||
|
f 54 53 52 283
|
||||||
|
f 83 79 80
|
||||||
|
f 83 80 81
|
||||||
|
f 48 47 46 107
|
||||||
|
f 25 20 21 26
|
||||||
|
f 301 11 10 19
|
||||||
|
f 39 115 108
|
||||||
|
f 306 307 75
|
||||||
|
f 110 39 109
|
||||||
|
f 292 298 306
|
||||||
|
f 306 308 307
|
||||||
|
f 70 66 65
|
||||||
|
f 294 38 297
|
||||||
|
f 5 6 96
|
||||||
|
f 85 84 110 109
|
||||||
|
f 62 63 50 52
|
||||||
|
f 102 25 28
|
||||||
|
f 9 106 8
|
||||||
|
f 310 293 30
|
||||||
|
f 70 71 66
|
||||||
|
f 77 89 90 72
|
||||||
|
f 66 71 67
|
||||||
|
f 297 37 34 293
|
||||||
|
f 106 9 104
|
||||||
|
f 25 19 20
|
||||||
|
f 44 107 46
|
||||||
|
f 85 296 298
|
||||||
|
f 117 101 36 116
|
||||||
|
f 111 39 112
|
||||||
|
f 307 70 65
|
||||||
|
f 35 34 37
|
||||||
|
f 23 305 27
|
||||||
|
f 102 301 19 25
|
||||||
|
f 50 288 51
|
||||||
|
f 80 73 299
|
||||||
|
f 84 298 292
|
||||||
|
f 49 50 63 64
|
||||||
|
f 32 305 89
|
||||||
|
f 1 5 96
|
||||||
|
f 32 31 27 305
|
||||||
|
f 66 67 44 46
|
||||||
|
f 296 295 33 87
|
||||||
|
f 291 10 282
|
||||||
|
f 81 80 299
|
||||||
|
f 309 27 31
|
||||||
|
f 84 85 298
|
||||||
|
f 116 36 37 115
|
||||||
|
f 292 79 83 84
|
||||||
|
f 283 52 51
|
||||||
|
f 309 26 21 22
|
||||||
|
f 284 291 282
|
||||||
|
f 102 36 101
|
||||||
|
f 65 64 69 307
|
||||||
|
f 295 296 114 119
|
||||||
|
f 73 68 299
|
||||||
|
f 39 116 115
|
||||||
|
f 105 5 7
|
||||||
|
f 23 24 305
|
||||||
|
f 39 117 116
|
||||||
|
f 77 71 76
|
||||||
|
f 109 39 114
|
||||||
|
f 297 38 118 108
|
||||||
|
f 75 292 306
|
||||||
|
f 39 118 119
|
||||||
|
f 21 20 291 9
|
||||||
|
f 9 8 22 21
|
||||||
|
f 287 45 44
|
||||||
|
f 71 70 308 76
|
||||||
|
f 84 83 113 110
|
||||||
|
f 67 92 41 44
|
||||||
|
f 25 26 29 28
|
||||||
|
f 104 291 284
|
||||||
|
f 102 28 35
|
||||||
|
f 69 64 63 68
|
||||||
|
f 72 90 91 92
|
||||||
|
f 52 50 51
|
||||||
|
f 102 35 36
|
||||||
|
g wings
|
||||||
|
s 5
|
||||||
|
f 16 15 17
|
||||||
|
f 304 15 16
|
||||||
|
f 300 57 60
|
||||||
|
f 14 13 304
|
||||||
|
f 59 53 55 57
|
||||||
|
f 60 57 58
|
||||||
|
f 18 301 103
|
||||||
|
f 300 59 57
|
||||||
|
f 304 13 15
|
||||||
|
f 56 55 53 54
|
||||||
|
f 15 13 11 301
|
||||||
|
f 61 59 300
|
||||||
|
f 57 55 302
|
||||||
|
f 103 301 102
|
||||||
|
f 17 15 301
|
||||||
|
f 303 11 13 14
|
||||||
|
f 58 57 302
|
||||||
|
f 302 55 56
|
||||||
|
f 17 301 18
|
||||||
|
f 299 59 61
|
||||||
|
g tiles
|
||||||
|
# usemtl fldkdkgrey
|
||||||
|
s 3
|
||||||
|
f 302 56 54
|
||||||
|
f 18 103 40
|
||||||
|
f 16 17 99
|
||||||
|
f 86 61 300
|
||||||
|
f 99 304 16
|
||||||
|
f 303 14 304
|
||||||
|
f 99 303 304
|
||||||
|
f 17 18 99
|
||||||
|
f 302 54 100
|
||||||
|
f 58 302 100
|
||||||
|
f 100 86 300
|
||||||
|
f 18 40 99
|
||||||
|
f 100 60 58
|
||||||
|
f 100 300 60
|
||||||
|
f 101 117 111 82
|
||||||
|
f 102 101 82 299
|
||||||
|
f 117 39 111
|
||||||
|
f 99 100 54 303
|
||||||
|
f 303 54 98 12
|
||||||
|
f 86 100 99 40
|
||||||
|
f 40 103 61 86
|
||||||
|
f 299 61 103 102
|
||||||
|
g enginside
|
||||||
|
# usemtl redbrick
|
||||||
|
s 9
|
||||||
|
f 238 255 246
|
||||||
|
f 194 202 201 193
|
||||||
|
f 153 162 163 154
|
||||||
|
f 144 153 154 145
|
||||||
|
f 184 194 193 182
|
||||||
|
f 238 246 237
|
||||||
|
f 272 234 232 271
|
||||||
|
f 236 237 235 234
|
||||||
|
f 204 195 186
|
||||||
|
f 134 143 144 135
|
||||||
|
f 143 152 153 144
|
||||||
|
f 204 203 195
|
||||||
|
f 237 246 245 235
|
||||||
|
f 273 236 234 272
|
||||||
|
f 238 237 236
|
||||||
|
f 185 184 182 183
|
||||||
|
f 135 144 145 136
|
||||||
|
f 154 163 146
|
||||||
|
f 195 203 202 194
|
||||||
|
f 235 245 244 233
|
||||||
|
f 264 273 272 263
|
||||||
|
f 219 185 183 218
|
||||||
|
f 187 186 184 185
|
||||||
|
f 136 145 146
|
||||||
|
f 161 169 170 162
|
||||||
|
f 204 220 212
|
||||||
|
f 255 264 263 254
|
||||||
|
f 234 235 233 232
|
||||||
|
f 186 195 194 184
|
||||||
|
f 145 154 146
|
||||||
|
f 152 161 162 153
|
||||||
|
f 204 212 203
|
||||||
|
f 246 255 254 245
|
||||||
|
f 238 236 273
|
||||||
|
f 204 187 220
|
||||||
|
f 169 125 126 170
|
||||||
|
f 126 135 136 127
|
||||||
|
f 163 171 146
|
||||||
|
f 203 212 211 202
|
||||||
|
f 245 254 253 244
|
||||||
|
f 238 273 264
|
||||||
|
f 211 219 218 210
|
||||||
|
f 170 126 127 171
|
||||||
|
f 127 136 146
|
||||||
|
f 162 170 171 163
|
||||||
|
f 202 211 210 201
|
||||||
|
f 238 264 255
|
||||||
|
f 254 263 262 253
|
||||||
|
f 212 220 219 211
|
||||||
|
f 171 127 146
|
||||||
|
f 125 134 135 126
|
||||||
|
f 204 186 187
|
||||||
|
f 220 187 185 219
|
||||||
|
f 263 272 271 262
|
||||||
|
g engout
|
||||||
|
# usemtl black
|
||||||
|
f 251 260 259 250
|
||||||
|
f 209 217 216 208
|
||||||
|
f 157 165 166 158
|
||||||
|
f 132 141 142 133
|
||||||
|
f 179 178 176 177
|
||||||
|
f 215 177 175 214
|
||||||
|
f 270 230 228 269
|
||||||
|
f 227 241 240 225
|
||||||
|
f 191 199 198 190
|
||||||
|
f 150 159 160 151
|
||||||
|
f 131 140 141 132
|
||||||
|
f 177 176 174 175
|
||||||
|
f 230 231 229 228
|
||||||
|
f 269 228 226 268
|
||||||
|
f 229 242 241 227
|
||||||
|
f 192 200 199 191
|
||||||
|
f 139 148 149 140
|
||||||
|
f 130 139 140 131
|
||||||
|
f 180 192 191 178
|
||||||
|
f 228 229 227 226
|
||||||
|
f 268 226 224 267
|
||||||
|
f 231 243 242 229
|
||||||
|
f 176 190 189 174
|
||||||
|
f 140 149 150 141
|
||||||
|
f 149 158 159 150
|
||||||
|
f 190 198 197 189
|
||||||
|
f 243 252 251 242
|
||||||
|
f 259 268 267 258
|
||||||
|
f 216 179 177 215
|
||||||
|
f 181 180 178 179
|
||||||
|
f 121 130 131 122
|
||||||
|
f 167 123 124 168
|
||||||
|
f 208 216 215 207
|
||||||
|
f 250 259 258 249
|
||||||
|
f 252 261 260 251
|
||||||
|
f 198 207 206 197
|
||||||
|
f 158 166 167 159
|
||||||
|
f 123 132 133 124
|
||||||
|
f 166 122 123 167
|
||||||
|
f 207 215 214 206
|
||||||
|
f 261 270 269 260
|
||||||
|
f 241 250 249 240
|
||||||
|
f 199 208 207 198
|
||||||
|
f 159 167 168 160
|
||||||
|
f 122 131 132 123
|
||||||
|
f 165 121 122 166
|
||||||
|
f 217 181 179 216
|
||||||
|
f 260 269 268 259
|
||||||
|
f 242 251 250 241
|
||||||
|
f 200 209 208 199
|
||||||
|
f 148 157 158 149
|
||||||
|
f 141 150 151 142
|
||||||
|
f 178 191 190 176
|
||||||
|
f 226 227 225 224
|
||||||
|
g engmount
|
||||||
|
# usemtl brass
|
||||||
|
s 11
|
||||||
|
f 225 240 239 222
|
||||||
|
f 164 120 121 165
|
||||||
|
f 128 137 138 129
|
||||||
|
f 196 205 289 290
|
||||||
|
f 265 221 285 266
|
||||||
|
f 206 214 213 205
|
||||||
|
f 138 147 148 139
|
||||||
|
f 174 189 188 172
|
||||||
|
f 249 258 256 247
|
||||||
|
f 221 222 223 285
|
||||||
|
f 155 277 164 156
|
||||||
|
f 274 155 156 147
|
||||||
|
f 213 173 281 276
|
||||||
|
f 258 267 265 256
|
||||||
|
f 189 197 196 188
|
||||||
|
f 120 129 130 121
|
||||||
|
f 173 172 279 281
|
||||||
|
f 239 247 248 286
|
||||||
|
f 205 213 276 289
|
||||||
|
f 137 274 147 138
|
||||||
|
f 156 164 165 157
|
||||||
|
f 224 225 222 221
|
||||||
|
f 247 256 257 248
|
||||||
|
f 172 188 278 279
|
||||||
|
f 280 128 129 120
|
||||||
|
f 188 196 290 278
|
||||||
|
f 256 265 266 257
|
||||||
|
f 214 175 173 213
|
||||||
|
f 147 156 157 148
|
||||||
|
f 175 174 172 173
|
||||||
|
f 240 249 247 239
|
||||||
|
f 222 239 286 223
|
||||||
|
f 277 280 120 164
|
||||||
|
f 129 138 139 130
|
||||||
|
f 197 206 205 196
|
||||||
|
f 267 224 221 265
|
||||||
|
g engrim
|
||||||
|
# usemtl dkdkgrey
|
||||||
|
s off
|
||||||
|
f 233 244 243 231
|
||||||
|
f 124 133 134 125
|
||||||
|
f 262 271 270 261
|
||||||
|
f 142 151 152 143
|
||||||
|
f 253 262 261 252
|
||||||
|
f 151 160 161 152
|
||||||
|
f 244 253 252 243
|
||||||
|
f 160 168 169 161
|
||||||
|
f 201 210 209 200
|
||||||
|
f 271 232 230 270
|
||||||
|
f 133 142 143 134
|
||||||
|
f 232 233 231 230
|
||||||
|
f 183 182 180 181
|
||||||
|
f 218 183 181 217
|
||||||
|
f 182 193 192 180
|
||||||
|
f 210 218 217 209
|
||||||
|
f 193 201 200 192
|
||||||
|
f 168 124 125 169
|
||||||
|
# 393 elements
|
4095
data/models/skyscraper.obj
Normal file
4393
data/models/slot_machine.obj
Normal file
82
data/models/superman.mtl
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
# Blender3D MTL File:
|
||||||
|
# Material Count: 8
|
||||||
|
newmtl log1.001
|
||||||
|
Ns 96.078431
|
||||||
|
Ka 0.000000 0.000000 0.000000
|
||||||
|
Kd 0.320000 0.200784 0.379608
|
||||||
|
Ks 0.165000 0.165000 0.165000
|
||||||
|
Ni 1.000000
|
||||||
|
d 1.000000
|
||||||
|
illum 2
|
||||||
|
|
||||||
|
|
||||||
|
newmtl _DimGray_.001
|
||||||
|
Ns 96.078431
|
||||||
|
Ka 0.000000 0.000000 0.000000
|
||||||
|
Kd 0.329412 0.329412 0.329412
|
||||||
|
Ks 0.165000 0.165000 0.165000
|
||||||
|
Ni 1.000000
|
||||||
|
d 1.000000
|
||||||
|
illum 2
|
||||||
|
|
||||||
|
|
||||||
|
newmtl belt1.001
|
||||||
|
Ns 96.078431
|
||||||
|
Ka 0.000000 0.000000 0.000000
|
||||||
|
Kd 0.712157 0.727843 0.147451
|
||||||
|
Ks 0.165000 0.165000 0.165000
|
||||||
|
Ni 1.000000
|
||||||
|
d 1.000000
|
||||||
|
illum 2
|
||||||
|
|
||||||
|
|
||||||
|
newmtl blue1.001
|
||||||
|
Ns 96.078431
|
||||||
|
Ka 0.000000 0.000000 0.000000
|
||||||
|
Kd 0.021961 0.392157 0.762353
|
||||||
|
Ks 0.165000 0.165000 0.165000
|
||||||
|
Ni 1.000000
|
||||||
|
d 1.000000
|
||||||
|
illum 2
|
||||||
|
|
||||||
|
|
||||||
|
newmtl hairrrr1.001
|
||||||
|
Ns 96.078431
|
||||||
|
Ka 0.000000 0.000000 0.000000
|
||||||
|
Kd 0.040784 0.094118 0.090980
|
||||||
|
Ks 0.165000 0.165000 0.165000
|
||||||
|
Ni 1.000000
|
||||||
|
d 1.000000
|
||||||
|
illum 2
|
||||||
|
|
||||||
|
|
||||||
|
newmtl red1.001
|
||||||
|
Ns 96.078431
|
||||||
|
Ka 0.000000 0.000000 0.000000
|
||||||
|
Kd 0.652549 0.003138 0.150588
|
||||||
|
Ks 0.165000 0.165000 0.165000
|
||||||
|
Ni 1.000000
|
||||||
|
d 1.000000
|
||||||
|
illum 2
|
||||||
|
|
||||||
|
|
||||||
|
newmtl _Charcoal_.001
|
||||||
|
Ns 96.078431
|
||||||
|
Ka 0.000000 0.000000 0.000000
|
||||||
|
Kd 0.109804 0.109804 0.109804
|
||||||
|
Ks 0.165000 0.165000 0.165000
|
||||||
|
Ni 1.000000
|
||||||
|
d 1.000000
|
||||||
|
illum 2
|
||||||
|
|
||||||
|
|
||||||
|
newmtl body1.001
|
||||||
|
Ns 96.078431
|
||||||
|
Ka 0.000000 0.000000 0.000000
|
||||||
|
Kd 0.693334 0.401569 0.272941
|
||||||
|
Ks 0.165000 0.165000 0.165000
|
||||||
|
Ni 1.000000
|
||||||
|
d 1.000000
|
||||||
|
illum 2
|
||||||
|
|
||||||
|
|
8755
data/models/superman.obj
Normal file
BIN
data/models/superman.png
Normal file
After Width: | Height: | Size: 4.2 KiB |
960
data/models/vp.mtl
Normal file
|
@ -0,0 +1,960 @@
|
||||||
|
newmtl white
|
||||||
|
Ka 0.4000 0.4000 0.4000
|
||||||
|
Kd 1.0000 1.0000 1.0000
|
||||||
|
Ks 0.3000 0.3000 0.3000
|
||||||
|
illum 2
|
||||||
|
Ns 60.0000
|
||||||
|
|
||||||
|
|
||||||
|
newmtl red
|
||||||
|
Ka 0.4449 0.0000 0.0000
|
||||||
|
Kd 0.7714 0.0000 0.0000
|
||||||
|
Ks 0.8857 0.0000 0.0000
|
||||||
|
illum 2
|
||||||
|
Ns 136.4300
|
||||||
|
|
||||||
|
|
||||||
|
newmtl blue_pure
|
||||||
|
Ka 0.0000 0.0000 0.5000
|
||||||
|
Kd 0.0000 0.0000 1.0000
|
||||||
|
Ks 0.0000 0.0000 0.5000
|
||||||
|
illum 2
|
||||||
|
Ns 65.8900
|
||||||
|
|
||||||
|
|
||||||
|
newmtl lime
|
||||||
|
Ka 0.0000 0.5000 0.0000
|
||||||
|
Kd 0.0000 1.0000 0.0000
|
||||||
|
Ks 0.0000 0.5000 0.0000
|
||||||
|
illum 2
|
||||||
|
Ns 65.8900
|
||||||
|
|
||||||
|
|
||||||
|
newmtl green
|
||||||
|
Ka 0.0000 0.2500 0.0000
|
||||||
|
Kd 0.0000 0.2500 0.0000
|
||||||
|
Ks 0.0000 0.2500 0.0000
|
||||||
|
illum 2
|
||||||
|
Ns 65.8900
|
||||||
|
|
||||||
|
|
||||||
|
newmtl yellow
|
||||||
|
Ka 1.0000 0.6667 0.0000
|
||||||
|
Kd 1.0000 0.6667 0.0000
|
||||||
|
Ks 1.0000 0.6667 0.0000
|
||||||
|
illum 2
|
||||||
|
Ns 65.8900
|
||||||
|
|
||||||
|
|
||||||
|
newmtl purple
|
||||||
|
Ka 0.5000 0.0000 1.0000
|
||||||
|
Kd 0.5000 0.0000 1.0000
|
||||||
|
Ks 0.5000 0.0000 1.0000
|
||||||
|
illum 2
|
||||||
|
Ns 65.8900
|
||||||
|
|
||||||
|
|
||||||
|
newmtl orange
|
||||||
|
Ka 1.0000 0.1667 0.0000
|
||||||
|
Kd 1.0000 0.1667 0.0000
|
||||||
|
Ks 1.0000 0.1667 0.0000
|
||||||
|
illum 2
|
||||||
|
Ns 65.8900
|
||||||
|
|
||||||
|
|
||||||
|
newmtl grey
|
||||||
|
Ka 0.5000 0.5000 0.5000
|
||||||
|
Kd 0.1837 0.1837 0.1837
|
||||||
|
Ks 0.5000 0.5000 0.5000
|
||||||
|
illum 2
|
||||||
|
Ns 65.8900
|
||||||
|
|
||||||
|
|
||||||
|
newmtl rubber
|
||||||
|
Ka 0.0000 0.0000 0.0000
|
||||||
|
Kd 0.0100 0.0100 0.0100
|
||||||
|
Ks 0.1000 0.1000 0.1000
|
||||||
|
illum 2
|
||||||
|
Ns 65.8900
|
||||||
|
|
||||||
|
|
||||||
|
newmtl flaqua
|
||||||
|
Ka 0.0000 0.4000 0.4000
|
||||||
|
Kd 0.0000 0.5000 0.5000
|
||||||
|
illum 1
|
||||||
|
|
||||||
|
|
||||||
|
newmtl flblack
|
||||||
|
Ka 0.0000 0.0000 0.0000
|
||||||
|
Kd 0.0041 0.0041 0.0041
|
||||||
|
illum 1
|
||||||
|
|
||||||
|
|
||||||
|
newmtl flblue_pure
|
||||||
|
Ka 0.0000 0.0000 0.5592
|
||||||
|
Kd 0.0000 0.0000 0.7102
|
||||||
|
illum 1
|
||||||
|
|
||||||
|
|
||||||
|
newmtl flgrey
|
||||||
|
Ka 0.2163 0.2163 0.2163
|
||||||
|
Kd 0.5000 0.5000 0.5000
|
||||||
|
illum 1
|
||||||
|
|
||||||
|
|
||||||
|
newmtl fllime
|
||||||
|
Ka 0.0000 0.3673 0.0000
|
||||||
|
Kd 0.0000 1.0000 0.0000
|
||||||
|
illum 1
|
||||||
|
|
||||||
|
|
||||||
|
newmtl florange
|
||||||
|
Ka 0.6857 0.1143 0.0000
|
||||||
|
Kd 1.0000 0.1667 0.0000
|
||||||
|
illum 1
|
||||||
|
|
||||||
|
|
||||||
|
newmtl flpurple
|
||||||
|
Ka 0.2368 0.0000 0.4735
|
||||||
|
Kd 0.3755 0.0000 0.7510
|
||||||
|
illum 1
|
||||||
|
|
||||||
|
|
||||||
|
newmtl flred
|
||||||
|
Ka 0.4000 0.0000 0.0000
|
||||||
|
Kd 1.0000 0.0000 0.0000
|
||||||
|
illum 1
|
||||||
|
|
||||||
|
|
||||||
|
newmtl flyellow
|
||||||
|
Ka 0.7388 0.4925 0.0000
|
||||||
|
Kd 1.0000 0.6667 0.0000
|
||||||
|
illum 1
|
||||||
|
|
||||||
|
|
||||||
|
newmtl pink
|
||||||
|
Ka 0.9469 0.0078 0.2845
|
||||||
|
Kd 0.9878 0.1695 0.6702
|
||||||
|
Ks 0.7429 0.2972 0.2972
|
||||||
|
illum 2
|
||||||
|
Ns 106.2000
|
||||||
|
|
||||||
|
|
||||||
|
newmtl flbrown
|
||||||
|
Ka 0.0571 0.0066 0.0011
|
||||||
|
Kd 0.1102 0.0120 0.0013
|
||||||
|
illum 1
|
||||||
|
|
||||||
|
|
||||||
|
newmtl brown
|
||||||
|
Ka 0.1020 0.0185 0.0013
|
||||||
|
Kd 0.0857 0.0147 0.0000
|
||||||
|
Ks 0.1633 0.0240 0.0000
|
||||||
|
illum 2
|
||||||
|
Ns 65.8900
|
||||||
|
|
||||||
|
|
||||||
|
newmtl glass
|
||||||
|
Ka 1.0000 1.0000 1.0000
|
||||||
|
Kd 0.5020 0.5020 0.5020
|
||||||
|
Ks 1.0000 1.0000 1.0000
|
||||||
|
illum 2
|
||||||
|
Ns 192.2500
|
||||||
|
|
||||||
|
|
||||||
|
newmtl flesh
|
||||||
|
Ka 0.4612 0.3638 0.2993
|
||||||
|
Kd 0.5265 0.4127 0.3374
|
||||||
|
Ks 0.3000 0.3000 0.3000
|
||||||
|
illum 2
|
||||||
|
Ns 60.0000
|
||||||
|
|
||||||
|
|
||||||
|
newmtl aqua
|
||||||
|
Ka 0.0000 0.4000 0.4000
|
||||||
|
Kd 0.0000 0.5000 0.5000
|
||||||
|
Ks 0.5673 0.5673 0.5673
|
||||||
|
illum 2
|
||||||
|
Ns 60.0000
|
||||||
|
|
||||||
|
|
||||||
|
newmtl black
|
||||||
|
Ka 0.0000 0.0000 0.0000
|
||||||
|
Kd 0.0020 0.0020 0.0020
|
||||||
|
Ks 0.5184 0.5184 0.5184
|
||||||
|
illum 2
|
||||||
|
Ns 157.3600
|
||||||
|
|
||||||
|
|
||||||
|
newmtl silver
|
||||||
|
Ka 0.9551 0.9551 0.9551
|
||||||
|
Kd 0.6163 0.6163 0.6163
|
||||||
|
Ks 0.3000 0.3000 0.3000
|
||||||
|
illum 2
|
||||||
|
Ns 60.0000
|
||||||
|
|
||||||
|
|
||||||
|
newmtl dkblue_pure
|
||||||
|
Ka 0.0000 0.0000 0.0449
|
||||||
|
Kd 0.0000 0.0000 0.1347
|
||||||
|
Ks 0.0000 0.0000 0.5673
|
||||||
|
illum 2
|
||||||
|
Ns 65.8900
|
||||||
|
|
||||||
|
|
||||||
|
newmtl fldkblue_pure
|
||||||
|
Ka 0.0000 0.0000 0.0449
|
||||||
|
Kd 0.0000 0.0000 0.1347
|
||||||
|
illum 1
|
||||||
|
|
||||||
|
|
||||||
|
newmtl dkgreen
|
||||||
|
Ka 0.0000 0.0122 0.0000
|
||||||
|
Kd 0.0058 0.0245 0.0000
|
||||||
|
Ks 0.0000 0.0490 0.0000
|
||||||
|
illum 2
|
||||||
|
Ns 60.0000
|
||||||
|
|
||||||
|
|
||||||
|
newmtl dkgrey
|
||||||
|
Ka 0.4000 0.4000 0.4000
|
||||||
|
Kd 0.0245 0.0245 0.0245
|
||||||
|
Ks 0.3000 0.3000 0.3000
|
||||||
|
illum 2
|
||||||
|
Ns 60.0000
|
||||||
|
|
||||||
|
|
||||||
|
newmtl ltbrown
|
||||||
|
Ka 0.1306 0.0538 0.0250
|
||||||
|
Kd 0.2776 0.1143 0.0531
|
||||||
|
Ks 0.3000 0.1235 0.0574
|
||||||
|
illum 2
|
||||||
|
Ns 60.0000
|
||||||
|
|
||||||
|
|
||||||
|
newmtl fldkgreen
|
||||||
|
Ka 0.0000 0.0122 0.0000
|
||||||
|
Kd 0.0058 0.0245 0.0000
|
||||||
|
illum 1
|
||||||
|
|
||||||
|
|
||||||
|
newmtl flltbrown
|
||||||
|
Ka 0.1306 0.0538 0.0250
|
||||||
|
Kd 0.2776 0.1143 0.0531
|
||||||
|
illum 1
|
||||||
|
|
||||||
|
|
||||||
|
newmtl tan
|
||||||
|
Ka 0.4000 0.3121 0.1202
|
||||||
|
Kd 0.6612 0.5221 0.2186
|
||||||
|
Ks 0.5020 0.4118 0.2152
|
||||||
|
illum 2
|
||||||
|
Ns 60.0000
|
||||||
|
|
||||||
|
|
||||||
|
newmtl fltan
|
||||||
|
Ka 0.4000 0.3121 0.1202
|
||||||
|
Kd 0.6612 0.4567 0.1295
|
||||||
|
illum 1
|
||||||
|
|
||||||
|
|
||||||
|
newmtl brzskin
|
||||||
|
Ka 0.4408 0.2694 0.1592
|
||||||
|
Kd 0.3796 0.2898 0.2122
|
||||||
|
Ks 0.3000 0.3000 0.3000
|
||||||
|
illum 2
|
||||||
|
Ns 25.0000
|
||||||
|
|
||||||
|
|
||||||
|
newmtl lips
|
||||||
|
Ka 0.4408 0.2694 0.1592
|
||||||
|
Kd 0.9265 0.2612 0.2898
|
||||||
|
Ks 0.3000 0.3000 0.3000
|
||||||
|
illum 2
|
||||||
|
Ns 25.0000
|
||||||
|
|
||||||
|
|
||||||
|
newmtl redorange
|
||||||
|
Ka 0.2653 0.0160 0.0097
|
||||||
|
Kd 0.7551 0.0327 0.0146
|
||||||
|
Ks 0.7510 0.0816 0.0490
|
||||||
|
illum 2
|
||||||
|
Ns 132.5600
|
||||||
|
|
||||||
|
|
||||||
|
newmtl blutan
|
||||||
|
Ka 0.4408 0.2694 0.1592
|
||||||
|
Kd 0.0776 0.2571 0.2041
|
||||||
|
Ks 0.1467 0.1469 0.0965
|
||||||
|
illum 2
|
||||||
|
Ns 25.0000
|
||||||
|
|
||||||
|
|
||||||
|
newmtl bluteal
|
||||||
|
Ka 0.0041 0.1123 0.1224
|
||||||
|
Kd 0.0776 0.2571 0.2041
|
||||||
|
Ks 0.1467 0.1469 0.0965
|
||||||
|
illum 2
|
||||||
|
Ns 25.0000
|
||||||
|
|
||||||
|
|
||||||
|
newmtl pinktan
|
||||||
|
Ka 0.4408 0.2694 0.1592
|
||||||
|
Kd 0.6857 0.2571 0.2163
|
||||||
|
Ks 0.1467 0.1469 0.0965
|
||||||
|
illum 2
|
||||||
|
Ns 25.0000
|
||||||
|
|
||||||
|
|
||||||
|
newmtl areola3
|
||||||
|
Ka 0.8122 0.3510 0.1551
|
||||||
|
Kd 0.5469 0.0749 0.0749
|
||||||
|
Ks 0.8490 0.2898 0.3184
|
||||||
|
illum 2
|
||||||
|
Ns 20.9300
|
||||||
|
|
||||||
|
|
||||||
|
newmtl brnhair
|
||||||
|
Ka 0.0612 0.0174 0.0066
|
||||||
|
Kd 0.0898 0.0302 0.0110
|
||||||
|
Ks 0.1306 0.0819 0.0352
|
||||||
|
illum 2
|
||||||
|
Ns 60.4700
|
||||||
|
|
||||||
|
|
||||||
|
newmtl blondhair
|
||||||
|
Ka 0.4449 0.2632 0.0509
|
||||||
|
Kd 0.5714 0.3283 0.0443
|
||||||
|
Ks 0.7755 0.4602 0.0918
|
||||||
|
illum 2
|
||||||
|
Ns 4.6500
|
||||||
|
|
||||||
|
|
||||||
|
newmtl flblonde
|
||||||
|
Ka 0.4449 0.2632 0.0509
|
||||||
|
Kd 0.5714 0.3283 0.0443
|
||||||
|
illum 1
|
||||||
|
|
||||||
|
|
||||||
|
newmtl yelloworng
|
||||||
|
Ka 0.5837 0.1715 0.0000
|
||||||
|
Kd 0.8857 0.2490 0.0000
|
||||||
|
Ks 0.3000 0.3000 0.3000
|
||||||
|
illum 2
|
||||||
|
Ns 60.0000
|
||||||
|
|
||||||
|
|
||||||
|
newmtl bone
|
||||||
|
Ka 0.3633 0.2179 0.1142
|
||||||
|
Kd 0.9000 0.6229 0.2278
|
||||||
|
Ks 0.4612 0.4193 0.2673
|
||||||
|
illum 2
|
||||||
|
Ns 200.0000
|
||||||
|
|
||||||
|
|
||||||
|
#newmtl bone
|
||||||
|
|
||||||
|
newmtl teeth
|
||||||
|
Ka 0.6408 0.5554 0.3845
|
||||||
|
Kd 0.9837 0.7959 0.4694
|
||||||
|
illum 1
|
||||||
|
|
||||||
|
|
||||||
|
newmtl brass
|
||||||
|
Ka 0.2490 0.1102 0.0000
|
||||||
|
Kd 0.4776 0.1959 0.0000
|
||||||
|
Ks 0.5796 0.5796 0.5796
|
||||||
|
illum 2
|
||||||
|
Ns 134.8800
|
||||||
|
|
||||||
|
|
||||||
|
newmtl china
|
||||||
|
Kd 1.0000 1.0000 1.0000
|
||||||
|
illum 0
|
||||||
|
map_Kd china.tif
|
||||||
|
|
||||||
|
|
||||||
|
newmtl dkred
|
||||||
|
Ka 0.0939 0.0000 0.0000
|
||||||
|
Kd 0.2286 0.0000 0.0000
|
||||||
|
Ks 0.2490 0.0000 0.0000
|
||||||
|
illum 2
|
||||||
|
Ns 60.0000
|
||||||
|
|
||||||
|
|
||||||
|
newmtl taupe
|
||||||
|
Ka 0.1061 0.0709 0.0637
|
||||||
|
Kd 0.2041 0.1227 0.1058
|
||||||
|
Ks 0.3000 0.3000 0.3000
|
||||||
|
illum 2
|
||||||
|
Ns 84.5000
|
||||||
|
|
||||||
|
|
||||||
|
newmtl dkteal
|
||||||
|
Ka 0.0000 0.0245 0.0163
|
||||||
|
Kd 0.0000 0.0653 0.0449
|
||||||
|
Ks 0.3000 0.3000 0.3000
|
||||||
|
illum 2
|
||||||
|
Ns 55.0400
|
||||||
|
|
||||||
|
|
||||||
|
newmtl dkdkgrey
|
||||||
|
Ka 0.0000 0.0000 0.0000
|
||||||
|
Kd 0.0122 0.0122 0.0122
|
||||||
|
Ks 0.3000 0.3000 0.3000
|
||||||
|
illum 2
|
||||||
|
Ns 60.0000
|
||||||
|
|
||||||
|
|
||||||
|
newmtl dkblue
|
||||||
|
Ka 0.0000 0.0029 0.0408
|
||||||
|
Kd 0.0000 0.0041 0.0571
|
||||||
|
Ks 0.3000 0.3000 0.3000
|
||||||
|
illum 2
|
||||||
|
Ns 60.0000
|
||||||
|
|
||||||
|
|
||||||
|
newmtl gold
|
||||||
|
Ka 0.5265 0.2735 0.0122
|
||||||
|
Kd 1.0000 0.5184 0.0286
|
||||||
|
Ks 0.3000 0.3000 0.3000
|
||||||
|
illum 2
|
||||||
|
Ns 123.2600
|
||||||
|
|
||||||
|
|
||||||
|
newmtl redbrick
|
||||||
|
Ka 0.1102 0.0000 0.0000
|
||||||
|
Kd 0.4939 0.1469 0.0766
|
||||||
|
illum 1
|
||||||
|
|
||||||
|
|
||||||
|
newmtl flmustard
|
||||||
|
Ka 0.4490 0.2653 0.0000
|
||||||
|
Kd 0.7959 0.4082 0.0694
|
||||||
|
illum 1
|
||||||
|
|
||||||
|
|
||||||
|
newmtl flpinegreen
|
||||||
|
Ka 0.0367 0.0612 0.0204
|
||||||
|
Kd 0.1061 0.2163 0.0857
|
||||||
|
illum 1
|
||||||
|
|
||||||
|
|
||||||
|
newmtl fldkred
|
||||||
|
Ka 0.0939 0.0000 0.0000
|
||||||
|
Kd 0.2286 0.0082 0.0082
|
||||||
|
illum 1
|
||||||
|
|
||||||
|
|
||||||
|
newmtl fldkgreen2
|
||||||
|
Ka 0.0025 0.0122 0.0014
|
||||||
|
Kd 0.0245 0.0694 0.0041
|
||||||
|
illum 1
|
||||||
|
|
||||||
|
|
||||||
|
newmtl flmintgreen
|
||||||
|
Ka 0.0408 0.1429 0.0571
|
||||||
|
Kd 0.1306 0.2898 0.1673
|
||||||
|
illum 1
|
||||||
|
|
||||||
|
|
||||||
|
newmtl olivegreen
|
||||||
|
Ka 0.0167 0.0245 0.0000
|
||||||
|
Kd 0.0250 0.0367 0.0000
|
||||||
|
Ks 0.2257 0.2776 0.1167
|
||||||
|
illum 2
|
||||||
|
Ns 97.6700
|
||||||
|
|
||||||
|
|
||||||
|
newmtl skin
|
||||||
|
Ka 0.2286 0.0187 0.0187
|
||||||
|
Kd 0.1102 0.0328 0.0139
|
||||||
|
Ks 0.3000 0.3000 0.3000
|
||||||
|
illum 2
|
||||||
|
Ns 17.8300
|
||||||
|
|
||||||
|
|
||||||
|
newmtl redbrown
|
||||||
|
Ka 0.1469 0.0031 0.0000
|
||||||
|
Kd 0.2816 0.0060 0.0000
|
||||||
|
Ks 0.3714 0.3714 0.3714
|
||||||
|
illum 2
|
||||||
|
Ns 141.0900
|
||||||
|
|
||||||
|
|
||||||
|
newmtl deepgreen
|
||||||
|
Ka 0.0000 0.0050 0.0000
|
||||||
|
Kd 0.0000 0.0204 0.0050
|
||||||
|
Ks 0.3000 0.3000 0.3000
|
||||||
|
illum 2
|
||||||
|
Ns 113.1800
|
||||||
|
|
||||||
|
|
||||||
|
newmtl flltolivegreen
|
||||||
|
Ka 0.0167 0.0245 0.0000
|
||||||
|
Kd 0.0393 0.0531 0.0100
|
||||||
|
illum 1
|
||||||
|
|
||||||
|
|
||||||
|
newmtl faceim
|
||||||
|
Ka 0.0000 0.0000 0.0000
|
||||||
|
Kd 1.0000 1.0000 1.0000
|
||||||
|
Ks 0.0000 0.0000 0.0000
|
||||||
|
illum 2
|
||||||
|
Ns 60.0000
|
||||||
|
map_Kd richmap.rgb
|
||||||
|
|
||||||
|
|
||||||
|
newmtl faceimx
|
||||||
|
Ka 0.0000 0.0000 0.0000
|
||||||
|
Kd 1.0000 0.7306 0.7429
|
||||||
|
Ks 0.0000 0.0000 0.0000
|
||||||
|
illum 2
|
||||||
|
Ns 0.0000
|
||||||
|
map_Kd richmap.rgb
|
||||||
|
|
||||||
|
|
||||||
|
newmtl jetflame
|
||||||
|
Ka 0.7714 0.1469 0.0000
|
||||||
|
Kd 0.9510 0.4939 0.0980
|
||||||
|
Ks 0.8531 0.4041 0.0000
|
||||||
|
illum 2
|
||||||
|
Ns 132.5600
|
||||||
|
|
||||||
|
|
||||||
|
newmtl brownskn
|
||||||
|
Ka 0.0122 0.0041 0.0000
|
||||||
|
Kd 0.0204 0.0082 0.0000
|
||||||
|
Ks 0.0735 0.0508 0.0321
|
||||||
|
illum 2
|
||||||
|
Ns 20.1600
|
||||||
|
|
||||||
|
|
||||||
|
newmtl greenskn
|
||||||
|
Ka 0.0816 0.0449 0.0000
|
||||||
|
Kd 0.0000 0.0735 0.0000
|
||||||
|
Ks 0.0490 0.1224 0.0898
|
||||||
|
illum 3
|
||||||
|
Ns 46.5100
|
||||||
|
sharpness 146.5100
|
||||||
|
|
||||||
|
|
||||||
|
#bump -bm 2.000 -o -0.870 -0.260 0.870 -s -0.420 2.770 0.500 -t 0.010 0.500 0.490 /liberty/people/vp/Brian/Maps/ashwood.tga
|
||||||
|
#refl -type sphere /liberty/people/vp/Brian/Maps/evrgreen.tga
|
||||||
|
|
||||||
|
newmtl ltgrey
|
||||||
|
Ka 0.5000 0.5000 0.5000
|
||||||
|
Kd 0.3837 0.3837 0.3837
|
||||||
|
Ks 0.5000 0.5000 0.5000
|
||||||
|
illum 2
|
||||||
|
Ns 65.8900
|
||||||
|
|
||||||
|
|
||||||
|
newmtl bronze
|
||||||
|
Ka 0.0449 0.0204 0.0000
|
||||||
|
Kd 0.0653 0.0367 0.0122
|
||||||
|
Ks 0.0776 0.0408 0.0000
|
||||||
|
illum 3
|
||||||
|
Ns 137.2100
|
||||||
|
sharpness 125.5800
|
||||||
|
|
||||||
|
|
||||||
|
newmtl bone1
|
||||||
|
Ka 0.6408 0.5554 0.3845
|
||||||
|
Kd 0.9837 0.7959 0.4694
|
||||||
|
illum 1
|
||||||
|
|
||||||
|
|
||||||
|
newmtl flwhite1
|
||||||
|
Ka 0.9306 0.9306 0.9306
|
||||||
|
Kd 1.0000 1.0000 1.0000
|
||||||
|
illum 1
|
||||||
|
|
||||||
|
|
||||||
|
newmtl flwhite
|
||||||
|
Ka 0.1551 0.1471 0.1310
|
||||||
|
Kd 0.9837 0.9309 0.8392
|
||||||
|
Ks 0.8082 0.7290 0.5708
|
||||||
|
illum 2
|
||||||
|
Ns 200.0000
|
||||||
|
|
||||||
|
|
||||||
|
newmtl shadow
|
||||||
|
Kd 0.0350 0.0248 0.0194
|
||||||
|
illum 0
|
||||||
|
d 0.7500
|
||||||
|
|
||||||
|
|
||||||
|
newmtl fldkolivegreen
|
||||||
|
Ka 0.0056 0.0082 0.0000
|
||||||
|
Kd 0.0151 0.0204 0.0038
|
||||||
|
illum 1
|
||||||
|
|
||||||
|
|
||||||
|
newmtl fldkdkgrey
|
||||||
|
Ka 0.0000 0.0000 0.0000
|
||||||
|
Kd 0.0122 0.0122 0.0122
|
||||||
|
illum 1
|
||||||
|
|
||||||
|
|
||||||
|
newmtl lcdgreen
|
||||||
|
Ka 0.4000 0.4000 0.4000
|
||||||
|
Kd 0.5878 1.0000 0.5061
|
||||||
|
Ks 0.3000 0.3000 0.3000
|
||||||
|
illum 2
|
||||||
|
Ns 60.0000
|
||||||
|
|
||||||
|
|
||||||
|
newmtl brownlips
|
||||||
|
Ka 0.1143 0.0694 0.0245
|
||||||
|
Kd 0.1429 0.0653 0.0408
|
||||||
|
Ks 0.3000 0.3000 0.3000
|
||||||
|
illum 2
|
||||||
|
Ns 25.0000
|
||||||
|
|
||||||
|
|
||||||
|
newmtl muscle
|
||||||
|
Ka 0.2122 0.0077 0.0154
|
||||||
|
Kd 0.4204 0.0721 0.0856
|
||||||
|
Ks 0.1184 0.1184 0.1184
|
||||||
|
illum 2
|
||||||
|
Ns 25.5800
|
||||||
|
|
||||||
|
|
||||||
|
newmtl flltgrey
|
||||||
|
Ka 0.5000 0.5000 0.5000
|
||||||
|
Kd 0.3837 0.3837 0.3837
|
||||||
|
illum 1
|
||||||
|
|
||||||
|
|
||||||
|
newmtl offwhite.warm
|
||||||
|
Ka 0.5184 0.4501 0.3703
|
||||||
|
Kd 0.8367 0.6898 0.4490
|
||||||
|
Ks 0.3000 0.3000 0.3000
|
||||||
|
illum 2
|
||||||
|
Ns 60.0000
|
||||||
|
|
||||||
|
|
||||||
|
newmtl offwhite.cool
|
||||||
|
Ka 0.5184 0.4501 0.3703
|
||||||
|
Kd 0.8367 0.6812 0.5703
|
||||||
|
Ks 0.3000 0.3000 0.3000
|
||||||
|
illum 2
|
||||||
|
Ns 60.0000
|
||||||
|
|
||||||
|
|
||||||
|
newmtl test2
|
||||||
|
Ka 1.0000 1.0000 1.0000
|
||||||
|
Kd 0.3336 0.6286 0.0000
|
||||||
|
Ks 0.3000 0.3000 0.3000
|
||||||
|
illum 2
|
||||||
|
Ns 31.0100
|
||||||
|
map_Kd -mm -0.270 0.500 skincol1.tif
|
||||||
|
|
||||||
|
|
||||||
|
newmtl test3
|
||||||
|
Ka 1.0000 1.0000 1.0000
|
||||||
|
Kd 0.3336 0.6286 0.0000
|
||||||
|
Ks 0.3000 0.3000 0.3000
|
||||||
|
illum 2
|
||||||
|
Ns 31.0100
|
||||||
|
map_Kd -mm -0.270 0.500 skincol1.tga
|
||||||
|
|
||||||
|
|
||||||
|
newmtl yellowbrt
|
||||||
|
Ka 0.4000 0.4000 0.4000
|
||||||
|
Kd 1.0000 0.7837 0.0000
|
||||||
|
Ks 0.3000 0.3000 0.3000
|
||||||
|
illum 2
|
||||||
|
Ns 60.0000
|
||||||
|
|
||||||
|
|
||||||
|
newmtl chappie
|
||||||
|
Ka 0.4000 0.4000 0.4000
|
||||||
|
Kd 0.5837 0.1796 0.0367
|
||||||
|
Ks 0.3000 0.3000 0.3000
|
||||||
|
illum 2
|
||||||
|
Ns 60.0000
|
||||||
|
|
||||||
|
|
||||||
|
newmtl mess
|
||||||
|
Ka 1.0000 0.2000 0.2000
|
||||||
|
Kd 0.6694 0.0000 0.0000
|
||||||
|
Ks 0.0000 0.1592 0.1878
|
||||||
|
illum 2
|
||||||
|
Ns 60.0000
|
||||||
|
map_Ks marble5.txc
|
||||||
|
map_Ns -mm 1.680 1.000 tile.cxs
|
||||||
|
|
||||||
|
|
||||||
|
newmtl steg
|
||||||
|
Ka 1.0000 1.0000 1.0000
|
||||||
|
Kd 1.0000 1.0000 1.0000
|
||||||
|
Ks 0.3000 0.3000 0.3000
|
||||||
|
illum 2
|
||||||
|
Ns 60.0000
|
||||||
|
map_Ka steg.sgi
|
||||||
|
map_Kd steg.sgi
|
||||||
|
|
||||||
|
|
||||||
|
newmtl deleteme
|
||||||
|
Ka 0.1061 0.1061 0.1061
|
||||||
|
Kd 1.0000 1.0000 1.0000
|
||||||
|
Ks 0.0898 0.0898 0.0826
|
||||||
|
illum 2
|
||||||
|
Ns 30.0000
|
||||||
|
map_Ka helena1.tga
|
||||||
|
map_Kd helena1.tga
|
||||||
|
|
||||||
|
|
||||||
|
newmtl fox
|
||||||
|
Kd 0.9429 0.8731 0.7736
|
||||||
|
illum 0
|
||||||
|
map_Kd fox.tga
|
||||||
|
|
||||||
|
|
||||||
|
newmtl dkgreen_bm
|
||||||
|
Ka 0.0000 0.0122 0.0000
|
||||||
|
Kd 0.0058 0.0245 0.0000
|
||||||
|
Ks 0.0000 0.0490 0.0000
|
||||||
|
illum 2
|
||||||
|
Ns 60.0000
|
||||||
|
bump lime.tex
|
||||||
|
|
||||||
|
|
||||||
|
newmtl archwhite
|
||||||
|
Ka 0.2816 0.2816 0.2816
|
||||||
|
Kd 0.9959 0.9959 0.9959
|
||||||
|
illum 1
|
||||||
|
|
||||||
|
|
||||||
|
newmtl archwhite2
|
||||||
|
Ka 0.2816 0.2816 0.2816
|
||||||
|
Kd 0.8408 0.8408 0.8408
|
||||||
|
illum 1
|
||||||
|
|
||||||
|
|
||||||
|
newmtl lighttan
|
||||||
|
Ka 0.0980 0.0536 0.0220
|
||||||
|
Kd 0.7020 0.4210 0.2206
|
||||||
|
Ks 0.8286 0.8057 0.5851
|
||||||
|
illum 2
|
||||||
|
Ns 177.5200
|
||||||
|
|
||||||
|
|
||||||
|
newmtl lighttan2
|
||||||
|
Ka 0.0980 0.0492 0.0144
|
||||||
|
Kd 0.3143 0.1870 0.0962
|
||||||
|
Ks 0.8286 0.8057 0.5851
|
||||||
|
illum 2
|
||||||
|
Ns 177.5200
|
||||||
|
|
||||||
|
|
||||||
|
newmtl lighttan3
|
||||||
|
Ka 0.0980 0.0492 0.0144
|
||||||
|
Kd 0.1796 0.0829 0.0139
|
||||||
|
Ks 0.8286 0.8057 0.5851
|
||||||
|
illum 2
|
||||||
|
Ns 177.5200
|
||||||
|
|
||||||
|
|
||||||
|
newmtl lightyellow
|
||||||
|
Ka 0.0980 0.0492 0.0144
|
||||||
|
Kd 0.6122 0.4552 0.2074
|
||||||
|
Ks 0.8286 0.8057 0.5851
|
||||||
|
illum 2
|
||||||
|
Ns 177.5200
|
||||||
|
|
||||||
|
|
||||||
|
newmtl lighttannew
|
||||||
|
Ka 0.0980 0.0492 0.0144
|
||||||
|
Kd 0.7878 0.6070 0.3216
|
||||||
|
Ks 0.8286 0.8057 0.5851
|
||||||
|
illum 2
|
||||||
|
Ns 177.5200
|
||||||
|
|
||||||
|
|
||||||
|
newmtl buctx
|
||||||
|
Kd 0.8653 0.8653 0.8653
|
||||||
|
illum 0
|
||||||
|
map_Kd buctx.tga
|
||||||
|
|
||||||
|
|
||||||
|
newmtl default
|
||||||
|
Ka 0.4000 0.4000 0.4000
|
||||||
|
Kd 0.7102 0.7020 0.6531
|
||||||
|
Ks 0.3000 0.3000 0.3000
|
||||||
|
illum 2
|
||||||
|
Ns 60.0000
|
||||||
|
|
||||||
|
|
||||||
|
newmtl ship
|
||||||
|
Ka 0.0000 0.0000 0.0000
|
||||||
|
Kd 1.0000 1.0000 1.0000
|
||||||
|
Ks 0.1143 0.1143 0.1143
|
||||||
|
illum 2
|
||||||
|
Ns 60.0000
|
||||||
|
map_Kd eshtex1.tif
|
||||||
|
|
||||||
|
|
||||||
|
newmtl ship2
|
||||||
|
Ka 0.0000 0.0000 0.0000
|
||||||
|
Kd 1.0000 1.0000 1.0000
|
||||||
|
Ks 0.1143 0.1143 0.1143
|
||||||
|
illum 2
|
||||||
|
Ns 60.0000
|
||||||
|
|
||||||
|
|
||||||
|
newmtl nwing.tex
|
||||||
|
Ka 0.0013 0.0204 0.0015
|
||||||
|
Kd 1.0000 1.0000 1.0000
|
||||||
|
Ks 0.1347 0.1347 0.1347
|
||||||
|
illum 2
|
||||||
|
Ns 119.3800
|
||||||
|
map_Kd /usr/projects/emil/ship/ewitex.tif
|
||||||
|
|
||||||
|
|
||||||
|
newmtl dkpurple
|
||||||
|
Ka 0.0082 0.0000 0.0163
|
||||||
|
Kd 0.0245 0.0000 0.0490
|
||||||
|
Ks 0.1266 0.0000 0.2531
|
||||||
|
illum 2
|
||||||
|
Ns 65.8900
|
||||||
|
|
||||||
|
|
||||||
|
newmtl dkorange
|
||||||
|
Ka 0.4041 0.0123 0.0000
|
||||||
|
Kd 0.7143 0.0217 0.0000
|
||||||
|
Ks 0.4857 0.0175 0.0000
|
||||||
|
illum 2
|
||||||
|
Ns 65.8900
|
||||||
|
|
||||||
|
|
||||||
|
newmtl mintgrn
|
||||||
|
Ka 0.0101 0.1959 0.0335
|
||||||
|
Kd 0.0245 0.4776 0.0816
|
||||||
|
Ks 0.0245 0.4776 0.0816
|
||||||
|
illum 2
|
||||||
|
Ns 65.8900
|
||||||
|
|
||||||
|
|
||||||
|
newmtl fgreen
|
||||||
|
Ka 0.0000 0.0449 0.0000
|
||||||
|
Kd 0.0000 0.0449 0.0004
|
||||||
|
Ks 0.0062 0.0694 0.0000
|
||||||
|
illum 2
|
||||||
|
Ns 106.2000
|
||||||
|
|
||||||
|
|
||||||
|
newmtl slvr1
|
||||||
|
Ka 0.9551 0.9551 0.9551
|
||||||
|
Kd 0.6163 0.6163 0.6163
|
||||||
|
Ks 0.3000 0.3000 0.3000
|
||||||
|
illum 3
|
||||||
|
Ns 60.0000
|
||||||
|
sharpness 60.0000
|
||||||
|
|
||||||
|
|
||||||
|
newmtl slvrscuff1
|
||||||
|
Ka 0.9551 0.9551 0.9551
|
||||||
|
Kd 0.6163 0.6163 0.6163
|
||||||
|
Ks 0.3000 0.3000 0.3000
|
||||||
|
illum 3
|
||||||
|
Ns 60.0000
|
||||||
|
sharpness 60.0000
|
||||||
|
bump 512.txb
|
||||||
|
|
||||||
|
|
||||||
|
newmtl slvrscuff2
|
||||||
|
Ka 0.9551 0.9551 0.9551
|
||||||
|
Kd 0.6163 0.6163 0.6163
|
||||||
|
Ks 0.3000 0.3000 0.3000
|
||||||
|
illum 3
|
||||||
|
Ns 60.0000
|
||||||
|
sharpness 60.0000
|
||||||
|
bump bulbs.tex
|
||||||
|
|
||||||
|
|
||||||
|
newmtl slvrscuff3
|
||||||
|
Ka 0.9551 0.9551 0.9551
|
||||||
|
Kd 0.6163 0.6163 0.6163
|
||||||
|
Ks 0.3000 0.3000 0.3000
|
||||||
|
illum 3
|
||||||
|
Ns 60.0000
|
||||||
|
sharpness 60.0000
|
||||||
|
bump football.mpb
|
||||||
|
|
||||||
|
|
||||||
|
newmtl glassblutint
|
||||||
|
Ka 0.4000 0.4000 0.4000
|
||||||
|
Kd 0.5551 0.8000 0.7730
|
||||||
|
Ks 0.7969 0.9714 0.9223
|
||||||
|
illum 4
|
||||||
|
d 0.3300
|
||||||
|
Ns 60.0000
|
||||||
|
sharpness 60.0000
|
||||||
|
|
||||||
|
|
||||||
|
newmtl candicel.mtl
|
||||||
|
Ka 0.4000 0.4000 0.4000
|
||||||
|
Kd 0.8000 0.8000 0.8000
|
||||||
|
Ks 0.6970 0.7673 0.6577
|
||||||
|
illum 2
|
||||||
|
d 0.9300
|
||||||
|
Ns 146.5100
|
||||||
|
map_Kd -mm -0.100 1.000 candicel.tga
|
||||||
|
|
||||||
|
|
||||||
|
newmtl bflesh
|
||||||
|
Ka 0.0041 0.0041 0.0041
|
||||||
|
Kd 0.0041 0.0011 0.0000
|
||||||
|
Ks 0.0531 0.0460 0.0153
|
||||||
|
illum 2
|
||||||
|
Ns 20.1600
|
||||||
|
|
||||||
|
|
||||||
|
newmtl utah
|
||||||
|
Ka 1.0000 1.0000 1.0000
|
||||||
|
Kd 1.0000 1.0000 1.0000
|
||||||
|
Ks 0.3000 0.3000 0.3000
|
||||||
|
illum 2
|
||||||
|
Ns 60.0000
|
||||||
|
map_Kd /tmp_mnt/tools/data/sofa/bill/broker/imagewar/1atextue/ut24b.sgi
|
||||||
|
bump /tmp_mnt/tools/data/sofa/bill/broker/imagewar/1atextue/ut24b.tga
|
||||||
|
|
||||||
|
|
||||||
|
newmtl meh
|
||||||
|
Ka 0.4000 0.4000 0.4000
|
||||||
|
Kd 0.5551 0.8000 0.7730
|
||||||
|
Ks 0.7969 0.9714 0.9223
|
||||||
|
illum 4
|
||||||
|
d 0.7500
|
||||||
|
Ns 183.7200
|
||||||
|
sharpness 60.0000
|
||||||
|
|
||||||
|
|
||||||
|
newmtl navyblu
|
||||||
|
Ka 0.4000 0.4000 0.4000
|
||||||
|
Kd 0.1100 0.1000 0.6800
|
||||||
|
Ks 0.3000 0.3000 0.3000
|
||||||
|
illum 2
|
||||||
|
Ns 20.0000
|
||||||
|
|
||||||
|
|
||||||
|
newmtl testchrm
|
||||||
|
Ka 0.5101 0.5020 1.0000
|
||||||
|
Kd 0.6449 0.6826 1.0000
|
||||||
|
Ks 0.3000 0.3000 0.3000
|
||||||
|
illum 3
|
||||||
|
Ns 197.6700
|
||||||
|
sharpness 60.0000
|
||||||
|
|
||||||
|
|
||||||
|
newmtl iris
|
||||||
|
Ka 0.4000 0.4000 0.4000
|
||||||
|
Kd 0.8000 0.8000 0.8000
|
||||||
|
Ks 0.3000 0.3000 0.3000
|
||||||
|
illum 2
|
||||||
|
Ns 60.0000
|
||||||
|
|
||||||
|
|
BIN
data/models/wizard.aoi
Normal file
21
data/models/wizard.mtl
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
#Produced by Art of Illusion 2.8.1, Thu Apr 01 15:01:08 PDT 2010
|
||||||
|
newmtl hat
|
||||||
|
Kd 0.67 0.2948 0.2948
|
||||||
|
Ks 0 0 0
|
||||||
|
Ka 0.67 0.2948 0.2948
|
||||||
|
illum 1
|
||||||
|
newmtl coat
|
||||||
|
Kd 0.49834 0.3944 0.58
|
||||||
|
Ks 0 0 0
|
||||||
|
Ka 0.49834 0.3944 0.58
|
||||||
|
illum 1
|
||||||
|
newmtl skin
|
||||||
|
Kd 0.87 0.79309 0.7221
|
||||||
|
Ks 0 0 0
|
||||||
|
Ka 0.87 0.79309 0.7221
|
||||||
|
illum 1
|
||||||
|
newmtl staff
|
||||||
|
Kd 0.49 0.31438 0.2156
|
||||||
|
Ks 0 0 0
|
||||||
|
Ka 0.49 0.31438 0.2156
|
||||||
|
illum 1
|
21
data/models/wizard.mtl.mtl
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
#Produced by Art of Illusion 2.8.1, Thu Apr 01 15:00:48 PDT 2010
|
||||||
|
newmtl hat
|
||||||
|
Kd 0.67 0.2948 0.2948
|
||||||
|
Ks 0 0 0
|
||||||
|
Ka 0.67 0.2948 0.2948
|
||||||
|
illum 1
|
||||||
|
newmtl coat
|
||||||
|
Kd 0.49834 0.3944 0.58
|
||||||
|
Ks 0 0 0
|
||||||
|
Ka 0.49834 0.3944 0.58
|
||||||
|
illum 1
|
||||||
|
newmtl skin
|
||||||
|
Kd 0.87 0.79309 0.7221
|
||||||
|
Ks 0 0 0
|
||||||
|
Ka 0.87 0.79309 0.7221
|
||||||
|
illum 1
|
||||||
|
newmtl staff
|
||||||
|
Kd 0.49 0.31438 0.2156
|
||||||
|
Ks 0 0 0
|
||||||
|
Ka 0.49 0.31438 0.2156
|
||||||
|
illum 1
|
4568
data/models/wizard.obj
Normal file
BIN
data/video/calib.avi
Normal file
2380
doc/Doxyfile.in
Normal file
BIN
doc/OCVtutorials.pdf
Normal file
26
doc/directories.doxygen
Executable file
|
@ -0,0 +1,26 @@
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dir doc
|
||||||
|
* @brief DOxygen doc
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dir data
|
||||||
|
* @brief data for unittests, image output, ...
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dir tools
|
||||||
|
* @brief scons compilation tools
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dir library
|
||||||
|
* @brief libraries for the MOOV3D project
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dir moov3d
|
||||||
|
* @brief Base directory of the project. All includes begins here.
|
||||||
|
*/
|
||||||
|
|
144
doc/index.doxygen
Executable file
|
@ -0,0 +1,144 @@
|
||||||
|
/** @mainpage TP Interfaces Realité Augmentée
|
||||||
|
*
|
||||||
|
* @section intro Introduction
|
||||||
|
*
|
||||||
|
*The objective of these TP sessions is to build a simple augmented reality application using OpenCV for the camera tracking part and OpenGL for the rendering. The exercises that will be proposed are meant to gradually introduce you to the OpenCV libraries and build all the function that are needed for a camera tracker in an incremental way, so that you will be able to test and debug each function, before plugging all together in the camera tracker class.
|
||||||
|
The main idea is to use a chessboard as a marker and render on top of that the augmented reality. The final application should render an OpenGL teapot on top of the chessboard. We will get there step by step, first detecting the chessboard, then create some basic rendering in OpenCV, and at last plugging everything in the OpenGL pipeline.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @section org Code Organization
|
||||||
|
*
|
||||||
|
* The directory is organized as follows:
|
||||||
|
*
|
||||||
|
* - ``doc`` contains a pdf copy of this text, a pdf copy of the reduced opencv tutorials, a pdf copy of the full, original opencv tutorial, and a pdf copy of the API reference manual of opencv (ie the copy of the online documentation).
|
||||||
|
*
|
||||||
|
* - ``data`` contains some images, videos and other data that will be used through the TP.
|
||||||
|
*
|
||||||
|
* - ``src`` contains the source files that you have to modify and complete; they are organize in directories:
|
||||||
|
*
|
||||||
|
* - ``tutorials`` contains the code used in the tutorials, in case you need to try it;
|
||||||
|
* - ``tp`` contains the files that you need to modify and complete through all the sessions of the TP.
|
||||||
|
*
|
||||||
|
* - ``3dparty`` this directory contains a library that will be used at the end of the TP. You don't have to worry (or do anything...) about this directory.
|
||||||
|
*
|
||||||
|
* @section indetails In details
|
||||||
|
* - @subpage installation
|
||||||
|
* - @subpage utilisation
|
||||||
|
* - @subpage history
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @section team Team
|
||||||
|
* - Simone Gasparini
|
||||||
|
* - Sylvie Chambon
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/** @page installation Installation
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @section install_linux Installation on Linux
|
||||||
|
*
|
||||||
|
|
||||||
|
### Dependencies
|
||||||
|
|
||||||
|
The project depends on:
|
||||||
|
|
||||||
|
- OpenCV
|
||||||
|
- OpenGL
|
||||||
|
- GLM ([webpage](http://devernay.free.fr/hacks/glm/)) which provides a more complete interface to the OBJ format (i.e. it manages textures, materials etc.).
|
||||||
|
|
||||||
|
If at any stage you get an error about missing ``Xi`` and ``Xmu`` library, you need to install them. In linux you can do
|
||||||
|
|
||||||
|
sudo apt-get install libxi-dev libxmu-dev.
|
||||||
|
|
||||||
|
### Setting up and building:
|
||||||
|
|
||||||
|
OpenCV and OpenGL are normally already installed on your machine. In case you may have a look at the next section to install OpenCV on your own machine. As for GLM, it comes with the project, so it will be compiled and built the first time it is needed.
|
||||||
|
|
||||||
|
In order to setting up the project, from the root of the project do:
|
||||||
|
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake ..
|
||||||
|
|
||||||
|
Then each application can be compiled by simply doing a
|
||||||
|
|
||||||
|
make <filename_without_extension>
|
||||||
|
|
||||||
|
If you run
|
||||||
|
|
||||||
|
make help
|
||||||
|
|
||||||
|
a list of all possible targets is displayed. Finally, running
|
||||||
|
|
||||||
|
make clean
|
||||||
|
|
||||||
|
will delete all the executable and the compilation objects.
|
||||||
|
|
||||||
|
In case you want to try the code on a different machine, you need to first install the OpenCV libraries (from (here)[http://opencv.org/downloads.html]) and then do
|
||||||
|
|
||||||
|
cmake .. -DOpenCV_DIR=path/to/OpenCVConfig.cmake
|
||||||
|
|
||||||
|
in order to specify the directory where you build them. More in general, you need to provide the path to the file ``OpenCVConfig.cmake``, which you can find e.g. with
|
||||||
|
|
||||||
|
locate OpenCVConfig.cmake
|
||||||
|
|
||||||
|
from your shell.
|
||||||
|
|
||||||
|
In order to generate the documentation you need have doxygen and graphviz installed. On linux:
|
||||||
|
|
||||||
|
sudo apt-get install doxygen graphviz.
|
||||||
|
|
||||||
|
|
||||||
|
On Mac OSX with homebrew
|
||||||
|
|
||||||
|
brew install doxygen graphviz.
|
||||||
|
|
||||||
|
Then a
|
||||||
|
On Mac OSX with homebrew
|
||||||
|
|
||||||
|
make doc
|
||||||
|
|
||||||
|
will generate the documentation in the ``doc`` folder of your build.
|
||||||
|
|
||||||
|
|
||||||
|
#### Installing OpenCV
|
||||||
|
|
||||||
|
You can download the code from [here](http://opencv.org/downloads.html) or clone the [github repository](https://github.com/itseez/opencv)
|
||||||
|
Create a `build` directory where to build the library. It also advisable to set an non-system install directory, so that it will be easier to set up the environment later:
|
||||||
|
|
||||||
|
mkdir build && cd build && cmake .. -DCMAKE_INSTALL_PREFIX=`pwd`/install
|
||||||
|
make install -j n
|
||||||
|
|
||||||
|
|
||||||
|
You can even run ```ccmake ..``` to set up other options (eg. CUDA support).
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/** @page utilisation Utilisation
|
||||||
|
*
|
||||||
|
* Ech application can be compiled by simply doing a
|
||||||
|
|
||||||
|
make <filename_without_extension>
|
||||||
|
|
||||||
|
The executable will be in the ``bin`` folder of your build. If you run
|
||||||
|
|
||||||
|
make help
|
||||||
|
|
||||||
|
a list of all possible targets is displayed.
|
||||||
|
*
|
||||||
|
|
||||||
|
Remember to set the ``LD_LIBRARY_PATH`` to allow your application to access the project libraries:
|
||||||
|
|
||||||
|
export $LD_LIBRARY_PATH=/home/<yourhome>/<path/to/code>/3dparty/glm/build/lib:$LD_LIBRARY_PATH
|
||||||
|
|
||||||
|
Also you may want to add the path to OpenCV if they are not installed in the system.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/** @page history history
|
||||||
|
* - October 2013 : First Version
|
||||||
|
* - October 2014 : First Version revised
|
||||||
|
*/
|
||||||
|
|
BIN
doc/opencv2refman.pdf
Normal file
BIN
doc/opencv_tutorials.pdf
Normal file
BIN
doc/sujetTP.pdf
Normal file
BIN
src/.DS_Store
vendored
Normal file
3
src/CMakeLists.txt
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
add_subdirectory(tp)
|
||||||
|
add_subdirectory(ogl)
|
||||||
|
add_subdirectory(tutorials)
|
4
src/ogl/CMakeLists.txt
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
|
||||||
|
#include_directories( ${LIBGLM_INCLUDE_DIRS})
|
||||||
|
#add_executable( openglObj openglObj.cpp )
|
||||||
|
#target_link_libraries( openglObj ${LIBGLM_LIBRARIES} ${OPENGL_LIBRARIES} ${GLUT_LIBRARIES} $)
|
523
src/ogl/openglObj.cpp
Normal file
|
@ -0,0 +1,523 @@
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Demonstrates how to load and display an Wavefront OBJ file.
|
||||||
|
* Using triangles and normals as static object. No texture mapping.
|
||||||
|
*
|
||||||
|
* OBJ files must be triangulated!!!
|
||||||
|
* Non triangulated objects wont work!
|
||||||
|
* You can use Blender to triangulate
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
//#include <windows.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#include <OpenGL/gl.h>
|
||||||
|
// #include <OpenGL/glu.h>
|
||||||
|
#include <GLUT/glut.h>
|
||||||
|
#else
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
#include <GL/gl.h>
|
||||||
|
// #include <GL/glu.h>
|
||||||
|
#include <GL/freeglut.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <glm.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
#define KEY_ESCAPE 27
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
Window
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
char* title;
|
||||||
|
|
||||||
|
float field_of_view_angle;
|
||||||
|
float z_near;
|
||||||
|
float z_far;
|
||||||
|
} glutWindow;
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
OBJ Loading
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
class Model_OBJ
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Model_OBJ( );
|
||||||
|
float* calculateNormal( float* coord1, float* coord2, float* coord3 );
|
||||||
|
int Load( char *filename ); // Loads the model
|
||||||
|
void Draw( ); // Draws the model on the screen
|
||||||
|
void Release( ); // Release the model
|
||||||
|
|
||||||
|
float* normals; // Stores the normals
|
||||||
|
float* Faces_Triangles; // Stores the triangles
|
||||||
|
float* vertexBuffer; // Stores the points which make the object
|
||||||
|
long TotalConnectedPoints; // Stores the total number of connected verteces
|
||||||
|
long TotalConnectedTriangles; // Stores the total number of connected triangles
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define POINTS_PER_VERTEX 3
|
||||||
|
#define TOTAL_FLOATS_IN_TRIANGLE 9
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
Model_OBJ::Model_OBJ( )
|
||||||
|
{
|
||||||
|
this->TotalConnectedTriangles = 0;
|
||||||
|
this->TotalConnectedPoints = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float* Model_OBJ::calculateNormal( float *coord1, float *coord2, float *coord3 )
|
||||||
|
{
|
||||||
|
/* calculate Vector1 and Vector2 */
|
||||||
|
float va[3], vb[3], vr[3], val;
|
||||||
|
va[0] = coord1[0] - coord2[0];
|
||||||
|
va[1] = coord1[1] - coord2[1];
|
||||||
|
va[2] = coord1[2] - coord2[2];
|
||||||
|
|
||||||
|
vb[0] = coord1[0] - coord3[0];
|
||||||
|
vb[1] = coord1[1] - coord3[1];
|
||||||
|
vb[2] = coord1[2] - coord3[2];
|
||||||
|
|
||||||
|
/* cross product */
|
||||||
|
vr[0] = va[1] * vb[2] - vb[1] * va[2];
|
||||||
|
vr[1] = vb[0] * va[2] - va[0] * vb[2];
|
||||||
|
vr[2] = va[0] * vb[1] - vb[0] * va[1];
|
||||||
|
|
||||||
|
/* normalization factor */
|
||||||
|
val = sqrt( vr[0] * vr[0] + vr[1] * vr[1] + vr[2] * vr[2] );
|
||||||
|
|
||||||
|
float norm[3];
|
||||||
|
norm[0] = vr[0] / val;
|
||||||
|
norm[1] = vr[1] / val;
|
||||||
|
norm[2] = vr[2] / val;
|
||||||
|
|
||||||
|
|
||||||
|
return norm;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Model_OBJ::Load( char* filename )
|
||||||
|
{
|
||||||
|
string line;
|
||||||
|
ifstream objFile( filename );
|
||||||
|
if( objFile.is_open( ) ) // If obj file is open, continue
|
||||||
|
{
|
||||||
|
objFile.seekg( 0, ios::end ); // Go to end of the file,
|
||||||
|
long fileSize = objFile.tellg( ); // get file size
|
||||||
|
objFile.seekg( 0, ios::beg ); // we'll use this to register memory for our 3d model
|
||||||
|
|
||||||
|
vertexBuffer = ( float* ) malloc( fileSize ); // Allocate memory for the verteces
|
||||||
|
Faces_Triangles = ( float* ) malloc( fileSize * sizeof (float ) ); // Allocate memory for the triangles
|
||||||
|
normals = ( float* ) malloc( fileSize * sizeof (float ) ); // Allocate memory for the normals
|
||||||
|
|
||||||
|
int triangle_index = 0; // Set triangle index to zero
|
||||||
|
int normal_index = 0; // Set normal index to zero
|
||||||
|
|
||||||
|
while( !objFile.eof( ) ) // Start reading file data
|
||||||
|
{
|
||||||
|
getline( objFile, line ); // Get line from file
|
||||||
|
|
||||||
|
if( line.c_str( )[0] == 'v' ) // The first character is a v: on this line is a vertex stored.
|
||||||
|
{
|
||||||
|
line[0] = ' '; // Set first character to 0. This will allow us to use sscanf
|
||||||
|
|
||||||
|
sscanf( line.c_str( ), "%f %f %f ", // Read floats from the line: v X Y Z
|
||||||
|
&vertexBuffer[TotalConnectedPoints],
|
||||||
|
&vertexBuffer[TotalConnectedPoints + 1],
|
||||||
|
&vertexBuffer[TotalConnectedPoints + 2] );
|
||||||
|
TotalConnectedPoints += POINTS_PER_VERTEX; // Add 3 to the total connected points
|
||||||
|
|
||||||
|
}
|
||||||
|
else if( line.c_str( )[0] == 'f' ) // The first character is an 'f': on this line is a point stored
|
||||||
|
{
|
||||||
|
line[0] = ' '; // Set first character to 0. This will allow us to use sscanf
|
||||||
|
|
||||||
|
int vertexNumber[4] = {0, 0, 0};
|
||||||
|
if( ( line.find( "//" ) == std::string::npos ) && ( line.find( "/" ) == std::string::npos ) )
|
||||||
|
{
|
||||||
|
// cout << "reading from a b c" << endl;
|
||||||
|
sscanf( line.c_str( ), "%i%i%i", // Read integers from the line: f 1 2 3
|
||||||
|
&vertexNumber[0], // First point of our triangle. This is an
|
||||||
|
&vertexNumber[1], // pointer to our vertexBuffer list
|
||||||
|
&vertexNumber[2] ); // each point represents an X,Y,Z.
|
||||||
|
}
|
||||||
|
else if( line.find( "//" ) != std::string::npos )
|
||||||
|
{
|
||||||
|
// cout << "reading from //" << endl;
|
||||||
|
int a, b, c;
|
||||||
|
sscanf( line.c_str( ), "%i//%i %i//%i %i//%i", // Read integers from the line: f 1 2 3
|
||||||
|
&vertexNumber[0], &a, // First point of our triangle. This is an
|
||||||
|
&vertexNumber[1], &b, // pointer to our vertexBuffer list
|
||||||
|
&vertexNumber[2], &c ); // each point represents an X,Y,Z.
|
||||||
|
// cout << vertexNumber[0] << " " << a << " " << vertexNumber[1] << " " << b << " " << vertexNumber[2] << " " << c << " " << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
vertexNumber[0] -= 1; // OBJ file starts counting from 1
|
||||||
|
vertexNumber[1] -= 1; // OBJ file starts counting from 1
|
||||||
|
vertexNumber[2] -= 1; // OBJ file starts counting from 1
|
||||||
|
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Create triangles (f 1 2 3) from points: (v X Y Z) (v X Y Z) (v X Y Z).
|
||||||
|
* The vertexBuffer contains all verteces
|
||||||
|
* The triangles will be created using the verteces we read previously
|
||||||
|
*/
|
||||||
|
|
||||||
|
int tCounter = 0;
|
||||||
|
for( int i = 0; i < POINTS_PER_VERTEX; i++ )
|
||||||
|
{
|
||||||
|
Faces_Triangles[triangle_index + tCounter ] = vertexBuffer[3 * vertexNumber[i] ];
|
||||||
|
Faces_Triangles[triangle_index + tCounter + 1 ] = vertexBuffer[3 * vertexNumber[i] + 1 ];
|
||||||
|
Faces_Triangles[triangle_index + tCounter + 2 ] = vertexBuffer[3 * vertexNumber[i] + 2 ];
|
||||||
|
tCounter += POINTS_PER_VERTEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
* Calculate all normals, used for lighting
|
||||||
|
*/
|
||||||
|
float coord1[3] = {Faces_Triangles[triangle_index], Faces_Triangles[triangle_index + 1], Faces_Triangles[triangle_index + 2]};
|
||||||
|
float coord2[3] = {Faces_Triangles[triangle_index + 3], Faces_Triangles[triangle_index + 4], Faces_Triangles[triangle_index + 5]};
|
||||||
|
float coord3[3] = {Faces_Triangles[triangle_index + 6], Faces_Triangles[triangle_index + 7], Faces_Triangles[triangle_index + 8]};
|
||||||
|
float *norm = this->calculateNormal( coord1, coord2, coord3 );
|
||||||
|
|
||||||
|
tCounter = 0;
|
||||||
|
for( int i = 0; i < POINTS_PER_VERTEX; i++ )
|
||||||
|
{
|
||||||
|
normals[normal_index + tCounter ] = norm[0];
|
||||||
|
normals[normal_index + tCounter + 1] = norm[1];
|
||||||
|
normals[normal_index + tCounter + 2] = norm[2];
|
||||||
|
tCounter += POINTS_PER_VERTEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
triangle_index += TOTAL_FLOATS_IN_TRIANGLE;
|
||||||
|
normal_index += TOTAL_FLOATS_IN_TRIANGLE;
|
||||||
|
TotalConnectedTriangles += TOTAL_FLOATS_IN_TRIANGLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
cout << "TotalConnectedTriangles: " << TotalConnectedTriangles << endl;
|
||||||
|
objFile.close( ); // Close OBJ file
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cout << "Unable to open file";
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Model_OBJ::Release( )
|
||||||
|
{
|
||||||
|
free( this->Faces_Triangles );
|
||||||
|
free( this->normals );
|
||||||
|
free( this->vertexBuffer );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Model_OBJ::Draw( )
|
||||||
|
{
|
||||||
|
glEnableClientState( GL_VERTEX_ARRAY ); // Enable vertex arrays
|
||||||
|
glEnableClientState( GL_NORMAL_ARRAY ); // Enable normal arrays
|
||||||
|
glVertexPointer( 3, GL_FLOAT, 0, Faces_Triangles ); // Vertex Pointer to triangle array
|
||||||
|
glNormalPointer( GL_FLOAT, 0, normals ); // Normal pointer to normal array
|
||||||
|
glDrawArrays( GL_TRIANGLES, 0, TotalConnectedTriangles ); // Draw the triangles
|
||||||
|
glDisableClientState( GL_VERTEX_ARRAY ); // Disable vertex arrays
|
||||||
|
glDisableClientState( GL_NORMAL_ARRAY ); // Disable normal arrays
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* Program code
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
Model_OBJ obj;
|
||||||
|
GLMmodel *pmodel = NULL; /* the loaded model */
|
||||||
|
GLfloat modelDim[3];
|
||||||
|
float g_rotation;
|
||||||
|
glutWindow win;
|
||||||
|
|
||||||
|
GLuint mode = 0;
|
||||||
|
int wireframe = 0; /* Draw modes */
|
||||||
|
int show_axis = 1;
|
||||||
|
int smooth = 1;
|
||||||
|
int material = 1;
|
||||||
|
int textured = 0;
|
||||||
|
int two_sided = 1;
|
||||||
|
int lighting = 1;
|
||||||
|
|
||||||
|
void DrawModel( void )
|
||||||
|
{
|
||||||
|
|
||||||
|
mode = GLM_NONE; /* reset mode */
|
||||||
|
|
||||||
|
if( smooth )
|
||||||
|
mode = mode | GLM_SMOOTH;
|
||||||
|
else
|
||||||
|
mode = mode | GLM_FLAT;
|
||||||
|
|
||||||
|
if( two_sided )
|
||||||
|
mode = mode | GLM_2_SIDED;
|
||||||
|
|
||||||
|
if( material )
|
||||||
|
mode = mode | GLM_MATERIAL;
|
||||||
|
else
|
||||||
|
mode = mode | GLM_COLOR;
|
||||||
|
|
||||||
|
if( textured && material )
|
||||||
|
mode = mode | GLM_TEXTURE;
|
||||||
|
|
||||||
|
glPushMatrix( );
|
||||||
|
if( pmodel )
|
||||||
|
glmDraw( pmodel, mode );
|
||||||
|
glPopMatrix( );
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawAxis( float scale )
|
||||||
|
{
|
||||||
|
glPushMatrix( );
|
||||||
|
glDisable( GL_LIGHTING );
|
||||||
|
glDisable( GL_TEXTURE_2D );
|
||||||
|
glScalef( scale, scale, scale );
|
||||||
|
|
||||||
|
glBegin( GL_LINES );
|
||||||
|
|
||||||
|
glColor3f( 1.0, 0.0, 0.0 );
|
||||||
|
glVertex3f( .8f, 0.05f, 0.0 );
|
||||||
|
glVertex3f( 1.0, 0.25f, 0.0 ); /* Letter X */
|
||||||
|
glVertex3f( 0.8f, .25f, 0.0 );
|
||||||
|
glVertex3f( 1.0, 0.05f, 0.0 );
|
||||||
|
glVertex3f( 0.0, 0.0, 0.0 );
|
||||||
|
glVertex3f( 1.0, 0.0, 0.0 ); /* X axis */
|
||||||
|
|
||||||
|
glColor3f( 0.0, 1.0, 0.0 );
|
||||||
|
glVertex3f( 0.0, 0.0, 0.0 );
|
||||||
|
glVertex3f( 0.0, 1.0, 0.0 ); /* Y axis */
|
||||||
|
|
||||||
|
glColor3f( 0.0, 0.0, 1.0 );
|
||||||
|
glVertex3f( 0.0, 0.0, 0.0 );
|
||||||
|
glVertex3f( 0.0, 0.0, 1.0 ); /* Z axis */
|
||||||
|
glEnd( );
|
||||||
|
if( lighting )
|
||||||
|
glEnable( GL_LIGHTING );
|
||||||
|
if( lighting )
|
||||||
|
glEnable( GL_TEXTURE_2D );
|
||||||
|
glColor3f( 1.0, 1.0, 1.0 );
|
||||||
|
glPopMatrix( );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void draw_axis( float scale )
|
||||||
|
{
|
||||||
|
glPushMatrix( );
|
||||||
|
glDisable( GL_LIGHTING );
|
||||||
|
|
||||||
|
glScalef( scale, scale, scale );
|
||||||
|
|
||||||
|
glBegin( GL_LINES );
|
||||||
|
|
||||||
|
glColor3f( 1.0, 0.0, 0.0 );
|
||||||
|
glVertex3f( .8f, 0.05f, 0.0 );
|
||||||
|
glVertex3f( 1.0, 0.25f, 0.0 ); // Letter X
|
||||||
|
glVertex3f( 0.8f, .25f, 0.0 );
|
||||||
|
glVertex3f( 1.0, 0.05f, 0.0 );
|
||||||
|
glVertex3f( 0.0, 0.0, 0.0 );
|
||||||
|
glVertex3f( 1.0, 0.0, 0.0 ); // X axis
|
||||||
|
|
||||||
|
glColor3f( 0.0, 1.0, 0.0 );
|
||||||
|
glVertex3f( 0.0, 0.0, 0.0 );
|
||||||
|
glVertex3f( 0.0, 1.0, 0.0 ); // Y axis
|
||||||
|
|
||||||
|
glColor3f( 0.0, 0.0, 1.0 );
|
||||||
|
glVertex3f( 0.0, 0.0, 0.0 );
|
||||||
|
glVertex3f( 0.0, 0.0, 1.0 ); // Z axis
|
||||||
|
glEnd( );
|
||||||
|
glEnable( GL_LIGHTING );
|
||||||
|
glColor3f( 1.0, 1.0, 1.0 );
|
||||||
|
glPopMatrix( );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void display( )
|
||||||
|
{
|
||||||
|
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
|
||||||
|
glLoadIdentity( );
|
||||||
|
// gluLookAt( 0, 1, 4, 0, 0, 0, 0, 1, 0 );
|
||||||
|
glPushMatrix( );
|
||||||
|
GLfloat gLightPos[] = {100.0, 200.0, 200.0, 0.0};
|
||||||
|
glEnable( GL_LIGHTING );
|
||||||
|
glLightfv( GL_LIGHT0, GL_POSITION, gLightPos );
|
||||||
|
|
||||||
|
glTranslatef( 0, 0, -1.95 );
|
||||||
|
glRotatef( g_rotation, 0, 1, 0 );
|
||||||
|
// glRotatef( 90, 0, 1, 0 );
|
||||||
|
g_rotation += 0.1;
|
||||||
|
// draw_axis( 1.0f );
|
||||||
|
// glScalef( 0.025, 0.025, 0.025 );
|
||||||
|
|
||||||
|
|
||||||
|
if( show_axis )
|
||||||
|
DrawAxis( 1.0f );
|
||||||
|
if( wireframe ) /* if Wireframe is checked */
|
||||||
|
glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); /* draw wireframe */
|
||||||
|
else /* else */
|
||||||
|
glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); /* draw filled polygons */
|
||||||
|
|
||||||
|
// glScalef( 0.25, 0.25, 0.25);
|
||||||
|
glTranslatef( 0, 0.5 * 0.25 * modelDim[1], 0 );
|
||||||
|
DrawModel( );
|
||||||
|
|
||||||
|
// glutSolidTeapot( 15 );
|
||||||
|
// obj.Draw( );
|
||||||
|
|
||||||
|
glPopMatrix( );
|
||||||
|
glutSwapBuffers( );
|
||||||
|
}
|
||||||
|
|
||||||
|
void initialize( )
|
||||||
|
{
|
||||||
|
glMatrixMode( GL_PROJECTION );
|
||||||
|
glViewport( 0, 0, win.width, win.height );
|
||||||
|
GLfloat aspect = ( GLfloat ) win.width / win.height;
|
||||||
|
glMatrixMode( GL_PROJECTION );
|
||||||
|
glLoadIdentity( );
|
||||||
|
gluPerspective( win.field_of_view_angle, aspect, win.z_near, win.z_far );
|
||||||
|
glMatrixMode( GL_MODELVIEW );
|
||||||
|
glShadeModel( GL_SMOOTH );
|
||||||
|
glClearColor( 0.1f, 0.1f, 0.1f, 0.5f );
|
||||||
|
glClearDepth( 1.0f );
|
||||||
|
glEnable( GL_DEPTH_TEST );
|
||||||
|
glDepthFunc( GL_LEQUAL );
|
||||||
|
glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
|
||||||
|
|
||||||
|
GLfloat amb_light[] = {0.9, 0.9, 0.9, 1.0};
|
||||||
|
GLfloat diffuse[] = {0.6, 0.6, 0.6, 1};
|
||||||
|
GLfloat specular[] = {0.7, 0.7, 0.3, 1};
|
||||||
|
GLfloat gLightPos[] = {100.0, 200.0, -200.0, 0.0};
|
||||||
|
glLightModelfv( GL_LIGHT_MODEL_AMBIENT, amb_light );
|
||||||
|
glLightfv( GL_LIGHT0, GL_DIFFUSE, diffuse );
|
||||||
|
glLightfv( GL_LIGHT0, GL_SPECULAR, specular );
|
||||||
|
glLightfv( GL_LIGHT0, GL_POSITION, gLightPos );
|
||||||
|
|
||||||
|
GLfloat mat_ambient[] = {0.7, 0.7, 0.7, 1.0};
|
||||||
|
GLfloat mat_diffuse[] = {0.8, 0.8, 0.8, 1.0};
|
||||||
|
GLfloat mat_specular[] = {1.0, 1.0, 1.0, 1.0};
|
||||||
|
GLfloat high_shininess[] = {100.0};
|
||||||
|
glMaterialfv( GL_FRONT, GL_AMBIENT, mat_ambient );
|
||||||
|
glMaterialfv( GL_FRONT, GL_DIFFUSE, mat_diffuse );
|
||||||
|
glMaterialfv( GL_FRONT, GL_SPECULAR, mat_specular );
|
||||||
|
glMaterialfv( GL_FRONT, GL_SHININESS, high_shininess );
|
||||||
|
|
||||||
|
glEnable( GL_LIGHT0 );
|
||||||
|
glEnable( GL_COLOR_MATERIAL );
|
||||||
|
glShadeModel( GL_SMOOTH );
|
||||||
|
glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE );
|
||||||
|
glDepthFunc( GL_LEQUAL );
|
||||||
|
glEnable( GL_DEPTH_TEST );
|
||||||
|
glEnable( GL_LIGHTING );
|
||||||
|
glEnable( GL_LIGHT0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
void keyboard( unsigned char key, int x, int y )
|
||||||
|
{
|
||||||
|
switch( key )
|
||||||
|
{
|
||||||
|
case 'w':
|
||||||
|
case 'W':
|
||||||
|
{
|
||||||
|
wireframe = !wireframe;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'd':
|
||||||
|
case 'D':
|
||||||
|
{
|
||||||
|
two_sided = !two_sided;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 's':
|
||||||
|
case 'S':
|
||||||
|
{
|
||||||
|
smooth = !smooth;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'm':
|
||||||
|
case 'M':
|
||||||
|
{
|
||||||
|
material = !material;
|
||||||
|
if( !material && textured )
|
||||||
|
textured = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 't':
|
||||||
|
case 'T':
|
||||||
|
{
|
||||||
|
textured = !textured;
|
||||||
|
if( !material && textured )
|
||||||
|
material = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case KEY_ESCAPE:
|
||||||
|
exit( 0 );
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main( int argc, char **argv )
|
||||||
|
{
|
||||||
|
// set window values
|
||||||
|
win.width = 640;
|
||||||
|
win.height = 480;
|
||||||
|
win.title = "OpenGL/GLUT OBJ Loader.";
|
||||||
|
win.field_of_view_angle = 45;
|
||||||
|
win.z_near = 1.0f;
|
||||||
|
win.z_far = 500.0f;
|
||||||
|
|
||||||
|
// initialize and run program
|
||||||
|
glutInit( &argc, argv ); // GLUT initialization
|
||||||
|
glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ); // Display Mode
|
||||||
|
glutInitWindowSize( win.width, win.height ); // set window size
|
||||||
|
glutCreateWindow( win.title ); // create Window
|
||||||
|
glutDisplayFunc( display ); // register Display Function
|
||||||
|
glutIdleFunc( display ); // register Idle Function
|
||||||
|
glutKeyboardFunc( keyboard ); // register Keyboard Handler
|
||||||
|
initialize( );
|
||||||
|
|
||||||
|
// load_obj(argv[1], suzanne_vertices, suzanne_normals, suzanne_elements);
|
||||||
|
obj.Load( argv[1] );
|
||||||
|
if( !pmodel )
|
||||||
|
{ /* load up the model */
|
||||||
|
pmodel = glmReadOBJ( argv[1] );
|
||||||
|
if( !pmodel )
|
||||||
|
{
|
||||||
|
printf( "\nUsage: objviewV2 <-s> <obj filename>\n" );
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
glmUnitize( pmodel );
|
||||||
|
glmDimensions( pmodel, modelDim );
|
||||||
|
cerr << "Model dimensions WxHxD: " << modelDim[0] << " x " << modelDim[1] << " x " << modelDim[2] << endl;
|
||||||
|
|
||||||
|
glmScale( pmodel, 0.25 );
|
||||||
|
|
||||||
|
glmVertexNormals( pmodel, 90.0, GL_TRUE );
|
||||||
|
}
|
||||||
|
glutMainLoop( ); // run GLUT mainloop
|
||||||
|
return 0;
|
||||||
|
}
|
45
src/tp/CMakeLists.txt
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
add_subdirectory(tracker)
|
||||||
|
|
||||||
|
# Make sure the compiler can find include files from our tracker library.
|
||||||
|
#include_directories (${TP_Interface_AR_SOURCE_DIR}/src/tp/tracker)
|
||||||
|
include_directories (./tracker)
|
||||||
|
|
||||||
|
|
||||||
|
# Make sure the linker can find the tracker library once it is built.
|
||||||
|
link_directories (${TP_Interface_AR_BINARY_DIR}/lib)
|
||||||
|
|
||||||
|
|
||||||
|
add_executable( checkerboard checkerboard.cpp )
|
||||||
|
target_link_libraries( checkerboard ${OpenCV_LIBS} tracker )
|
||||||
|
|
||||||
|
add_executable( checkerboardvideo checkerboardvideo.cpp )
|
||||||
|
target_link_libraries( checkerboardvideo ${OpenCV_LIBS} tracker )
|
||||||
|
|
||||||
|
add_executable( checkerboardvideoRectified checkerboardvideoRectified.cpp )
|
||||||
|
target_link_libraries( checkerboardvideoRectified ${OpenCV_LIBS} tracker )
|
||||||
|
|
||||||
|
add_executable( checkerboardvideoUndistort checkerboardvideoUndistort.cpp )
|
||||||
|
target_link_libraries( checkerboardvideoUndistort ${OpenCV_LIBS} )
|
||||||
|
|
||||||
|
add_executable( tracking tracking.cpp )
|
||||||
|
target_link_libraries( tracking ${OpenCV_LIBS} tracker )
|
||||||
|
|
||||||
|
add_executable( trackingKLT trackingKLT.cpp )
|
||||||
|
target_link_libraries( trackingKLT ${OpenCV_LIBS} tracker )
|
||||||
|
|
||||||
|
add_executable( calibration calibration.cpp )
|
||||||
|
target_link_libraries( calibration ${OpenCV_LIBS} )
|
||||||
|
|
||||||
|
add_executable( videoOGL videoOGL.cpp )
|
||||||
|
target_link_libraries( videoOGL ${OpenCV_LIBS} ${OPENGL_LIBRARIES} ${GLUT_LIBRARIES} tracker)
|
||||||
|
|
||||||
|
include_directories( ${LIBGLM_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
add_executable( videoOGLTeapot videoOGLTeapot.cpp )
|
||||||
|
target_link_libraries( videoOGLTeapot ${LIBGLM_LIBRARIES} ${OpenCV_LIBS} ${OPENGL_LIBRARIES} ${GLUT_LIBRARIES} tracker)
|
||||||
|
|
||||||
|
add_executable( videoOGLTracking videoOGLTracking.cpp )
|
||||||
|
target_link_libraries( videoOGLTracking ${LIBGLM_LIBRARIES} ${OpenCV_LIBS} ${OPENGL_LIBRARIES} ${GLUT_LIBRARIES} tracker)
|
||||||
|
|
||||||
|
add_executable( videoOGLOBJ videoOGLOBJ.cpp )
|
||||||
|
target_link_libraries( videoOGLOBJ ${LIBGLM_LIBRARIES} ${OpenCV_LIBS} ${OPENGL_LIBRARIES} ${GLUT_LIBRARIES} tracker)
|
71
src/tp/README.md
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
## Detecting the chessboard
|
||||||
|
|
||||||
|
In this first exercise we want to build a program that given an image as input, detect the a chessboard in the image and draw the detected chessboard corners
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./bin/checkerboard -w 8 -h 6 ../data/images/left01re.jpg
|
||||||
|
```
|
||||||
|
|
||||||
|
## Detecting the chessboard on a video
|
||||||
|
|
||||||
|
Now that we can detect a chessboard on an image, let’s move one step forward and write a program that detected the chessboard in a given video stream.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./bin/checkerboardVideo -w 9 -h 6 ../data/video/calib.avi
|
||||||
|
```
|
||||||
|
|
||||||
|
### Perspective rectification
|
||||||
|
|
||||||
|
In this exercise we will modify the previous code in order to estimate the homography in a robust way every time the chessboard is detected.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./bin/checkerboardvideoRectified -w 9 -h 6 ../data/video/calib.avi
|
||||||
|
```
|
||||||
|
|
||||||
|
## Camera calibration
|
||||||
|
|
||||||
|
In order to calibrate the camera we will rely on a program that comes with OpenCV.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./bin/calibration -w 9 -h 6 -V -n 10 -zt -o calib.xml ../data/video/calib.avi
|
||||||
|
```
|
||||||
|
|
||||||
|
### Removing the optical distortion
|
||||||
|
|
||||||
|
We want to implement a program that given a video and the relevant camera parameters as input, will remove the optical distortion and show the undistorted image.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./bin/checkerboardvideoUndistort -c calib.xml ../data/video/calib.avi
|
||||||
|
```
|
||||||
|
|
||||||
|
## The camera tracker
|
||||||
|
|
||||||
|
This first version of the camera tracker implements a tracking by detection method: each frame is processed independently to detect the chessboard and eventually compute the camera pose.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./bin/tracking -w 9 -h 6 -c calib.xml ../data/video/calib.avi
|
||||||
|
```
|
||||||
|
|
||||||
|
## The KLT version
|
||||||
|
|
||||||
|
In this exercise we will build a camera tracker that detect the chessboard and then track the corners using the Kanade-Lucas- Tomasi method (KLT).
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./bin/trackingKLT -w 9 -h 6 -c calib.xml ../data/video/calib.avi
|
||||||
|
```
|
||||||
|
|
||||||
|
## Adding the OpenGL rendering
|
||||||
|
|
||||||
|
We will use OpenGL to render the 3D object on top of the chessboard.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./bin/videoOGLTeapotTP -w 9 -h 6 -c calib.xml ../data/video/calib.avi
|
||||||
|
```
|
||||||
|
|
||||||
|
## Rendering an OBJ 3D object
|
||||||
|
|
||||||
|
The last step of this TP is to replace the usual OpenGL teapot with a generic 3D object loaded from an Wavefront OBJ file.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./bin/videoOGLTracking -w 9 -h 6 -c calib.xml -o ../data/models/superma.obj ../data/video/calib.avi
|
||||||
|
```
|
590
src/tp/calibration.cpp
Normal file
|
@ -0,0 +1,590 @@
|
||||||
|
#include "opencv2/core/core.hpp"
|
||||||
|
#include "opencv2/imgproc/imgproc.hpp"
|
||||||
|
#include "opencv2/calib3d/calib3d.hpp"
|
||||||
|
#include "opencv2/highgui/highgui.hpp"
|
||||||
|
|
||||||
|
#include <cctype>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
|
using namespace cv;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
const char * usage =
|
||||||
|
" \nexample command line for calibration from a live feed.\n"
|
||||||
|
" calibration -w 4 -h 5 -s 0.025 -o camera.yml -op -oe\n"
|
||||||
|
" \n"
|
||||||
|
" example command line for calibration from a list of stored images:\n"
|
||||||
|
" imagelist_creator image_list.xml *.png\n"
|
||||||
|
" calibration -w 4 -h 5 -s 0.025 -o camera.yml -op -oe image_list.xml\n"
|
||||||
|
" where image_list.xml is the standard OpenCV XML/YAML\n"
|
||||||
|
" use imagelist_creator to create the xml or yaml list\n"
|
||||||
|
" file consisting of the list of strings, e.g.:\n"
|
||||||
|
" \n"
|
||||||
|
"<?xml version=\"1.0\"?>\n"
|
||||||
|
"<opencv_storage>\n"
|
||||||
|
"<images>\n"
|
||||||
|
"view000.png\n"
|
||||||
|
"view001.png\n"
|
||||||
|
"<!-- view002.png -->\n"
|
||||||
|
"view003.png\n"
|
||||||
|
"view010.png\n"
|
||||||
|
"one_extra_view.jpg\n"
|
||||||
|
"</images>\n"
|
||||||
|
"</opencv_storage>\n";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const char* liveCaptureHelp =
|
||||||
|
"When the live video from camera is used as input, the following hot-keys may be used:\n"
|
||||||
|
" <ESC>, 'q' - quit the program\n"
|
||||||
|
" 'g' - start capturing images\n"
|
||||||
|
" 'u' - switch undistortion on/off\n"
|
||||||
|
" 't' - to take the shot if delay <=0\n";
|
||||||
|
|
||||||
|
static void help( )
|
||||||
|
{
|
||||||
|
printf( "This is a camera calibration sample.\n"
|
||||||
|
"Usage: calibration\n"
|
||||||
|
" -w <board_width> # the number of inner corners per one of board dimension\n"
|
||||||
|
" -h <board_height> # the number of inner corners per another board dimension\n"
|
||||||
|
" [-pt <pattern>] # the type of pattern: chessboard or circles' grid\n"
|
||||||
|
" [-n <number_of_frames>] # the number of frames to use for calibration\n"
|
||||||
|
" # (if not specified, it will be set to the number\n"
|
||||||
|
" # of board views actually available)\n"
|
||||||
|
" [-d <delay>] # a minimum delay in ms between subsequent attempts to capture a next view\n"
|
||||||
|
" # (used only for video capturing)\n"
|
||||||
|
" # if <=0, then the capture will be done manually by pressing 't'\n"
|
||||||
|
" [-s <squareSize>] # square size in some user-defined units (1 by default)\n"
|
||||||
|
" [-o <out_camera_params>] # the output filename for intrinsic [and extrinsic] parameters\n"
|
||||||
|
" [-op] # write detected feature points\n"
|
||||||
|
" [-oe] # write extrinsic parameters\n"
|
||||||
|
" [-zt] # assume zero tangential distortion\n"
|
||||||
|
" [-a <aspectRatio>] # fix aspect ratio (fx/fy)\n"
|
||||||
|
" [-p] # fix the principal point at the center\n"
|
||||||
|
" [-v] # flip the captured images around the horizontal axis\n"
|
||||||
|
" [-V] # use a video file, and not an image list, uses\n"
|
||||||
|
" # [input_data] string for the video file name\n"
|
||||||
|
" [-su] # show undistorted images after calibration\n"
|
||||||
|
" [input_data] # input data, one of the following:\n"
|
||||||
|
" # - text file with a list of the images of the board\n"
|
||||||
|
" # the text file can be generated with imagelist_creator\n"
|
||||||
|
" # - name of video file with a video of the board\n"
|
||||||
|
" # if input_data not specified, a live view from the camera is used\n"
|
||||||
|
"\n" );
|
||||||
|
printf( "\n%s", usage );
|
||||||
|
printf( "\n%s", liveCaptureHelp );
|
||||||
|
}
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
DETECTION = 0, CAPTURING = 1, CALIBRATED = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Pattern
|
||||||
|
{
|
||||||
|
CHESSBOARD, CIRCLES_GRID, ASYMMETRIC_CIRCLES_GRID
|
||||||
|
};
|
||||||
|
|
||||||
|
static double computeReprojectionErrors(
|
||||||
|
const vector<vector<Point3f> >& objectPoints,
|
||||||
|
const vector<vector<Point2f> >& imagePoints,
|
||||||
|
const vector<Mat>& rvecs, const vector<Mat>& tvecs,
|
||||||
|
const Mat& cameraMatrix, const Mat& distCoeffs,
|
||||||
|
vector<float>& perViewErrors )
|
||||||
|
{
|
||||||
|
vector<Point2f> imagePoints2;
|
||||||
|
int i, totalPoints = 0;
|
||||||
|
double totalErr = 0, err;
|
||||||
|
perViewErrors.resize( objectPoints.size( ) );
|
||||||
|
|
||||||
|
for( i = 0; i < ( int ) objectPoints.size( ); i++ )
|
||||||
|
{
|
||||||
|
projectPoints( Mat( objectPoints[i] ), rvecs[i], tvecs[i],
|
||||||
|
cameraMatrix, distCoeffs, imagePoints2 );
|
||||||
|
err = norm( Mat( imagePoints[i] ), Mat( imagePoints2 ), CV_L2 );
|
||||||
|
auto n = ( int ) objectPoints[i].size( );
|
||||||
|
perViewErrors[i] = ( float ) std::sqrt( err * err / n );
|
||||||
|
totalErr += err*err;
|
||||||
|
totalPoints += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::sqrt( totalErr / totalPoints );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void calcChessboardCorners( Size boardSize, float squareSize, vector<Point3f>& corners, Pattern patternType = CHESSBOARD )
|
||||||
|
{
|
||||||
|
corners.resize( 0 );
|
||||||
|
|
||||||
|
switch( patternType )
|
||||||
|
{
|
||||||
|
case CHESSBOARD:
|
||||||
|
case CIRCLES_GRID:
|
||||||
|
for( int i = 0; i < boardSize.height; i++ )
|
||||||
|
for( int j = 0; j < boardSize.width; j++ )
|
||||||
|
corners.push_back( Point3f(j * squareSize,
|
||||||
|
i * squareSize, 0 ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ASYMMETRIC_CIRCLES_GRID:
|
||||||
|
for( int i = 0; i < boardSize.height; i++ )
|
||||||
|
for( int j = 0; j < boardSize.width; j++ )
|
||||||
|
corners.push_back( Point3f((2 * j + i % 2 ) * squareSize,
|
||||||
|
i * squareSize, 0 ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
CV_Error( CV_StsBadArg, "Unknown pattern type\n" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool runCalibration( const vector<vector<Point2f> > &imagePoints,
|
||||||
|
const Size &imageSize, const Size &boardSize, Pattern patternType,
|
||||||
|
float squareSize, float aspectRatio,
|
||||||
|
int flags, Mat& cameraMatrix, Mat& distCoeffs,
|
||||||
|
vector<Mat>& rvecs, vector<Mat>& tvecs,
|
||||||
|
vector<float>& reprojErrs,
|
||||||
|
double& totalAvgErr )
|
||||||
|
{
|
||||||
|
cameraMatrix = Mat::eye( 3, 3, CV_64F );
|
||||||
|
if( flags & CV_CALIB_FIX_ASPECT_RATIO )
|
||||||
|
cameraMatrix.at<double>( 0, 0 ) = aspectRatio;
|
||||||
|
|
||||||
|
distCoeffs = Mat::zeros( 8, 1, CV_64F );
|
||||||
|
|
||||||
|
vector<vector<Point3f> > objectPoints( 1 );
|
||||||
|
calcChessboardCorners( boardSize, squareSize, objectPoints[0], patternType );
|
||||||
|
|
||||||
|
objectPoints.resize( imagePoints.size( ), objectPoints[0] );
|
||||||
|
|
||||||
|
double rms = calibrateCamera( objectPoints, imagePoints, imageSize, cameraMatrix,
|
||||||
|
distCoeffs, rvecs, tvecs, flags | CV_CALIB_FIX_K4 | CV_CALIB_FIX_K5 );
|
||||||
|
///*|CV_CALIB_FIX_K3*/|CV_CALIB_FIX_K4|CV_CALIB_FIX_K5);
|
||||||
|
printf( "RMS error reported by calibrateCamera: %g\n", rms );
|
||||||
|
|
||||||
|
bool ok = checkRange( cameraMatrix ) && checkRange( distCoeffs );
|
||||||
|
|
||||||
|
totalAvgErr = computeReprojectionErrors( objectPoints, imagePoints,
|
||||||
|
rvecs, tvecs, cameraMatrix, distCoeffs, reprojErrs );
|
||||||
|
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void saveCameraParams( const string& filename,
|
||||||
|
Size imageSize, Size boardSize,
|
||||||
|
float squareSize, float aspectRatio, int flags,
|
||||||
|
const Mat& cameraMatrix, const Mat& distCoeffs,
|
||||||
|
const vector<Mat>& rvecs, const vector<Mat>& tvecs,
|
||||||
|
const vector<float>& reprojErrs,
|
||||||
|
const vector<vector<Point2f> >& imagePoints,
|
||||||
|
double totalAvgErr )
|
||||||
|
{
|
||||||
|
FileStorage fs( filename, FileStorage::WRITE );
|
||||||
|
|
||||||
|
time_t tt;
|
||||||
|
time( &tt );
|
||||||
|
struct tm *t2 = localtime( &tt );
|
||||||
|
char buf[1024];
|
||||||
|
strftime( buf, sizeof (buf ) - 1, "%c", t2 );
|
||||||
|
|
||||||
|
fs << "calibration_time" << buf;
|
||||||
|
|
||||||
|
if( !rvecs.empty( ) || !reprojErrs.empty( ) )
|
||||||
|
fs << "nframes" << ( int ) std::max( rvecs.size( ), reprojErrs.size( ) );
|
||||||
|
fs << "image_width" << imageSize.width;
|
||||||
|
fs << "image_height" << imageSize.height;
|
||||||
|
fs << "board_width" << boardSize.width;
|
||||||
|
fs << "board_height" << boardSize.height;
|
||||||
|
fs << "square_size" << squareSize;
|
||||||
|
|
||||||
|
if( flags & CV_CALIB_FIX_ASPECT_RATIO )
|
||||||
|
fs << "aspectRatio" << aspectRatio;
|
||||||
|
|
||||||
|
if( flags != 0 )
|
||||||
|
{
|
||||||
|
sprintf( buf, "flags: %s%s%s%s",
|
||||||
|
flags & CV_CALIB_USE_INTRINSIC_GUESS ? "+use_intrinsic_guess" : "",
|
||||||
|
flags & CV_CALIB_FIX_ASPECT_RATIO ? "+fix_aspectRatio" : "",
|
||||||
|
flags & CV_CALIB_FIX_PRINCIPAL_POINT ? "+fix_principal_point" : "",
|
||||||
|
flags & CV_CALIB_ZERO_TANGENT_DIST ? "+zero_tangent_dist" : "" );
|
||||||
|
cvWriteComment( *fs, buf, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
fs << "flags" << flags;
|
||||||
|
|
||||||
|
fs << "camera_matrix" << cameraMatrix;
|
||||||
|
fs << "distortion_coefficients" << distCoeffs;
|
||||||
|
|
||||||
|
fs << "avg_reprojection_error" << totalAvgErr;
|
||||||
|
if( !reprojErrs.empty( ) )
|
||||||
|
fs << "per_view_reprojection_errors" << Mat( reprojErrs );
|
||||||
|
|
||||||
|
if( !rvecs.empty( ) && !tvecs.empty( ) )
|
||||||
|
{
|
||||||
|
CV_Assert( rvecs[0].type( ) == tvecs[0].type( ) );
|
||||||
|
Mat bigmat( ( int ) rvecs.size( ), 6, rvecs[0].type( ) );
|
||||||
|
for( int i = 0; i < ( int ) rvecs.size( ); i++ )
|
||||||
|
{
|
||||||
|
Mat r = bigmat( Range( i, i + 1 ), Range( 0, 3 ) );
|
||||||
|
Mat t = bigmat( Range( i, i + 1 ), Range( 3, 6 ) );
|
||||||
|
|
||||||
|
CV_Assert( rvecs[i].rows == 3 && rvecs[i].cols == 1 );
|
||||||
|
CV_Assert( tvecs[i].rows == 3 && tvecs[i].cols == 1 );
|
||||||
|
//*.t() is MatExpr (not Mat) so we can use assignment operator
|
||||||
|
r = rvecs[i].t( );
|
||||||
|
t = tvecs[i].t( );
|
||||||
|
}
|
||||||
|
cvWriteComment( *fs, "a set of 6-tuples (rotation vector + translation vector) for each view", 0 );
|
||||||
|
fs << "extrinsic_parameters" << bigmat;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !imagePoints.empty( ) )
|
||||||
|
{
|
||||||
|
Mat imagePtMat( ( int ) imagePoints.size( ), ( int ) imagePoints[0].size( ), CV_32FC2 );
|
||||||
|
for( int i = 0; i < ( int ) imagePoints.size( ); i++ )
|
||||||
|
{
|
||||||
|
Mat r = imagePtMat.row( i ).reshape( 2, imagePtMat.cols );
|
||||||
|
Mat imgpti( imagePoints[i] );
|
||||||
|
imgpti.copyTo( r );
|
||||||
|
}
|
||||||
|
fs << "image_points" << imagePtMat;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool readStringList( const string& filename, vector<string>& l )
|
||||||
|
{
|
||||||
|
l.resize( 0 );
|
||||||
|
FileStorage fs( filename, FileStorage::READ );
|
||||||
|
if( !fs.isOpened( ) )
|
||||||
|
return false;
|
||||||
|
FileNode n = fs.getFirstTopLevelNode( );
|
||||||
|
if( n.type( ) != FileNode::SEQ )
|
||||||
|
return false;
|
||||||
|
FileNodeIterator it = n.begin( ), it_end = n.end( );
|
||||||
|
for(; it != it_end; ++it )
|
||||||
|
l.push_back( ( string ) * it );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool runAndSave( const string& outputFilename,
|
||||||
|
const vector<vector<Point2f> >& imagePoints,
|
||||||
|
const Size &imageSize, const Size &boardSize, Pattern patternType, float squareSize,
|
||||||
|
float aspectRatio, int flags, Mat& cameraMatrix,
|
||||||
|
Mat& distCoeffs, bool writeExtrinsics, bool writePoints )
|
||||||
|
{
|
||||||
|
vector<Mat> rvecs, tvecs;
|
||||||
|
vector<float> reprojErrs;
|
||||||
|
double totalAvgErr = 0;
|
||||||
|
|
||||||
|
bool ok = runCalibration( imagePoints, imageSize, boardSize, patternType, squareSize,
|
||||||
|
aspectRatio, flags, cameraMatrix, distCoeffs,
|
||||||
|
rvecs, tvecs, reprojErrs, totalAvgErr );
|
||||||
|
printf( "%s. avg reprojection error = %.2f\n",
|
||||||
|
ok ? "Calibration succeeded" : "Calibration failed",
|
||||||
|
totalAvgErr );
|
||||||
|
|
||||||
|
if( ok )
|
||||||
|
saveCameraParams( outputFilename, imageSize,
|
||||||
|
boardSize, squareSize, aspectRatio,
|
||||||
|
flags, cameraMatrix, distCoeffs,
|
||||||
|
writeExtrinsics ? rvecs : vector<Mat>( ),
|
||||||
|
writeExtrinsics ? tvecs : vector<Mat>( ),
|
||||||
|
writeExtrinsics ? reprojErrs : vector<float>( ),
|
||||||
|
writePoints ? imagePoints : vector<vector<Point2f> >( ),
|
||||||
|
totalAvgErr );
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main( int argc, char** argv )
|
||||||
|
{
|
||||||
|
Size boardSize, imageSize;
|
||||||
|
float squareSize = 1.f, aspectRatio = 1.f;
|
||||||
|
Mat cameraMatrix, distCoeffs;
|
||||||
|
const char* outputFilename = "out_camera_data.yml";
|
||||||
|
const char* inputFilename = nullptr;
|
||||||
|
|
||||||
|
int i, nframes = 10;
|
||||||
|
bool writeExtrinsics = false, writePoints = false;
|
||||||
|
bool undistortImage = false;
|
||||||
|
int flags = 0;
|
||||||
|
VideoCapture capture;
|
||||||
|
bool flipVertical = false;
|
||||||
|
bool showUndistorted = false;
|
||||||
|
bool videofile = false;
|
||||||
|
int delay = 1000;
|
||||||
|
clock_t prevTimestamp = 0;
|
||||||
|
int mode = DETECTION;
|
||||||
|
int cameraId = 1;
|
||||||
|
vector<vector<Point2f> > imagePoints;
|
||||||
|
vector<string> imageList;
|
||||||
|
Pattern pattern = CHESSBOARD;
|
||||||
|
|
||||||
|
if( argc < 2 )
|
||||||
|
{
|
||||||
|
help( );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for( i = 1; i < argc; i++ )
|
||||||
|
{
|
||||||
|
const char* s = argv[i];
|
||||||
|
if( strcmp( s, "-w" ) == 0 )
|
||||||
|
{
|
||||||
|
if( sscanf( argv[++i], "%u", &boardSize.width ) != 1 || boardSize.width <= 0 )
|
||||||
|
return fprintf( stderr, "Invalid board width\n" ), -1;
|
||||||
|
}
|
||||||
|
else if( strcmp( s, "-h" ) == 0 )
|
||||||
|
{
|
||||||
|
if( sscanf( argv[++i], "%u", &boardSize.height ) != 1 || boardSize.height <= 0 )
|
||||||
|
return fprintf( stderr, "Invalid board height\n" ), -1;
|
||||||
|
}
|
||||||
|
else if( strcmp( s, "-pt" ) == 0 )
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
if( !strcmp( argv[i], "circles" ) )
|
||||||
|
pattern = CIRCLES_GRID;
|
||||||
|
else if( !strcmp( argv[i], "acircles" ) )
|
||||||
|
pattern = ASYMMETRIC_CIRCLES_GRID;
|
||||||
|
else if( !strcmp( argv[i], "chessboard" ) )
|
||||||
|
pattern = CHESSBOARD;
|
||||||
|
else
|
||||||
|
return fprintf( stderr, "Invalid pattern type: must be chessboard or circles\n" ), -1;
|
||||||
|
}
|
||||||
|
else if( strcmp( s, "-s" ) == 0 )
|
||||||
|
{
|
||||||
|
if( sscanf( argv[++i], "%f", &squareSize ) != 1 || squareSize <= 0 )
|
||||||
|
return fprintf( stderr, "Invalid board square width\n" ), -1;
|
||||||
|
}
|
||||||
|
else if( strcmp( s, "-n" ) == 0 )
|
||||||
|
{
|
||||||
|
if( sscanf( argv[++i], "%u", &nframes ) != 1 || nframes <= 3 )
|
||||||
|
return printf( "Invalid number of images\n" ), -1;
|
||||||
|
}
|
||||||
|
else if( strcmp( s, "-a" ) == 0 )
|
||||||
|
{
|
||||||
|
if( sscanf( argv[++i], "%f", &aspectRatio ) != 1 || aspectRatio <= 0 )
|
||||||
|
return printf( "Invalid aspect ratio\n" ), -1;
|
||||||
|
flags |= CV_CALIB_FIX_ASPECT_RATIO;
|
||||||
|
}
|
||||||
|
else if( strcmp( s, "-d" ) == 0 )
|
||||||
|
{
|
||||||
|
if( sscanf( argv[++i], "%u", &delay ) != 1 )
|
||||||
|
return printf( "Invalid delay\n" ), -1;
|
||||||
|
}
|
||||||
|
else if( strcmp( s, "-op" ) == 0 )
|
||||||
|
{
|
||||||
|
writePoints = true;
|
||||||
|
}
|
||||||
|
else if( strcmp( s, "-oe" ) == 0 )
|
||||||
|
{
|
||||||
|
writeExtrinsics = true;
|
||||||
|
}
|
||||||
|
else if( strcmp( s, "-zt" ) == 0 )
|
||||||
|
{
|
||||||
|
flags |= CV_CALIB_ZERO_TANGENT_DIST;
|
||||||
|
}
|
||||||
|
else if( strcmp( s, "-p" ) == 0 )
|
||||||
|
{
|
||||||
|
flags |= CV_CALIB_FIX_PRINCIPAL_POINT;
|
||||||
|
}
|
||||||
|
else if( strcmp( s, "-v" ) == 0 )
|
||||||
|
{
|
||||||
|
flipVertical = true;
|
||||||
|
}
|
||||||
|
else if( strcmp( s, "-V" ) == 0 )
|
||||||
|
{
|
||||||
|
videofile = true;
|
||||||
|
}
|
||||||
|
else if( strcmp( s, "-o" ) == 0 )
|
||||||
|
{
|
||||||
|
outputFilename = argv[++i];
|
||||||
|
}
|
||||||
|
else if( strcmp( s, "-su" ) == 0 )
|
||||||
|
{
|
||||||
|
showUndistorted = true;
|
||||||
|
}
|
||||||
|
else if( s[0] != '-' )
|
||||||
|
{
|
||||||
|
if( isdigit( s[0] ) )
|
||||||
|
sscanf( s, "%d", &cameraId );
|
||||||
|
else
|
||||||
|
inputFilename = s;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return fprintf( stderr, "Unknown option %s", s ), -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( inputFilename )
|
||||||
|
{
|
||||||
|
if( !videofile && readStringList( inputFilename, imageList ) )
|
||||||
|
mode = CAPTURING;
|
||||||
|
else
|
||||||
|
capture.open( inputFilename );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
capture.open( cameraId );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !capture.isOpened( ) && imageList.empty( ) )
|
||||||
|
return fprintf( stderr, "Could not initialize video (%d) capture\n", cameraId ), -2;
|
||||||
|
|
||||||
|
if( !imageList.empty( ) )
|
||||||
|
nframes = ( int ) imageList.size( );
|
||||||
|
|
||||||
|
if( !inputFilename )
|
||||||
|
{
|
||||||
|
capture.set( CV_CAP_PROP_FRAME_WIDTH, 640 );
|
||||||
|
capture.set( CV_CAP_PROP_FRAME_HEIGHT, 480 );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( capture.isOpened( ) )
|
||||||
|
printf( "%s", liveCaptureHelp );
|
||||||
|
|
||||||
|
namedWindow( "Image View", 1 );
|
||||||
|
|
||||||
|
for( i = 0;; i++ )
|
||||||
|
{
|
||||||
|
int key = 0;
|
||||||
|
Mat view, viewGray;
|
||||||
|
bool blink = false;
|
||||||
|
|
||||||
|
if( capture.isOpened( ) )
|
||||||
|
{
|
||||||
|
Mat view0;
|
||||||
|
capture >> view0;
|
||||||
|
view0.copyTo( view );
|
||||||
|
}
|
||||||
|
else if( i < ( int ) imageList.size( ) )
|
||||||
|
view = imread( imageList[i], 1 );
|
||||||
|
|
||||||
|
if( !view.data )
|
||||||
|
{
|
||||||
|
if(!imagePoints.empty())
|
||||||
|
runAndSave( outputFilename, imagePoints, imageSize,
|
||||||
|
boardSize, pattern, squareSize, aspectRatio,
|
||||||
|
flags, cameraMatrix, distCoeffs,
|
||||||
|
writeExtrinsics, writePoints );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
imageSize = view.size( );
|
||||||
|
|
||||||
|
if( flipVertical )
|
||||||
|
flip( view, view, 0 );
|
||||||
|
|
||||||
|
vector<Point2f> pointbuf;
|
||||||
|
cvtColor( view, viewGray, CV_BGR2GRAY );
|
||||||
|
|
||||||
|
bool found;
|
||||||
|
switch( pattern )
|
||||||
|
{
|
||||||
|
case CHESSBOARD:
|
||||||
|
found = findChessboardCorners( view, boardSize, pointbuf,
|
||||||
|
CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_FAST_CHECK | CV_CALIB_CB_NORMALIZE_IMAGE );
|
||||||
|
break;
|
||||||
|
case CIRCLES_GRID:
|
||||||
|
found = findCirclesGrid( view, boardSize, pointbuf );
|
||||||
|
break;
|
||||||
|
case ASYMMETRIC_CIRCLES_GRID:
|
||||||
|
found = findCirclesGrid( view, boardSize, pointbuf, CALIB_CB_ASYMMETRIC_GRID );
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return fprintf( stderr, "Unknown pattern type\n" ), -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// improve the found corners' coordinate accuracy
|
||||||
|
if( pattern == CHESSBOARD && found ) cornerSubPix( viewGray, pointbuf, Size( 11, 11 ),
|
||||||
|
Size( -1, -1 ), TermCriteria( CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 30, 0.1 ) );
|
||||||
|
|
||||||
|
if( mode == CAPTURING && found &&
|
||||||
|
( !capture.isOpened( ) || ( ( ( delay <= 0 ) && ( key == 't' ) ) || ( ( delay > 0 ) && ( clock( ) - prevTimestamp > delay * 1e-3 * CLOCKS_PER_SEC ) ) ) ) )
|
||||||
|
{
|
||||||
|
imagePoints.push_back( pointbuf );
|
||||||
|
prevTimestamp = clock( );
|
||||||
|
blink = capture.isOpened( );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( found )
|
||||||
|
drawChessboardCorners( view, boardSize, Mat( pointbuf ), found );
|
||||||
|
|
||||||
|
string msg = mode == CAPTURING ? "100/100" :
|
||||||
|
mode == CALIBRATED ? "Calibrated" : "Press 'g' to start";
|
||||||
|
int baseLine = 0;
|
||||||
|
Size textSize = getTextSize( msg, 1, 1, 1, &baseLine );
|
||||||
|
Point textOrigin( view.cols - 2 * textSize.width - 10, view.rows - 2 * baseLine - 10 );
|
||||||
|
|
||||||
|
if( mode == CAPTURING )
|
||||||
|
{
|
||||||
|
if( undistortImage )
|
||||||
|
msg = format( "Press 't' to grab image %d/%d Undist", ( int ) imagePoints.size( ), nframes );
|
||||||
|
else
|
||||||
|
msg = format( "Press 't' to grab image %d/%d", ( int ) imagePoints.size( ), nframes );
|
||||||
|
}
|
||||||
|
|
||||||
|
putText( view, msg, textOrigin, 1, 1,
|
||||||
|
mode != CALIBRATED ? Scalar( 0, 0, 255 ) : Scalar( 0, 255, 0 ) );
|
||||||
|
|
||||||
|
if( blink )
|
||||||
|
bitwise_not( view, view );
|
||||||
|
|
||||||
|
if( mode == CALIBRATED && undistortImage )
|
||||||
|
{
|
||||||
|
Mat temp = view.clone( );
|
||||||
|
undistort( temp, view, cameraMatrix, distCoeffs );
|
||||||
|
}
|
||||||
|
|
||||||
|
imshow( "Image View", view );
|
||||||
|
key = 0xff & waitKey( capture.isOpened( ) ? 50 : 500 );
|
||||||
|
|
||||||
|
if( ( key & 255 ) == 27 )
|
||||||
|
break;
|
||||||
|
|
||||||
|
if( key == 'u' && mode == CALIBRATED )
|
||||||
|
undistortImage = !undistortImage;
|
||||||
|
|
||||||
|
if( capture.isOpened( ) && key == 'g' )
|
||||||
|
{
|
||||||
|
mode = CAPTURING;
|
||||||
|
imagePoints.clear( );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( mode == CAPTURING && imagePoints.size( ) >= ( unsigned ) nframes )
|
||||||
|
{
|
||||||
|
if( runAndSave( outputFilename, imagePoints, imageSize,
|
||||||
|
boardSize, pattern, squareSize, aspectRatio,
|
||||||
|
flags, cameraMatrix, distCoeffs,
|
||||||
|
writeExtrinsics, writePoints ) )
|
||||||
|
mode = CALIBRATED;
|
||||||
|
else
|
||||||
|
mode = DETECTION;
|
||||||
|
if( !capture.isOpened( ) )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !capture.isOpened( ) && showUndistorted )
|
||||||
|
{
|
||||||
|
Mat view, rview, map1, map2;
|
||||||
|
initUndistortRectifyMap( cameraMatrix, distCoeffs, Mat( ),
|
||||||
|
getOptimalNewCameraMatrix( cameraMatrix, distCoeffs, imageSize, 1, imageSize, nullptr),
|
||||||
|
imageSize, CV_16SC2, map1, map2 );
|
||||||
|
|
||||||
|
for( i = 0; i < ( int ) imageList.size( ); i++ )
|
||||||
|
{
|
||||||
|
view = imread( imageList[i], 1 );
|
||||||
|
if( !view.data )
|
||||||
|
continue;
|
||||||
|
//undistort( view, rview, cameraMatrix, distCoeffs, cameraMatrix );
|
||||||
|
remap( view, rview, map1, map2, INTER_LINEAR );
|
||||||
|
imshow( "Image View", rview );
|
||||||
|
int c = 0xff & waitKey( );
|
||||||
|
if( ( c & 255 ) == 27 || c == 'q' || c == 'Q' )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
190
src/tp/checkerboard.cpp
Normal file
|
@ -0,0 +1,190 @@
|
||||||
|
#include "tracker/utility.hpp"
|
||||||
|
|
||||||
|
#include <opencv2/core/core.hpp>
|
||||||
|
#include <opencv2/imgproc/imgproc.hpp>
|
||||||
|
#include <opencv2/calib3d/calib3d.hpp>
|
||||||
|
#include <opencv2/highgui/highgui.hpp>
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
|
using namespace cv;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
// Display the help for the programm
|
||||||
|
void help( const char* programName );
|
||||||
|
|
||||||
|
// parse the input command line arguments
|
||||||
|
bool parseArgs( int argc, char**argv, Size &boardSize, string &inputFilename, Pattern &pattern );
|
||||||
|
|
||||||
|
int main( int argc, char** argv )
|
||||||
|
{
|
||||||
|
/******************************************************************/
|
||||||
|
/* CONSTANTS to use */
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
// the name of the window
|
||||||
|
const string WINDOW_NAME = "Image View";
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
/* VARIABLES TO use */
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
Mat view; // it will contain the original image loaded from file
|
||||||
|
|
||||||
|
|
||||||
|
vector<Point2f> pointbuf; // it will contain the detected corners on the chessboard
|
||||||
|
|
||||||
|
bool found; // it will be true if a chessboard is found, false otherwise
|
||||||
|
|
||||||
|
// it will contain the size in terms of corners (width X height) of the chessboard
|
||||||
|
Size boardSize;
|
||||||
|
|
||||||
|
// it will contains the filename of the image file
|
||||||
|
string inputFilename;
|
||||||
|
|
||||||
|
// Default pattern is chessboard
|
||||||
|
Pattern pattern = CHESSBOARD;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
/* READ THE INPUT PARAMETERS - DO NOT MODIFY */
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
if( !parseArgs( argc, argv, boardSize, inputFilename, pattern ) )
|
||||||
|
{
|
||||||
|
cerr << "Aborting..." << endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
/* PART TO DEVELOP */
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// create a window to display the image --> see namedWindow
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// read the input image from file into "view" --> see imread
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
//Measure the execution time, get time before function call
|
||||||
|
auto t = ( double ) getTickCount( );
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// call the function that detects the chessboard on the image
|
||||||
|
// found = detectChessboard...
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
// get time after function call and display info
|
||||||
|
t = ( ( double ) getTickCount( ) - t ) / getTickFrequency( );
|
||||||
|
|
||||||
|
cout << ( ( !found ) ? ( "No " ) : ( "" ) ) << "chessboard detected!" << endl;
|
||||||
|
cout << "Chessboard detection took " << t * 1000 << "ms" << endl;
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// if the chessboard is found draw the cornerns on top of it
|
||||||
|
// --> see drawChessboardCorners
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// show the image inside the window --> see imshow
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
// wait for user input before ending --> see waitKey
|
||||||
|
waitKey( -1 );
|
||||||
|
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Display the help for the programm
|
||||||
|
|
||||||
|
void help( const char* programName )
|
||||||
|
{
|
||||||
|
cout << "Detect a chessboard in a given image" << endl
|
||||||
|
<< "Usage: " << programName << endl
|
||||||
|
<< " -w <board_width> # the number of inner corners per one of board dimension" << endl
|
||||||
|
<< " -h <board_height> # the number of inner corners per another board dimension" << endl
|
||||||
|
<< " [-pt <pattern=[circles|acircles|chess]>] # the type of pattern: chessboard or circles' grid" << endl
|
||||||
|
<< " <image file> " << endl
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse the input command line arguments
|
||||||
|
|
||||||
|
bool parseArgs( int argc, char**argv, Size &boardSize, string &inputFilename, Pattern &pattern )
|
||||||
|
{
|
||||||
|
// check the minimum number of arguments
|
||||||
|
if( argc < 3 )
|
||||||
|
{
|
||||||
|
help( argv[0] );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Read the input arguments
|
||||||
|
for( int i = 1; i < argc; i++ )
|
||||||
|
{
|
||||||
|
const char* s = argv[i];
|
||||||
|
if( strcmp( s, "-w" ) == 0 )
|
||||||
|
{
|
||||||
|
if( sscanf( argv[++i], "%u", &boardSize.width ) != 1 || boardSize.width <= 0 )
|
||||||
|
{
|
||||||
|
cerr << "Invalid board width" << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( strcmp( s, "-h" ) == 0 )
|
||||||
|
{
|
||||||
|
if( sscanf( argv[++i], "%u", &boardSize.height ) != 1 || boardSize.height <= 0 )
|
||||||
|
{
|
||||||
|
cerr << "Invalid board height" << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( s[0] != '-' )
|
||||||
|
{
|
||||||
|
inputFilename.assign( s );
|
||||||
|
}
|
||||||
|
else if( strcmp( s, "-pt" ) == 0 )
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
if( !strcmp( argv[i], "circles" ) )
|
||||||
|
pattern = CIRCLES_GRID;
|
||||||
|
else if( !strcmp( argv[i], "acircles" ) )
|
||||||
|
pattern = ASYMMETRIC_CIRCLES_GRID;
|
||||||
|
else if( !strcmp( argv[i], "chess" ) )
|
||||||
|
pattern = CHESSBOARD;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cerr << "Invalid pattern type: must be chessboard or circles" << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cerr << "Unknown option " << s << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
224
src/tp/checkerboardvideo.cpp
Normal file
|
@ -0,0 +1,224 @@
|
||||||
|
#include <tracker/utility.hpp>
|
||||||
|
|
||||||
|
#include <opencv2/core/core.hpp>
|
||||||
|
#include <opencv2/imgproc/imgproc.hpp>
|
||||||
|
#include <opencv2/calib3d/calib3d.hpp>
|
||||||
|
#include <opencv2/highgui/highgui.hpp>
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
|
using namespace cv;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
// Display the help for the program
|
||||||
|
void help( const char* programName );
|
||||||
|
|
||||||
|
// parse the input command line arguments
|
||||||
|
bool parseArgs( int argc, char**argv, Size &boardSize, string &inputFilename, Pattern &pattern );
|
||||||
|
|
||||||
|
int main( int argc, char** argv )
|
||||||
|
{
|
||||||
|
/******************************************************************/
|
||||||
|
/* CONSTANTS to use */
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
// the name of the window
|
||||||
|
const string WINDOW_NAME = "Image View";
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
/* VARIABLES to use */
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
vector<Point2f> pointbuf; // it will contain the detected corners on the chessboard
|
||||||
|
|
||||||
|
bool found; // it will be true if a chessboard is found, false otherwise
|
||||||
|
|
||||||
|
// it will contain the size in terms of corners (width X height) of the chessboard
|
||||||
|
Size boardSize;
|
||||||
|
|
||||||
|
// it will contains the filename of the image file
|
||||||
|
string inputFilename;
|
||||||
|
|
||||||
|
// Default pattern is chessboard
|
||||||
|
Pattern pattern = CHESSBOARD;
|
||||||
|
|
||||||
|
// Used to load the video and get the frames
|
||||||
|
VideoCapture capture;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
/* READ THE INPUT PARAMETERS - DO NOT MODIFY */
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
if( !parseArgs( argc, argv, boardSize, inputFilename, pattern ) )
|
||||||
|
{
|
||||||
|
cerr << "Aborting..." << endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
/* PART TO DEVELOP */
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// create a window to display the image --> see namedWindow
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// read the input video with capture
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// check it is really opened
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// processing loop
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
Mat view;
|
||||||
|
/******************************************************************/
|
||||||
|
// get the new frame from capture and copy it to view
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// if no more images to process exit the loop
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//Measure the execution time, get time before function call
|
||||||
|
auto t = ( double ) getTickCount( );
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// call the function that detects the chessboard on the image
|
||||||
|
// found = detectChessboard...
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
// get time after function call and display info
|
||||||
|
t = ( ( double ) getTickCount( ) - t ) / getTickFrequency( );
|
||||||
|
|
||||||
|
cout << ( ( !found ) ? ( "No " ) : ( "" ) ) << "chessboard detected!" << endl;
|
||||||
|
cout << "Chessboard detection took " << t * 1000 << "ms" << endl;
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// if the chessboard is found draw the corners on top of it
|
||||||
|
// --> see drawChessboardCorners
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// show the image inside the window --> see imshow
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
// wait 20ms for user input before processing the next frame
|
||||||
|
// Any user input will stop the execution
|
||||||
|
if( waitKey( 10 ) >= 0 )
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// release the video resource
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Display the help for the program
|
||||||
|
|
||||||
|
void help( const char* programName )
|
||||||
|
{
|
||||||
|
cout << "Detect a chessboard in a given video" << endl
|
||||||
|
<< "Usage: " << programName << endl
|
||||||
|
<< " -w <board_width> # the number of inner corners per one of board dimension" << endl
|
||||||
|
<< " -h <board_height> # the number of inner corners per another board dimension" << endl
|
||||||
|
<< " [-pt <pattern=[circles|acircles|chess]>] # the type of pattern: chessboard or circles' grid" << endl
|
||||||
|
<< " <video file> " << endl
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse the input command line arguments
|
||||||
|
|
||||||
|
bool parseArgs( int argc, char**argv, Size &boardSize, string &inputFilename, Pattern &pattern )
|
||||||
|
{
|
||||||
|
// check the minimum number of arguments
|
||||||
|
if( argc < 3 )
|
||||||
|
{
|
||||||
|
help( argv[0] );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Read the input arguments
|
||||||
|
for( int i = 1; i < argc; i++ )
|
||||||
|
{
|
||||||
|
const char* s = argv[i];
|
||||||
|
if( strcmp( s, "-w" ) == 0 )
|
||||||
|
{
|
||||||
|
if( sscanf( argv[++i], "%u", &boardSize.width ) != 1 || boardSize.width <= 0 )
|
||||||
|
{
|
||||||
|
cerr << "Invalid board width" << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( strcmp( s, "-h" ) == 0 )
|
||||||
|
{
|
||||||
|
if( sscanf( argv[++i], "%u", &boardSize.height ) != 1 || boardSize.height <= 0 )
|
||||||
|
{
|
||||||
|
cerr << "Invalid board height" << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( s[0] != '-' )
|
||||||
|
{
|
||||||
|
inputFilename.assign( s );
|
||||||
|
}
|
||||||
|
else if( strcmp( s, "-pt" ) == 0 )
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
if( !strcmp( argv[i], "circles" ) )
|
||||||
|
pattern = CIRCLES_GRID;
|
||||||
|
else if( !strcmp( argv[i], "acircles" ) )
|
||||||
|
pattern = ASYMMETRIC_CIRCLES_GRID;
|
||||||
|
else if( !strcmp( argv[i], "chess" ) )
|
||||||
|
pattern = CHESSBOARD;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cerr << "Invalid pattern type: must be chessboard or circles" << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cerr << "Unknown option " << s << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
262
src/tp/checkerboardvideoRectified.cpp
Normal file
|
@ -0,0 +1,262 @@
|
||||||
|
#include <tracker/utility.hpp>
|
||||||
|
|
||||||
|
#include <opencv2/core/core.hpp>
|
||||||
|
#include <opencv2/imgproc/imgproc.hpp>
|
||||||
|
#include <opencv2/calib3d/calib3d.hpp>
|
||||||
|
#include <opencv2/highgui/highgui.hpp>
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
|
using namespace cv;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
// Display the help for the programm
|
||||||
|
void help( const char* programName );
|
||||||
|
|
||||||
|
// parse the input command line arguments
|
||||||
|
bool parseArgs( int argc, char**argv, Size &boardSize, string &inputFilename, Pattern &pattern );
|
||||||
|
|
||||||
|
int main( int argc, char** argv )
|
||||||
|
{
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
/* CONSTANTS to use */
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
// the name of the window
|
||||||
|
const string WINDOW_NAME = "Image View";
|
||||||
|
|
||||||
|
// the name of the window
|
||||||
|
const string WINDOW_RECTIFIED = "Rectified Image";
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
/* VARIABLES to use */
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
vector<Point2f> pointbuf; // it will contain the detected corners on the chessboard
|
||||||
|
|
||||||
|
vector<Point2f> objectPoints; // it will contain the 2D "arbitrary" chosen points on the chessboard
|
||||||
|
|
||||||
|
bool found; // it will be true if a chessboard is found, false otherwise
|
||||||
|
|
||||||
|
// it will contain the size in terms of corners (width X height) of the chessboard
|
||||||
|
Size boardSize;
|
||||||
|
|
||||||
|
// it will contains the filename of the image file
|
||||||
|
string inputFilename;
|
||||||
|
|
||||||
|
// Default pattern is chessboard
|
||||||
|
Pattern pattern = CHESSBOARD;
|
||||||
|
|
||||||
|
// Used to load the video and get the frames
|
||||||
|
VideoCapture capture;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
/* READ THE INPUT PARAMETERS - DO NOT MODIFY */
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
if( !parseArgs( argc, argv, boardSize, inputFilename, pattern ) )
|
||||||
|
{
|
||||||
|
cerr << "Aborting..." << endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
/* PART TO DEVELOP */
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// create a window using WINDOW_NAME as name to display the image --> see namedWindow
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// create a second window using WINDOW_RECTIFIED as name to display the rectified image
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// read the input video with capture (same as before)
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// check it is really opened
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// create the set of 2D (arbitrary) points of the checkerboard, let's say the
|
||||||
|
// size of the squares is 25
|
||||||
|
// call to calcChessboardCorners
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
// processing loop
|
||||||
|
while( true )
|
||||||
|
{
|
||||||
|
Mat view, rectified;
|
||||||
|
/******************************************************************/
|
||||||
|
// get the new frame from capture and copy it to view
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// if no more images to process exit the loop
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// call the function that detects the chessboard on the image
|
||||||
|
/******************************************************************/
|
||||||
|
// found = detectChessboard...
|
||||||
|
|
||||||
|
|
||||||
|
cout << ( ( !found ) ? ( "No " ) : ( "" ) ) << "chessboard detected!" << endl;
|
||||||
|
|
||||||
|
// if a chessboard is found estimate the homography and rectify the image
|
||||||
|
if( found )
|
||||||
|
{
|
||||||
|
/******************************************************************/
|
||||||
|
// estimate the homography
|
||||||
|
// --> see findHomography
|
||||||
|
// http://docs.opencv.org/2.4.13.4/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html?highlight=homography#findhomography
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// use the estimated homography to rectify the image
|
||||||
|
// --> see warpPerspective
|
||||||
|
// http://docs.opencv.org/2.4.13.4/modules/imgproc/doc/geometric_transformations.html#void warpPerspective(InputArray src, OutputArray dst, InputArray M, Size dsize, int flags, int borderMode, const Scalar& borderValue)
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/******************************************************************/
|
||||||
|
// otherwise copy the original image in rectified
|
||||||
|
// Mat.copyTo()
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// if the chessboard is found draw the cornerns on top of it
|
||||||
|
// --> see drawChessboardCorners
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// show the image inside the window --> see imshow
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// show the rectified image inside the window --> see imshow
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
// wait 20ms for user input before processing the next frame
|
||||||
|
// Any user input will stop the execution
|
||||||
|
if( waitKey( 10 ) >= 0 )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// release the video resource
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Display the help for the programm
|
||||||
|
|
||||||
|
void help( const char* programName )
|
||||||
|
{
|
||||||
|
cout << "Detect a chessboard in a given video and show the rectified image according to the estimated homography" << endl
|
||||||
|
<< "Usage: " << programName << endl
|
||||||
|
<< " -w <board_width> # the number of inner corners per one of board dimension" << endl
|
||||||
|
<< " -h <board_height> # the number of inner corners per another board dimension" << endl
|
||||||
|
<< " [-pt <pattern=[circles|acircles|chess]>] # the type of pattern: chessboard or circles' grid" << endl
|
||||||
|
<< " <video file> " << endl
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse the input command line arguments
|
||||||
|
|
||||||
|
bool parseArgs( int argc, char**argv, Size &boardSize, string &inputFilename, Pattern &pattern )
|
||||||
|
{
|
||||||
|
// check the minimum number of arguments
|
||||||
|
if( argc < 3 )
|
||||||
|
{
|
||||||
|
help( argv[0] );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Read the input arguments
|
||||||
|
for( int i = 1; i < argc; i++ )
|
||||||
|
{
|
||||||
|
const char* s = argv[i];
|
||||||
|
if( strcmp( s, "-w" ) == 0 )
|
||||||
|
{
|
||||||
|
if( sscanf( argv[++i], "%u", &boardSize.width ) != 1 || boardSize.width <= 0 )
|
||||||
|
{
|
||||||
|
cerr << "Invalid board width" << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( strcmp( s, "-h" ) == 0 )
|
||||||
|
{
|
||||||
|
if( sscanf( argv[++i], "%u", &boardSize.height ) != 1 || boardSize.height <= 0 )
|
||||||
|
{
|
||||||
|
cerr << "Invalid board height" << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( s[0] != '-' )
|
||||||
|
{
|
||||||
|
inputFilename.assign( s );
|
||||||
|
}
|
||||||
|
else if( strcmp( s, "-pt" ) == 0 )
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
if( !strcmp( argv[i], "circles" ) )
|
||||||
|
pattern = CIRCLES_GRID;
|
||||||
|
else if( !strcmp( argv[i], "acircles" ) )
|
||||||
|
pattern = ASYMMETRIC_CIRCLES_GRID;
|
||||||
|
else if( !strcmp( argv[i], "chess" ) )
|
||||||
|
pattern = CHESSBOARD;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cerr << "Invalid pattern type: must be chessboard or circles" << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cerr << "Unknown option " << s << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
298
src/tp/checkerboardvideoUndistort.cpp
Normal file
|
@ -0,0 +1,298 @@
|
||||||
|
#include <opencv2/core/core.hpp>
|
||||||
|
#include <opencv2/imgproc/imgproc.hpp>
|
||||||
|
#include <opencv2/calib3d/calib3d.hpp>
|
||||||
|
#include <opencv2/highgui/highgui.hpp>
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
|
using namespace cv;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
// Display the help for the program
|
||||||
|
void help( const char* programName );
|
||||||
|
|
||||||
|
// parse the input command line arguments
|
||||||
|
bool parseArgs( int argc, char**argv, string &inputFilename, string &calibFile );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
/* FUNCTION TO DEVELOP */
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load the calibration parameters from a file
|
||||||
|
*
|
||||||
|
* @param[in] calibFilename The name of the file
|
||||||
|
* @param[out] matK the 3x3 calibration matrix
|
||||||
|
* @param[out] dist the vector containing the distortion coefficients
|
||||||
|
* @return true if the parameters have been successfully loaded
|
||||||
|
*/
|
||||||
|
bool loadCameraParameters( const string &calibFilename, Mat &matK, Mat &dist )
|
||||||
|
{
|
||||||
|
// object that will parse the file
|
||||||
|
FileStorage fs;
|
||||||
|
/******************************************************************/
|
||||||
|
// open the file to read the parameters
|
||||||
|
// --> see method open() of FileStorage
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// check if the file has been found/opened
|
||||||
|
// --> see isOpened()
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// load the camera matrix from the tag "camera_matrix" of the file
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// load the distortion coefficients from the tag "distortion_coefficients" of the file
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
cout << matK << endl;
|
||||||
|
cout << dist << endl;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main( int argc, char** argv )
|
||||||
|
{
|
||||||
|
/******************************************************************/
|
||||||
|
/* CONSTANTS to use */
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
// the name of the window
|
||||||
|
const string WINDOW_NAME = "Image View";
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
/* VARIABLES to use */
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
// it will contains the filename of the image file
|
||||||
|
string inputFilename;
|
||||||
|
|
||||||
|
// it will contains the filename of the calibration file
|
||||||
|
string calibFilename;
|
||||||
|
|
||||||
|
// Used to load the video and get the frames
|
||||||
|
VideoCapture capture;
|
||||||
|
|
||||||
|
// Matrix that will contain the camera matrix with the intrinsic parameters
|
||||||
|
Mat matK;
|
||||||
|
|
||||||
|
// Matrix that will contain the distortion coefficients of the camera
|
||||||
|
Mat dist;
|
||||||
|
|
||||||
|
// variable used to read the user input
|
||||||
|
int mode = 'o';
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
/* READ THE INPUT PARAMETERS - DO NOT MODIFY */
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
if( !parseArgs( argc, argv, inputFilename, calibFilename ) )
|
||||||
|
{
|
||||||
|
cerr << "Aborting..." << endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
/* PART TO DEVELOP */
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// create a window using WINDOW_NAME as name to display the image --> see namedWindow
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// read the input video with capture (same as before)
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// check it is really opened
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// call to loadCameraParameters. we want to read the calibration
|
||||||
|
// matrix in matK and the distortion coefficients in dist
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// processing loop
|
||||||
|
while( true )
|
||||||
|
{
|
||||||
|
Mat view;
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// get the new frame from capture and copy it to view
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
if( view.empty( ) )
|
||||||
|
break;
|
||||||
|
|
||||||
|
// this string contains the message to print on the image
|
||||||
|
string msg;
|
||||||
|
|
||||||
|
// if we want to see the difference image
|
||||||
|
if( mode == 'd' )
|
||||||
|
{
|
||||||
|
msg = "(o)riginal, (u)ndistorted";
|
||||||
|
|
||||||
|
// temporary image
|
||||||
|
Mat temp;
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// copy the original image into temp --> see Mat.clone()
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// apply the undistortion and store the new image in view
|
||||||
|
// --> see undistort
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// compute the difference between the two images and store the result in view
|
||||||
|
// see --> absdiff
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
}
|
||||||
|
// if we want to see the undistorted image
|
||||||
|
else if( mode == 'u' )
|
||||||
|
{
|
||||||
|
msg = "(o)riginal, (d)ifference";
|
||||||
|
// temporary image
|
||||||
|
Mat temp;
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// copy the original image into temp --> see Mat.clone()
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// apply the undistortion and store the new image in view
|
||||||
|
// --> see undistort
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
msg = "(d)ifference, (u)ndistorted";
|
||||||
|
}
|
||||||
|
|
||||||
|
int baseLine = 0;
|
||||||
|
Size textSize = getTextSize( msg, 1, 1, 1, &baseLine );
|
||||||
|
// cout << baseLine << endl;
|
||||||
|
// cout << textSize << endl;
|
||||||
|
Point textOrigin( view.cols / 2 - textSize.width / 2, view.rows - 2 * baseLine - 10 );
|
||||||
|
putText( view, msg, textOrigin, 1, 1, Scalar( 0, 255, 0 ) );
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// show view inside the window --> see imshow
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
// wait 20ms for user input before processing the next frame
|
||||||
|
// Any user input will stop the execution
|
||||||
|
int key = 0xff & waitKey( 70 );
|
||||||
|
|
||||||
|
if( key == 'q' )
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if( key != 255 )
|
||||||
|
{
|
||||||
|
mode = key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// release the video resource
|
||||||
|
capture.release( );
|
||||||
|
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Display the help for the program
|
||||||
|
|
||||||
|
void help( const char* programName )
|
||||||
|
{
|
||||||
|
cout << "Undistort the images from a video" << endl
|
||||||
|
<< "Usage: " << programName << endl
|
||||||
|
<< " -c <calib file> # the name of the calibration file" << endl
|
||||||
|
<< " <video file> # the name of the video file to process" << endl
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse the input command line arguments
|
||||||
|
|
||||||
|
bool parseArgs( int argc, char**argv, string &inputFilename, string &calibFile )
|
||||||
|
{
|
||||||
|
// check the minimum number of arguments
|
||||||
|
if( argc < 2 )
|
||||||
|
{
|
||||||
|
help( argv[0] );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Read the input arguments
|
||||||
|
for( int i = 1; i < argc; i++ )
|
||||||
|
{
|
||||||
|
const char* s = argv[i];
|
||||||
|
|
||||||
|
if( strcmp( s, "-c" ) == 0 )
|
||||||
|
{
|
||||||
|
if( i + 1 < argc )
|
||||||
|
calibFile.assign( argv[++i] );
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cerr << "Missing argument for option " << s << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( s[0] != '-' )
|
||||||
|
{
|
||||||
|
inputFilename.assign( s );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cerr << "Unknown option " << s << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
12
src/tp/tracker/CMakeLists.txt
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
|
||||||
|
set(trackerHeaders_hpp tracker/Camera.hpp
|
||||||
|
tracker/ChessboardCameraTrackerKLT.hpp
|
||||||
|
tracker/ChessboardCameraTracker.hpp
|
||||||
|
tracker/utility.hpp
|
||||||
|
tracker/ICameraTracker.hpp)
|
||||||
|
|
||||||
|
add_library( tracker STATIC utility.cpp ChessboardCameraTracker.cpp ChessboardCameraTrackerKLT.cpp Camera.cpp ${trackerHeaders_hpp})
|
||||||
|
target_link_libraries( tracker ${OpenCV_LIBS} )
|
||||||
|
|
||||||
|
install(TARGETS tracker LIBRARY DESTINATION lib ARCHIVE DESTINATION lib)
|
||||||
|
install(FILES ${trackerHeaders_hpp} DESTINATION include/)
|
91
src/tp/tracker/Camera.cpp
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
#include "tracker/Camera.hpp"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace cv;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the camera loading the internal parameters from the given file
|
||||||
|
*
|
||||||
|
* @param[in] calibFilename the calibration file
|
||||||
|
* @return true if success
|
||||||
|
*/
|
||||||
|
bool Camera::init( const std::string& calibFilename )
|
||||||
|
{
|
||||||
|
/******************************************************************/
|
||||||
|
// open the file storage with the given filename
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// check if the file storage has been opened correclty
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// load the camera_matrix in matK
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// load the distortion_coefficients in distCoeff
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// load image_width and image_height in imageSize.[width|height]
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// cout << matK << endl;
|
||||||
|
// cout << distCoeff << endl;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the OpenGL projection matrix for the camera
|
||||||
|
* @param[out] proj the OGL projection matrix (ready to be passed, ie in col major format)
|
||||||
|
* @param znear near clipping plane
|
||||||
|
* @param zfar far clipping plane
|
||||||
|
* \note using http://strawlab.org/2011/11/05/augmented-reality-with-OpenGL/
|
||||||
|
*/
|
||||||
|
void Camera::getOGLProjectionMatrix( float *proj, float znear, float zfar ) const
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
// With window_coords==’y down’, we have:
|
||||||
|
//
|
||||||
|
// [2*K00/width, -2*K01/width, (width - 2*K02 + 2*x0)/width, 0]
|
||||||
|
// [ 0, 2*K11/height, (-height + 2*K12 + 2*y0)/height, 0]
|
||||||
|
// [ 0, 0, (-zfar - znear)/(zfar - znear), -2*zfar*znear/(zfar - znear)]
|
||||||
|
// [ 0, 0, -1, 0]
|
||||||
|
|
||||||
|
//corrected with artoolkitpluss src/Tracker::349
|
||||||
|
|
||||||
|
proj[0] = ( float ) ( 2 * matK.at<double>( 0, 0 ) ) / imageSize.width;
|
||||||
|
proj[1 * 4 + 0] = ( float ) ( 2 * matK.at<double>( 0, 1 ) ) / imageSize.width;
|
||||||
|
proj[2 * 4 + 0] = -( float ) ( imageSize.width - 2 * matK.at<double>( 0, 2 ) ) / imageSize.width;
|
||||||
|
proj[3 * 4 + 0] = 0;
|
||||||
|
|
||||||
|
proj[0 * 4 + 1] = 0;
|
||||||
|
// minus -(float)(2*matK.at<double>(1,1))/imageSize.height;
|
||||||
|
proj[1 * 4 + 1] = -( float ) ( 2 * matK.at<double>( 1, 1 ) ) / imageSize.height;
|
||||||
|
proj[2 * 4 + 1] = -( float ) ( -imageSize.height + 2 * matK.at<double>( 1, 2 ) ) / imageSize.height;
|
||||||
|
proj[3 * 4 + 1] = 0;
|
||||||
|
|
||||||
|
proj[0 * 4 + 2] = 0;
|
||||||
|
proj[1 * 4 + 2] = 0;
|
||||||
|
proj[2 * 4 + 2] = ( zfar + znear ) / ( zfar - znear );
|
||||||
|
proj[3 * 4 + 2] = -2 * zfar * znear / ( zfar - znear );
|
||||||
|
|
||||||
|
proj[0 * 4 + 3] = 0;
|
||||||
|
proj[1 * 4 + 3] = 0;
|
||||||
|
proj[2 * 4 + 3] = 1;
|
||||||
|
proj[3 * 4 + 3] = 0;
|
||||||
|
|
||||||
|
}
|
78
src/tp/tracker/ChessboardCameraTracker.cpp
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
#include "tracker/ChessboardCameraTracker.hpp"
|
||||||
|
#include "tracker/utility.hpp"
|
||||||
|
|
||||||
|
#include <opencv2/calib3d/calib3d.hpp>
|
||||||
|
#include <opencv2/imgproc/imgproc.hpp>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace cv;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* It detects a chessboard inside an image and if found it returns the pose of the camera wrt the chessboard
|
||||||
|
*
|
||||||
|
* @param[in,out] view the original image
|
||||||
|
* @param[out] pose the pose of the camera
|
||||||
|
* @param[in] cam the camera
|
||||||
|
* @param[in] boardSize the size of the chessboard to detect
|
||||||
|
* @param[in] pattern the type of pattern to detect
|
||||||
|
* @return true if the chessboard has been found
|
||||||
|
*/
|
||||||
|
bool ChessboardCameraTracker::process( cv::Mat &view, cv::Mat &pose, const Camera & cam, const cv::Size &boardSize, const Pattern &pattern )
|
||||||
|
{
|
||||||
|
// true if the chessboard is found
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
// contains the points detected on the chessboard
|
||||||
|
vector<Point2f> corners;
|
||||||
|
|
||||||
|
//******************************************************************/
|
||||||
|
// undistort the input image. view at the end must contain the undistorted version
|
||||||
|
// of the image.
|
||||||
|
//******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************/
|
||||||
|
// detect the chessboard
|
||||||
|
//******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
// cout << ( (!found ) ? ( "No " ) : ("") ) << "chessboard detected!" << endl;
|
||||||
|
|
||||||
|
//******************************************************************/
|
||||||
|
// if a chessboard is found, estimate the homography
|
||||||
|
//******************************************************************/
|
||||||
|
if( found )
|
||||||
|
{
|
||||||
|
|
||||||
|
// contains the points on the chessboard
|
||||||
|
vector<Point2f> objectPoints;
|
||||||
|
|
||||||
|
//******************************************************************/
|
||||||
|
// create the set of 2D (arbitrary) points of the checkerboard
|
||||||
|
// call to calcChessboardCorners
|
||||||
|
//******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************/
|
||||||
|
// estimate the homography
|
||||||
|
// --> see findHomography
|
||||||
|
// http://docs.opencv.org/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html?highlight=homography#findhomography
|
||||||
|
//******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
// cout << "H = " << H << endl << endl;
|
||||||
|
// cout << "corners =" << corners << endl << endl;
|
||||||
|
// cout << "ptsOb =" << objectPoints << endl << endl;
|
||||||
|
|
||||||
|
//******************************************************************/
|
||||||
|
// decompose the homography
|
||||||
|
//******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return found;
|
||||||
|
}
|
162
src/tp/tracker/ChessboardCameraTrackerKLT.cpp
Normal file
|
@ -0,0 +1,162 @@
|
||||||
|
#include "tracker/ChessboardCameraTrackerKLT.hpp"
|
||||||
|
#include "tracker/utility.hpp"
|
||||||
|
|
||||||
|
#include <opencv2/calib3d/calib3d.hpp>
|
||||||
|
#include <opencv2/imgproc/imgproc.hpp>
|
||||||
|
#include <opencv2/video/tracking.hpp>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace cv;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* It detects a chessboard inside an image and if found it returns the pose of the camera wrt the chessboard
|
||||||
|
*
|
||||||
|
* @param[in,out] view the original image
|
||||||
|
* @param[out] pose the pose of the camera
|
||||||
|
* @param[in] cam the camera
|
||||||
|
* @param[in] boardSize the size of the chessboard to detect
|
||||||
|
* @param[in] pattern the type of pattern to detect
|
||||||
|
* @return true if the chessboard has been found
|
||||||
|
*/
|
||||||
|
bool ChessboardCameraTrackerKLT::process( cv::Mat &view, cv::Mat &pose, const Camera & cam, const cv::Size &boardSize, const Pattern &pattern )
|
||||||
|
{
|
||||||
|
// true if the chessboard is found
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
Mat temp = view.clone( ); // used for correcting the optical distortion
|
||||||
|
|
||||||
|
//******************************************************************/
|
||||||
|
// undistort the input image. view at the end must contain the undistorted version
|
||||||
|
// of the image.
|
||||||
|
//******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
// contains the grey version of the current frame
|
||||||
|
Mat viewGrey;
|
||||||
|
|
||||||
|
//******************************************************************/
|
||||||
|
// convert the current left frame into greylevel image
|
||||||
|
//******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
// if we have too few points or none
|
||||||
|
if( _corners.size( ) < 10 )
|
||||||
|
{
|
||||||
|
//******************************************************************/
|
||||||
|
// detect the chessboard
|
||||||
|
//******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
if( found )
|
||||||
|
{
|
||||||
|
//******************************************************************/
|
||||||
|
// generate the points on the chessboard, this time 3D points
|
||||||
|
// see --> calcChessboardCorners3D
|
||||||
|
//******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************/
|
||||||
|
// compute the pose of the camera using mySolvePnPRansac (utility.hpp))
|
||||||
|
//******************************************************************/
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// use klt to track the points
|
||||||
|
|
||||||
|
// some parameters for the optical flow algorithm
|
||||||
|
Size winSize( 11, 11 );
|
||||||
|
TermCriteria termcrit( CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 20, 0.03 );
|
||||||
|
|
||||||
|
// vector where the estimated tracked points of the new frame will be stored
|
||||||
|
vector<Point2f> currPts;
|
||||||
|
|
||||||
|
// auxiliary stuff for the optical flow computation
|
||||||
|
// status has will have the same length as currPts and is 0 if the
|
||||||
|
// optical flow estimation for the corresponding new point is not good
|
||||||
|
vector<uchar> status;
|
||||||
|
vector<float> err;
|
||||||
|
|
||||||
|
//******************************************************************/
|
||||||
|
// estimate the new position of the tracked points using calcOpticalFlowPyrLK
|
||||||
|
//******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************/
|
||||||
|
// Filter currPts and update the lists _corners and _objectPoints: if
|
||||||
|
// the corresponding value in status is >0 then copy the new point of
|
||||||
|
// currPts in _corner, otherwise skip the point.
|
||||||
|
//******************************************************************/
|
||||||
|
|
||||||
|
// i is used to run through all the elements of currPts
|
||||||
|
// k is used to run through _corners and _objectPoints to keep only the well tracked features
|
||||||
|
size_t i, k;
|
||||||
|
|
||||||
|
for( i = k = 0; i < currPts.size( ); i++ )
|
||||||
|
{
|
||||||
|
//******************************************************************/
|
||||||
|
// if it's a good point copy it in _corners and also copy keep the
|
||||||
|
// corresponding _objectPoints
|
||||||
|
//******************************************************************/
|
||||||
|
// if..
|
||||||
|
{
|
||||||
|
#if DEBUGGING
|
||||||
|
line( view, _corners[ i ], currPts[ i ], Scalar( 255, 0, 0 ), 1 );
|
||||||
|
circle( view, currPts[ i ], 3, Scalar( 255, 0, 255 ), -1, 8 );
|
||||||
|
#endif
|
||||||
|
//******************************************************************/
|
||||||
|
// copy the current point in _corners
|
||||||
|
//******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************/
|
||||||
|
// copy the corresponding _objectPoints
|
||||||
|
//******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************/
|
||||||
|
// update k
|
||||||
|
//******************************************************************/
|
||||||
|
++k;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// resize the two vector to the size k, the number of "well" tracked features
|
||||||
|
_corners.resize( k );
|
||||||
|
_objectPoints.resize( k );
|
||||||
|
|
||||||
|
// vector containing the inliers
|
||||||
|
vector<int> idxInl;
|
||||||
|
|
||||||
|
//******************************************************************/
|
||||||
|
// compute the pose of the camera using mySolvePnPRansac (utility.hpp))
|
||||||
|
//******************************************************************/
|
||||||
|
|
||||||
|
// _vecCorners.push_back(_corners);
|
||||||
|
//// _vecObjectPoints.push_back(_objectPoints);
|
||||||
|
// _vecIdx.push_back(_indices);
|
||||||
|
|
||||||
|
//******************************************************************/
|
||||||
|
// filter the points to remove the outliers. Use filterVector from utility.hpp
|
||||||
|
// Filter both the image points and the 3D reference points
|
||||||
|
//******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//******************************************************************/
|
||||||
|
// update _prevGrey with the current grey frame
|
||||||
|
//******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
return found;
|
||||||
|
}
|
39
src/tp/tracker/tracker/Camera.hpp
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <opencv2/core/core.hpp>
|
||||||
|
|
||||||
|
class Camera
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
Camera( ) = default;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the camera loading the internal parameters from the given file
|
||||||
|
*
|
||||||
|
* @param[in] calibFilename the calibration file
|
||||||
|
* @return true if success
|
||||||
|
*/
|
||||||
|
bool init( const std::string& calibFilename );
|
||||||
|
|
||||||
|
virtual ~Camera( ) = default;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the OpenGL projection matrix for the camera
|
||||||
|
* @param[out] proj the OGL projection matrix (ready to be passed, ie in col major format)
|
||||||
|
* @param znear near clipping plane
|
||||||
|
* @param zfar far clipping plane
|
||||||
|
* \note using http://strawlab.org/2011/11/05/augmented-reality-with-OpenGL/
|
||||||
|
*/
|
||||||
|
void getOGLProjectionMatrix( float *proj, float znear, float zfar ) const;
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
cv::Mat matK;
|
||||||
|
|
||||||
|
cv::Mat distCoeff;
|
||||||
|
|
||||||
|
cv::Size imageSize;
|
||||||
|
|
||||||
|
};
|
26
src/tp/tracker/tracker/ChessboardCameraTracker.hpp
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ICameraTracker.hpp"
|
||||||
|
|
||||||
|
class ChessboardCameraTracker : public ICameraTracker
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
ChessboardCameraTracker( ) = default;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* It detects a chessboard inside an image and if found it returns the pose of the camera wrt the chessboard
|
||||||
|
*
|
||||||
|
* @param[in,out] view the original image
|
||||||
|
* @param[out] pose the pose of the camera
|
||||||
|
* @param[in] cam the camera
|
||||||
|
* @param[in] boardSize the size of the chessboard to detect
|
||||||
|
* @param[in] pattern the type of pattern to detect
|
||||||
|
* @return true if the chessboard has been found
|
||||||
|
*/
|
||||||
|
bool process( cv::Mat &view, cv::Mat &pose, const Camera & cam, const cv::Size &boardSize, const Pattern &pattern );
|
||||||
|
|
||||||
|
virtual ~ChessboardCameraTracker( ) = default;
|
||||||
|
|
||||||
|
};
|
35
src/tp/tracker/tracker/ChessboardCameraTrackerKLT.hpp
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ICameraTracker.hpp"
|
||||||
|
|
||||||
|
class ChessboardCameraTrackerKLT : public ICameraTracker
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
ChessboardCameraTrackerKLT( ) = default;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* It detects and tracks a chessboard inside an image
|
||||||
|
*
|
||||||
|
* @param[in,out] input the original image
|
||||||
|
* @param[out] pose the pose of the camera
|
||||||
|
* @param[in] cam the camera
|
||||||
|
* @param[in] boardSize the size of the chessboard to detect
|
||||||
|
* @param[in] patt the type of pattern to detect
|
||||||
|
* @return true if the chessboard has been found
|
||||||
|
*/
|
||||||
|
bool process( cv::Mat &input, cv::Mat &pose, const Camera & cam, const cv::Size &boardSize, const Pattern &patt );
|
||||||
|
|
||||||
|
virtual ~ChessboardCameraTrackerKLT( ) = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// contains the 2D corners detected in the last frame that needs to be tracked
|
||||||
|
std::vector<cv::Point2f> _corners;
|
||||||
|
// contains the 3D points of the chessboard
|
||||||
|
std::vector<cv::Point3f> _objectPoints;
|
||||||
|
// the previous frame
|
||||||
|
cv::Mat _prevGrey{};
|
||||||
|
|
||||||
|
};
|
51
src/tp/tracker/tracker/ICameraTracker.hpp
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Camera.hpp"
|
||||||
|
#include "utility.hpp"
|
||||||
|
|
||||||
|
class ICameraTracker
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
/***************************************************
|
||||||
|
* INTERFACES
|
||||||
|
*
|
||||||
|
***************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param input
|
||||||
|
* @param pose
|
||||||
|
* @param cam
|
||||||
|
* @param boardSize
|
||||||
|
* @param patt
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
virtual bool process( cv::Mat &input, cv::Mat &pose, const Camera & cam, const cv::Size &boardSize, const Pattern &patt ) = 0;
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************
|
||||||
|
* METHODS
|
||||||
|
*
|
||||||
|
***************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the current projection matrix of the camera
|
||||||
|
* @return current projection matrix of the camera
|
||||||
|
*/
|
||||||
|
inline const cv::Mat & getCurrPose( ) const
|
||||||
|
{
|
||||||
|
return _currPose;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
4x4 rototranslation matrix for the camera position
|
||||||
|
*/
|
||||||
|
cv::Mat _currPose;
|
||||||
|
|
||||||
|
|
||||||
|
};
|
132
src/tp/tracker/tracker/utility.hpp
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Camera.hpp"
|
||||||
|
|
||||||
|
#include <opencv2/core/core.hpp>
|
||||||
|
#include <opencv2/highgui/highgui.hpp>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#define DEBUGGING 1
|
||||||
|
|
||||||
|
#if DEBUGGING
|
||||||
|
#define PRINTVAR( a ) std::cout << #a << " = " << (a) << endl << endl;
|
||||||
|
#else
|
||||||
|
#define PRINTVAR( a )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Enumerative type containing the possible patterns for the chessboard
|
||||||
|
|
||||||
|
enum Pattern
|
||||||
|
{
|
||||||
|
CHESSBOARD, CIRCLES_GRID, ASYMMETRIC_CIRCLES_GRID
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detect a chessboard in a given image
|
||||||
|
*
|
||||||
|
* @param[in] rgbimage The rgb image to process
|
||||||
|
* @param[out] pointbuf the set of 2D image corner detected on the chessboard
|
||||||
|
* @param[in] boardSize the size of the board in terms of corners (width X height)
|
||||||
|
* @param[in] patternType The type of chessboard pattern to look for
|
||||||
|
* @return true if the chessboard is detected inside the image, false otherwise
|
||||||
|
*/
|
||||||
|
bool detectChessboard( const cv::Mat &rgbimage, std::vector<cv::Point2f> &pointbuf, const cv::Size &boardSize, Pattern patternType );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decompose the homography into its components R and t
|
||||||
|
*
|
||||||
|
* @param[in] H The homography H = [h1 h2 h3]
|
||||||
|
* @param[in] matK The 3x3 calibration matrix K
|
||||||
|
* @param[out] poseMat the 3x4 pose matrix [R t]
|
||||||
|
*/
|
||||||
|
void decomposeHomography( const cv::Mat &H, const cv::Mat& matK, cv::Mat& poseMat );
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param[in,out] rgbimage The image on which to draw the reference system
|
||||||
|
* @param[in] cam The camera
|
||||||
|
* @param[in] poseMat The pose of the camera
|
||||||
|
* @param[in] thickness The thickness of the line
|
||||||
|
* @param[in] scale A scale factor for the unit vectors to draw
|
||||||
|
* @param[in] alreadyUndistorted A boolean value that tells if the input image rgbimage is already undistorted or we are working on a distorted image
|
||||||
|
*/
|
||||||
|
void drawReferenceSystem( cv::Mat &rgbimage, const Camera& cam, const cv::Mat &poseMat, const int &thickness, const double &scale, bool alreadyUndistorted = true );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper around the original opencv's projectPoints
|
||||||
|
*
|
||||||
|
* @param[in] objectPoints the 3D points
|
||||||
|
* @param[in] poseMat the pose matrix of the camera
|
||||||
|
* @param[in] cameraMatrix the calibration matrix
|
||||||
|
* @param[in] distCoeffs the distortion coefficients
|
||||||
|
* @param[out] imagePoints the projected points
|
||||||
|
*/
|
||||||
|
void myProjectPoints( cv::InputArray objectPoints, const cv::Mat &poseMat, cv::InputArray cameraMatrix, cv::InputArray distCoeffs, cv::OutputArray imagePoints );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper around the original opencv's solvePnPRansac
|
||||||
|
*
|
||||||
|
* @param[in] objectPoints the 3D points
|
||||||
|
* @param[in] imagePoints the image points
|
||||||
|
* @param[in] cameraMatrix the calibration matrix
|
||||||
|
* @param[in] distCoeffs the distortion coefficients
|
||||||
|
* @param[out] poseMat the pose matrix
|
||||||
|
* @param[out] inliers the list of indices of the inliers points
|
||||||
|
*/
|
||||||
|
void mySolvePnPRansac( cv::InputArray objectPoints, cv::InputArray imagePoints, cv::InputArray cameraMatrix, cv::InputArray distCoeffs, cv::Mat &poseMat, cv::OutputArray inliers = cv::noArray( ) );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate the set of 3D points of a chessboard
|
||||||
|
*
|
||||||
|
* @param[in] boardSize the size of the board in terms of corners (width X height)
|
||||||
|
* @param[in] squareSize the size in mm of the each square of the chessboard
|
||||||
|
* @param[out] corners the set of 2D points on the chessboard
|
||||||
|
* @param[in] patternType The type of chessboard pattern to look for
|
||||||
|
*/
|
||||||
|
void calcChessboardCorners( const cv::Size &boardSize, const float &squareSize, std::vector<cv::Point2f>& corners, Pattern patternType = CHESSBOARD );
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate the set of 3D points of a chessboard
|
||||||
|
*
|
||||||
|
* @param[in] boardSize the size of the board in terms of corners (width X height)
|
||||||
|
* @param[in] squareSize the size in mm of the each square of the chessboard
|
||||||
|
* @param[out] corners the set of 3D points on the chessboard
|
||||||
|
* @param[in] patternType The type of chessboard pattern to look for
|
||||||
|
*/
|
||||||
|
void calcChessboardCorners3D( const cv::Size &boardSize, const float &squareSize, std::vector<cv::Point3f>& corners, Pattern patternType = CHESSBOARD );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter a generic vector against a list of index of the elements to be deleted,
|
||||||
|
*
|
||||||
|
* @param[in,out] inout the vector to filter
|
||||||
|
* @param[in] idx list of indices of the element to keep
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
void filterVector( std::vector<T> &inout, const std::vector<int> &idx )
|
||||||
|
{
|
||||||
|
std::vector<T> temp;
|
||||||
|
temp.reserve( idx.size( ) );
|
||||||
|
|
||||||
|
for( size_t i = 0; i < idx.size( ); ++i )
|
||||||
|
{
|
||||||
|
assert( idx[i] < inout.size( ) );
|
||||||
|
temp.push_back( inout[ idx[i] ] );
|
||||||
|
}
|
||||||
|
|
||||||
|
inout.clear( ); //necessary??
|
||||||
|
inout = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Utility function used to detect the size and the type of a video stream.
|
||||||
|
* The video must be already open.
|
||||||
|
*
|
||||||
|
* @param[in] videoFilename The name of the video file
|
||||||
|
* @paramp[in,out] capture The video stream, it must be already open
|
||||||
|
* @param[out] singleSize The size of the frames (width x height) of the video
|
||||||
|
* @param[out] imgInType The type of the frame (uchar, int etc)
|
||||||
|
* @return true if everything went ok
|
||||||
|
*/
|
||||||
|
bool getVideoSizeAndType(const std::string &videoFilename, cv::VideoCapture capture, cv::Size &singleSize, int &imgInType);
|
411
src/tp/tracker/utility.cpp
Normal file
|
@ -0,0 +1,411 @@
|
||||||
|
#include "tracker/utility.hpp"
|
||||||
|
|
||||||
|
#include <opencv2/calib3d/calib3d.hpp>
|
||||||
|
#include <opencv2/imgproc/imgproc.hpp>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
using namespace cv;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
/* FUNCTIONS TO DEVELOP */
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detect a chessboard in a given image
|
||||||
|
*
|
||||||
|
* @param[in] rgbimage The rgb image to process
|
||||||
|
* @param[out] pointbuf the set of 2D image corner detected on the chessboard
|
||||||
|
* @param[in] boardSize the size of the board in terms of corners (width X height)
|
||||||
|
* @param[in] patternType The type of chessboard pattern to look for
|
||||||
|
* @return true if the chessboard is detected inside the image, false otherwise
|
||||||
|
*/
|
||||||
|
bool detectChessboard( const Mat &rgbimage, vector<Point2f> &pointbuf, const Size &boardSize, Pattern patternType )
|
||||||
|
{
|
||||||
|
// it contains the value to return
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
switch( patternType )
|
||||||
|
{
|
||||||
|
// detect a classic chessboard
|
||||||
|
case CHESSBOARD:
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// detect the chessboard --> see findChessboardCorners
|
||||||
|
// found = ...
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
// if a chessboard is found refine the position of the points in a window 11x11 pixel
|
||||||
|
// use the default value for the termination criteria --> TermCriteria( CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 30, 0.1 )
|
||||||
|
if( found )
|
||||||
|
{
|
||||||
|
Mat viewGrey; // it will contain the graylevel version of the image
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// convert the image in "rgbimage" to gray level and save it in "viewGrey"
|
||||||
|
// --> cvtColor with CV_BGR2GRAY option
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// refine the corner location in "pointbuf" using "viewGrey"
|
||||||
|
// --> see cornerSubPix
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// detect a regular grid made of circles
|
||||||
|
case CIRCLES_GRID:
|
||||||
|
/******************************************************************/
|
||||||
|
// detect the circles --> see findCirclesGrid
|
||||||
|
// found = ...
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
// detect an asymmetric grid made of circles
|
||||||
|
case ASYMMETRIC_CIRCLES_GRID:
|
||||||
|
/******************************************************************/
|
||||||
|
// detect the circles --> see findCirclesGrid using the options CALIB_CB_ASYMMETRIC_GRID | CALIB_CB_CLUSTERING
|
||||||
|
// found = ...
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
default:
|
||||||
|
cerr << "Unknown pattern type" << endl;
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param[in,out] rgbimage The image on which to draw the reference system
|
||||||
|
* @param[in] cam The camera
|
||||||
|
* @param[in] poseMat the pose matrix of the camera
|
||||||
|
* @param[in] thickness The thickness of the line
|
||||||
|
* @param[in] scale A scale factor for the unit vectors to draw
|
||||||
|
* @param[in] alreadyUndistorted A boolean value that tells if the input image rgbimage is already undistorted or we are working on a distorted image
|
||||||
|
*/
|
||||||
|
void drawReferenceSystem( cv::Mat &rgbimage, const Camera& cam, const cv::Mat &poseMat, const int &thickness, const double &scale, bool alreadyUndistorted )
|
||||||
|
{
|
||||||
|
|
||||||
|
// contains the points to project to draw the 3 axis
|
||||||
|
vector<Point3f> vertex3D;
|
||||||
|
|
||||||
|
//******************************************************************/
|
||||||
|
// Add the four 3D points (Point3f) that we can use to draw
|
||||||
|
// the reference system to vertex3D. Use <scale> as unit
|
||||||
|
//******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// contains the projected 3D points on the image
|
||||||
|
vector<Point2f> imgRefPts;
|
||||||
|
|
||||||
|
//******************************************************************/
|
||||||
|
// Project the 3D points using myProjectPoints. Attention, check the
|
||||||
|
// flag alreadyUndistorted to see if we have to apply the distortion:
|
||||||
|
// if it is true we pass a 1x5 zero vector, otherwise the distortion
|
||||||
|
// parameter of cam
|
||||||
|
//******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// cout << "vertex3D" << vertex3D << endl;
|
||||||
|
// cout << "imgRefPts" << imgRefPts << endl;
|
||||||
|
|
||||||
|
//******************************************************************/
|
||||||
|
// draw the line of the x-axis and put "X" at the end
|
||||||
|
//******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************/
|
||||||
|
// draw the line of the y-axis and put "Y" at the end
|
||||||
|
//******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************/
|
||||||
|
// draw the line of the z-axis and put "Z" at the end
|
||||||
|
//******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper around the original opencv's projectPoints
|
||||||
|
*
|
||||||
|
* @param objectPoints the 3D points
|
||||||
|
* @param poseMat the pose matrix
|
||||||
|
* @param cameraMatrix the calibration matrix
|
||||||
|
* @param distCoeffs the distortion coeffi
|
||||||
|
* @param imagePoints
|
||||||
|
*/
|
||||||
|
void myProjectPoints( InputArray objectPoints, const Mat &poseMat, InputArray cameraMatrix, InputArray distCoeffs, OutputArray imagePoints )
|
||||||
|
{
|
||||||
|
Mat rvec;
|
||||||
|
Rodrigues( poseMat.colRange( 0, 3 ), rvec );
|
||||||
|
// projectPoints( Mat( vertex3D.t( ) ).reshape( 3, 1 ), rvec, Tvec, K, dist, imgRefPts );
|
||||||
|
projectPoints( objectPoints, rvec, poseMat.col( 3 ), cameraMatrix, distCoeffs, imagePoints );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate the set of 3D points of a chessboard
|
||||||
|
*
|
||||||
|
* @param[in] boardSize the size of the board in terms of corners (width X height)
|
||||||
|
* @param[in] squareSize the size in mm of the each square of the chessboard
|
||||||
|
* @param[out] corners the set of 2D points on the chessboard
|
||||||
|
* @param[in] patternType The type of chessboard pattern to look for
|
||||||
|
*/
|
||||||
|
void calcChessboardCorners( const Size &boardSize, const float &squareSize, vector<Point2f>& corners, Pattern patternType )
|
||||||
|
{
|
||||||
|
corners.resize( 0 );
|
||||||
|
corners.reserve( boardSize.height * boardSize.width );
|
||||||
|
|
||||||
|
switch( patternType )
|
||||||
|
{
|
||||||
|
case CHESSBOARD:
|
||||||
|
case CIRCLES_GRID:
|
||||||
|
for( int i = 0; i < boardSize.height; i++ )
|
||||||
|
for( int j = 0; j < boardSize.width; j++ )
|
||||||
|
{
|
||||||
|
/******************************************************************/
|
||||||
|
// create a Point2f(x,y) according to the position j,i and a square
|
||||||
|
// size of squareSize. Add it to corners (using push_back...)
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ASYMMETRIC_CIRCLES_GRID:
|
||||||
|
for( int i = 0; i < boardSize.height; i++ )
|
||||||
|
for( int j = 0; j < boardSize.width; j++ )
|
||||||
|
{
|
||||||
|
/******************************************************************/
|
||||||
|
// create a Point2f(x,y) according to the position j,i considering
|
||||||
|
// that x is generate using the formula (2*j + i % 2)*squareSize
|
||||||
|
// Add it to corners (using push_back...)
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
CV_Error( CV_StsBadArg, "Unknown pattern type\n" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decompose the homography into its components R and t
|
||||||
|
*
|
||||||
|
* @param[in] H The homography H = [h1 h2 h3]
|
||||||
|
* @param[in] matK The 3x3 calibration matrix K
|
||||||
|
* @param[out] poseMat the 3x4 pose matrix [R t]
|
||||||
|
*/
|
||||||
|
void decomposeHomography( const Mat &H, const Mat& matK, Mat& poseMat )
|
||||||
|
{
|
||||||
|
|
||||||
|
Mat temp;
|
||||||
|
|
||||||
|
//******************************************************************/
|
||||||
|
//temp contains inv(K)*H
|
||||||
|
//******************************************************************/
|
||||||
|
|
||||||
|
// PRINTVAR( temp );
|
||||||
|
|
||||||
|
Mat r1, r2, r3, t;
|
||||||
|
//******************************************************************/
|
||||||
|
// get r1 and r2 from temp
|
||||||
|
//******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************/
|
||||||
|
// compute lambda
|
||||||
|
//******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************/
|
||||||
|
// normalize r1 and r2
|
||||||
|
//******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************/
|
||||||
|
// compute r3
|
||||||
|
//******************************************************************/
|
||||||
|
|
||||||
|
// PRINTVAR( r3 );
|
||||||
|
|
||||||
|
//******************************************************************/
|
||||||
|
// compute t
|
||||||
|
//******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************/
|
||||||
|
// create a 3x4 matrix (float) for poseMat
|
||||||
|
//******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************/
|
||||||
|
// fill the columns of poseMat with r1 r2 r3 and t
|
||||||
|
//******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// PRINTVAR( poseMat );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
//KLT ONLY
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate the set of 3D points of a chessboard
|
||||||
|
*
|
||||||
|
* @param[in] boardSize the size of the board in terms of corners (width X height)
|
||||||
|
* @param[in] squareSize the size in mm of the each square of the chessboard
|
||||||
|
* @param[out] corners the set of 3D points on the chessboard
|
||||||
|
* @param[in] patternType The type of chessboard pattern to look for
|
||||||
|
*/
|
||||||
|
void calcChessboardCorners3D( const Size &boardSize, const float &squareSize, vector<Point3f>& corners, Pattern patternType )
|
||||||
|
{
|
||||||
|
corners.resize( 0 );
|
||||||
|
corners.reserve( boardSize.height * boardSize.width );
|
||||||
|
|
||||||
|
switch( patternType )
|
||||||
|
{
|
||||||
|
case CHESSBOARD:
|
||||||
|
case CIRCLES_GRID:
|
||||||
|
for( int i = 0; i < boardSize.height; i++ )
|
||||||
|
for( int j = 0; j < boardSize.width; j++ )
|
||||||
|
{
|
||||||
|
/******************************************************************/
|
||||||
|
// create a Point3f(x,y,0) according to the position j,i and a square
|
||||||
|
// size of squareSize. Add it to corners (using push_back...)
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ASYMMETRIC_CIRCLES_GRID:
|
||||||
|
for( int i = 0; i < boardSize.height; i++ )
|
||||||
|
for( int j = 0; j < boardSize.width; j++ )
|
||||||
|
{
|
||||||
|
/******************************************************************/
|
||||||
|
// create a Point3f(x,y,0) according to the position j,i considering
|
||||||
|
// that x is generate using the formula (2*j + i % 2)*squareSize
|
||||||
|
// Add it to corners (using push_back...)
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
CV_Error( CV_StsBadArg, "Unknown pattern type\n" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper around the original opencv's solvePnPRansac
|
||||||
|
*
|
||||||
|
* @param[in] objectPoints the 3D points
|
||||||
|
* @param[in] imagePoints the image points
|
||||||
|
* @param[in] cameraMatrix the calibration matrix
|
||||||
|
* @param[in] distCoeffs the distortion coefficients
|
||||||
|
* @param[out] poseMat the pose matrix
|
||||||
|
* @param[out] inliers the list of indices of the inliers points
|
||||||
|
*/
|
||||||
|
void mySolvePnPRansac( cv::InputArray objectPoints, cv::InputArray imagePoints, cv::InputArray cameraMatrix, cv::InputArray distCoeffs, cv::Mat &poseMat, OutputArray inliers )
|
||||||
|
{
|
||||||
|
Mat currR, currT;
|
||||||
|
solvePnPRansac( objectPoints, imagePoints, cameraMatrix, distCoeffs, currR, currT, false, 100, 4, 100, inliers );
|
||||||
|
|
||||||
|
poseMat = Mat( 3, 4, CV_32F );
|
||||||
|
|
||||||
|
Mat Rot;
|
||||||
|
Rodrigues( currR, Rot );
|
||||||
|
#if CV_MINOR_VERSION < 4
|
||||||
|
// apparently older versions does not support direct copy
|
||||||
|
Mat temp;
|
||||||
|
Rot.convertTo( temp, CV_32F );
|
||||||
|
Mat a1 = poseMat.colRange( 0, 3 );
|
||||||
|
temp.copyTo( a1 );
|
||||||
|
a1 = poseMat.col( 3 );
|
||||||
|
currT.convertTo( temp, CV_32F );
|
||||||
|
temp.copyTo( a1 );
|
||||||
|
#else
|
||||||
|
Rot.copyTo( poseMat.colRange( 0, 3 ) );
|
||||||
|
currT.copyTo( poseMat.col( 3 ) );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool getVideoSizeAndType(const std::string &videoFilename, cv::VideoCapture capture, cv::Size &singleSize, int &imgInType)
|
||||||
|
{
|
||||||
|
if( !capture.isOpened( ) )
|
||||||
|
{
|
||||||
|
cerr << "Could not open video file " << videoFilename << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// open video file and get the first image just to get the image size
|
||||||
|
Mat view0;
|
||||||
|
capture >> view0;
|
||||||
|
if( view0.empty( ) )
|
||||||
|
{
|
||||||
|
cerr << "Could not get the first frame of the video file " << videoFilename << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
imgInType = view0.type( );
|
||||||
|
singleSize = view0.size( );
|
||||||
|
|
||||||
|
// close capture...
|
||||||
|
capture.release( );
|
||||||
|
// and re-open it so that we will start from the first frame again
|
||||||
|
return capture.open(videoFilename);
|
||||||
|
}
|
223
src/tp/tracking.cpp
Normal file
|
@ -0,0 +1,223 @@
|
||||||
|
#include "tracker/Camera.hpp"
|
||||||
|
#include "tracker/ChessboardCameraTracker.hpp"
|
||||||
|
#include "tracker/utility.hpp"
|
||||||
|
|
||||||
|
#include <opencv2/highgui/highgui.hpp>
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
|
using namespace cv;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
// Display the help for the program
|
||||||
|
void help( const char* programName );
|
||||||
|
|
||||||
|
// parse the input command line arguments
|
||||||
|
bool parseArgs( int argc, char**argv, Size &boardSize, string &inputFilename, string &calibFile );
|
||||||
|
|
||||||
|
int main( int argc, char** argv )
|
||||||
|
{
|
||||||
|
/******************************************************************/
|
||||||
|
/* CONSTANTS to use */
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
// the name of the window
|
||||||
|
const string WINDOW_NAME = "Image View";
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
/* VARIABLES to use */
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
// it will contain the size in terms of corners (width X height) of the chessboard
|
||||||
|
Size boardSize;
|
||||||
|
|
||||||
|
// it will contains the filename of the image file
|
||||||
|
string inputFilename;
|
||||||
|
|
||||||
|
// it will contains the filename of the image file
|
||||||
|
string calibFilename;
|
||||||
|
|
||||||
|
// Default pattern is chessboard
|
||||||
|
Pattern pattern = CHESSBOARD;
|
||||||
|
|
||||||
|
// Used to load the video and get the frames
|
||||||
|
VideoCapture capture;
|
||||||
|
|
||||||
|
// Camera object containing the calibration parameters
|
||||||
|
Camera cam;
|
||||||
|
|
||||||
|
// Camera Tracker object
|
||||||
|
ChessboardCameraTracker tracker;
|
||||||
|
|
||||||
|
// 3x4 camera pose matrix [R t]
|
||||||
|
Mat cameraPose;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
/* READ THE INPUT PARAMETERS - DO NOT MODIFY */
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
if( !parseArgs( argc, argv, boardSize, inputFilename, calibFilename ) )
|
||||||
|
{
|
||||||
|
cerr << "Aborting..." << endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
/* PART TO DEVELOP */
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// create a window using WINDOW_NAME as name to display the image --> see namedWindow
|
||||||
|
/******************************************************************/
|
||||||
|
namedWindow( WINDOW_NAME, CV_WINDOW_AUTOSIZE | CV_WINDOW_KEEPRATIO );
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// read the input video with capture (same as before)
|
||||||
|
/******************************************************************/
|
||||||
|
capture.open( string( inputFilename ) );
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// check it is really opened
|
||||||
|
/******************************************************************/
|
||||||
|
if( !capture.isOpened( ) )
|
||||||
|
{
|
||||||
|
cerr << "Could not open video file " << inputFilename << endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//******************************************************************/
|
||||||
|
// init the Camera loading the calibration parameters
|
||||||
|
//******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// processing loop
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
Mat view;
|
||||||
|
/******************************************************************/
|
||||||
|
// get the new frame from capture and copy it to view
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// if no more images to process exit the loop
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************/
|
||||||
|
// process the image with the process method
|
||||||
|
//******************************************************************/
|
||||||
|
//if...
|
||||||
|
{
|
||||||
|
//******************************************************************/
|
||||||
|
// draw the reference on top of the image
|
||||||
|
//******************************************************************/
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// show the image inside the window --> see imshow
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
// wait 20ms for user input before processing the next frame
|
||||||
|
// Any user input will stop the execution
|
||||||
|
#if DEBUGGING
|
||||||
|
if( ( waitKey( -1 ) & 0xff ) == 'q' )
|
||||||
|
break;
|
||||||
|
#else
|
||||||
|
if( waitKey( 10 ) >= 0 )
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// release the video resource
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Display the help for the program
|
||||||
|
|
||||||
|
void help( const char* programName )
|
||||||
|
{
|
||||||
|
cout << "Detect a chessboard and display an augmented reference system on top of it" << endl
|
||||||
|
<< "Usage: " << programName << endl
|
||||||
|
<< " -w <board_width> # the number of inner corners per one of board dimension" << endl
|
||||||
|
<< " -h <board_height> # the number of inner corners per another board dimension" << endl
|
||||||
|
<< " -c <calib file> # the name of the calibration file" << endl
|
||||||
|
<< " <video file> # the name of the video file" << endl
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse the input command line arguments
|
||||||
|
|
||||||
|
bool parseArgs( int argc, char**argv, Size &boardSize, string &inputFilename, string &calibFile )
|
||||||
|
{
|
||||||
|
// check the minimum number of arguments
|
||||||
|
if( argc < 3 )
|
||||||
|
{
|
||||||
|
help( argv[0] );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Read the input arguments
|
||||||
|
for( int i = 1; i < argc; i++ )
|
||||||
|
{
|
||||||
|
const char* s = argv[i];
|
||||||
|
if( strcmp( s, "-w" ) == 0 )
|
||||||
|
{
|
||||||
|
if( sscanf( argv[++i], "%u", &boardSize.width ) != 1 || boardSize.width <= 0 )
|
||||||
|
{
|
||||||
|
cerr << "Invalid board width" << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( strcmp( s, "-h" ) == 0 )
|
||||||
|
{
|
||||||
|
if( sscanf( argv[++i], "%u", &boardSize.height ) != 1 || boardSize.height <= 0 )
|
||||||
|
{
|
||||||
|
cerr << "Invalid board height" << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( s[0] != '-' )
|
||||||
|
{
|
||||||
|
inputFilename.assign( s );
|
||||||
|
}
|
||||||
|
else if( strcmp( s, "-c" ) == 0 )
|
||||||
|
{
|
||||||
|
if( i + 1 < argc )
|
||||||
|
calibFile.assign( argv[++i] );
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cerr << "Missing argument for option " << s << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cerr << "Unknown option " << s << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
220
src/tp/trackingKLT.cpp
Normal file
|
@ -0,0 +1,220 @@
|
||||||
|
#include "tracker/Camera.hpp"
|
||||||
|
#include "tracker/ChessboardCameraTrackerKLT.hpp"
|
||||||
|
#include "tracker/utility.hpp"
|
||||||
|
|
||||||
|
#include <opencv2/highgui/highgui.hpp>
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
|
using namespace cv;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
// Display the help for the program
|
||||||
|
void help( const char* programName );
|
||||||
|
|
||||||
|
// parse the input command line arguments
|
||||||
|
bool parseArgs( int argc, char**argv, Size &boardSize, string &inputFilename, string &calibFile );
|
||||||
|
|
||||||
|
int main( int argc, char** argv )
|
||||||
|
{
|
||||||
|
/******************************************************************/
|
||||||
|
/* CONSTANTS to use */
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
// the name of the window
|
||||||
|
const string WINDOW_NAME = "Image View";
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
/* VARIABLES to use */
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
// it will contain the size in terms of corners (width X height) of the chessboard
|
||||||
|
Size boardSize;
|
||||||
|
|
||||||
|
// it will contains the filename of the image file
|
||||||
|
string inputFilename;
|
||||||
|
|
||||||
|
// it will contains the filename of the image file
|
||||||
|
string calibFilename;
|
||||||
|
|
||||||
|
// Default pattern is chessboard
|
||||||
|
Pattern pattern = CHESSBOARD;
|
||||||
|
|
||||||
|
// Used to load the video and get the frames
|
||||||
|
VideoCapture capture;
|
||||||
|
|
||||||
|
// Camera object containing the calibration parameters
|
||||||
|
Camera cam;
|
||||||
|
|
||||||
|
// Camera Tracker object
|
||||||
|
ChessboardCameraTrackerKLT tracker;
|
||||||
|
|
||||||
|
// 3x4 camera pose matrix [R t]
|
||||||
|
Mat cameraPose;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
/* READ THE INPUT PARAMETERS - DO NOT MODIFY */
|
||||||
|
/******************************************************************/
|
||||||
|
if( !parseArgs( argc, argv, boardSize, inputFilename, calibFilename ) )
|
||||||
|
{
|
||||||
|
cerr << "Aborting..." << endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
/* PART TO DEVELOP */
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
//******************************************************************/
|
||||||
|
// create a window using WINDOW_NAME as name to display the image --> see namedWindow
|
||||||
|
//******************************************************************/
|
||||||
|
namedWindow( WINDOW_NAME, CV_WINDOW_AUTOSIZE | CV_WINDOW_KEEPRATIO );
|
||||||
|
|
||||||
|
//******************************************************************/
|
||||||
|
// read the input video with capture (same as before)
|
||||||
|
//******************************************************************/
|
||||||
|
capture.open( string( inputFilename ) );
|
||||||
|
|
||||||
|
//******************************************************************/
|
||||||
|
// check it is really opened
|
||||||
|
//******************************************************************/
|
||||||
|
if( !capture.isOpened( ) )
|
||||||
|
{
|
||||||
|
cerr << "Could not open video file " << inputFilename << endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//******************************************************************/
|
||||||
|
// init the Camera loading the calibration parameters
|
||||||
|
//******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// processing loop
|
||||||
|
while( true )
|
||||||
|
{
|
||||||
|
Mat view;
|
||||||
|
/******************************************************************/
|
||||||
|
// get the new frame from capture and copy it to view
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// if no more images to process exit the loop
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************/
|
||||||
|
// process the image
|
||||||
|
//******************************************************************/
|
||||||
|
//if...
|
||||||
|
{
|
||||||
|
//******************************************************************/
|
||||||
|
// draw the reference on top of the image
|
||||||
|
//******************************************************************/
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// show the image inside the window --> see imshow
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
// wait 20ms for user input before processing the next frame
|
||||||
|
// Any user input will stop the execution
|
||||||
|
#if DEBUGGING
|
||||||
|
if( ( waitKey( -1 ) & 0xff ) == 'q' )
|
||||||
|
break;
|
||||||
|
#else
|
||||||
|
if( waitKey( 10 ) >= 0 )
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
// release the video resource
|
||||||
|
/******************************************************************/
|
||||||
|
capture.release( );
|
||||||
|
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display the help for the program
|
||||||
|
|
||||||
|
void help( const char* programName )
|
||||||
|
{
|
||||||
|
cout << "Detect and track a chessboard with the KLT algorithm and display an augmented reference system on top of it" << endl
|
||||||
|
<< "Usage: " << programName << endl
|
||||||
|
<< " -w <board_width> # the number of inner corners per one of board dimension" << endl
|
||||||
|
<< " -h <board_height> # the number of inner corners per another board dimension" << endl
|
||||||
|
<< " -c <calib file> # the name of the calibration file" << endl
|
||||||
|
<< " <video file> # the name of the video file" << endl
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse the input command line arguments
|
||||||
|
|
||||||
|
bool parseArgs( int argc, char**argv, Size &boardSize, string &inputFilename, string &calibFile )
|
||||||
|
{
|
||||||
|
// check the minimum number of arguments
|
||||||
|
if( argc < 3 )
|
||||||
|
{
|
||||||
|
help( argv[0] );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Read the input arguments
|
||||||
|
for( int i = 1; i < argc; i++ )
|
||||||
|
{
|
||||||
|
const char* s = argv[i];
|
||||||
|
if( strcmp( s, "-w" ) == 0 )
|
||||||
|
{
|
||||||
|
if( sscanf( argv[++i], "%u", &boardSize.width ) != 1 || boardSize.width <= 0 )
|
||||||
|
{
|
||||||
|
cerr << "Invalid board width" << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( strcmp( s, "-h" ) == 0 )
|
||||||
|
{
|
||||||
|
if( sscanf( argv[++i], "%u", &boardSize.height ) != 1 || boardSize.height <= 0 )
|
||||||
|
{
|
||||||
|
cerr << "Invalid board height" << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( s[0] != '-' )
|
||||||
|
{
|
||||||
|
inputFilename.assign( s );
|
||||||
|
}
|
||||||
|
else if( strcmp( s, "-c" ) == 0 )
|
||||||
|
{
|
||||||
|
if( i + 1 < argc )
|
||||||
|
calibFile.assign( argv[++i] );
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cerr << "Missing argument for option " << s << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cerr << "Unknown option " << s << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
256
src/tp/videoOGL.cpp
Normal file
|
@ -0,0 +1,256 @@
|
||||||
|
#include "tracker/utility.hpp"
|
||||||
|
#include <opencv2/highgui/highgui.hpp>
|
||||||
|
#include <opencv2/calib3d/calib3d.hpp>
|
||||||
|
#include <opencv2/core/core.hpp>
|
||||||
|
#include <opencv2/imgproc/imgproc.hpp>
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#include <OpenGL/gl.h>
|
||||||
|
// #include <OpenGL/glu.h>
|
||||||
|
#include <GLUT/glut.h>
|
||||||
|
#else
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
#include <GL/gl.h>
|
||||||
|
// #include <GL/glu.h>
|
||||||
|
#include <GL/freeglut.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <iostream>
|
||||||
|
#include <chrono>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace cv;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Common globals
|
||||||
|
*/
|
||||||
|
|
||||||
|
int gFinished;
|
||||||
|
|
||||||
|
// the OpenGL reference for the texture to display
|
||||||
|
GLuint gCameraTextureId;
|
||||||
|
|
||||||
|
// this will physically contain the current frame that is used as texture
|
||||||
|
Mat gResultImage;
|
||||||
|
|
||||||
|
// the size of the video frame
|
||||||
|
Size singleSize;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// OpenGL initialization
|
||||||
|
|
||||||
|
void glInit( )
|
||||||
|
{
|
||||||
|
|
||||||
|
glEnable( GL_TEXTURE_2D );
|
||||||
|
glGenTextures( 1, &gCameraTextureId );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Updates texture handle gCameraTextureId with OpenCV image in cv::Mat from gResultImage
|
||||||
|
|
||||||
|
void updateTexture( )
|
||||||
|
{
|
||||||
|
glBindTexture( GL_TEXTURE_2D, gCameraTextureId );
|
||||||
|
|
||||||
|
// set texture filter to linear - we do not build mipmaps for speed
|
||||||
|
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
|
||||||
|
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
|
||||||
|
|
||||||
|
// create the texture from OpenCV image data
|
||||||
|
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB8, singleSize.width, singleSize.height, 0,
|
||||||
|
#if _WIN32
|
||||||
|
GL_BGR_EXT,
|
||||||
|
#else
|
||||||
|
GL_BGR,
|
||||||
|
#endif
|
||||||
|
GL_UNSIGNED_BYTE, gResultImage.data );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw the background from the camera image
|
||||||
|
*/
|
||||||
|
void drawBackground( )
|
||||||
|
{
|
||||||
|
// set up the modelview matrix so that the view is between [-1,-1] and [1,1]
|
||||||
|
glMatrixMode( GL_PROJECTION );
|
||||||
|
glPushMatrix( );
|
||||||
|
glLoadIdentity( );
|
||||||
|
glOrtho( -1, 1, -1, 1, 0, 1 );
|
||||||
|
glMatrixMode( GL_MODELVIEW );
|
||||||
|
glLoadIdentity( );
|
||||||
|
|
||||||
|
// draw the quad textured with the camera image
|
||||||
|
glBindTexture( GL_TEXTURE_2D, gCameraTextureId );
|
||||||
|
glBegin( GL_QUADS );
|
||||||
|
glTexCoord2f( 0, 1 );
|
||||||
|
glVertex2f( -1, -1 );
|
||||||
|
glTexCoord2f( 0, 0 );
|
||||||
|
glVertex2f( -1, 1 );
|
||||||
|
glTexCoord2f( 1, 0 );
|
||||||
|
glVertex2f( 1, 1 );
|
||||||
|
glTexCoord2f( 1, 1 );
|
||||||
|
glVertex2f( 1, -1 );
|
||||||
|
glEnd( );
|
||||||
|
|
||||||
|
// reset the projection matrix
|
||||||
|
glMatrixMode( GL_PROJECTION );
|
||||||
|
glPopMatrix( );
|
||||||
|
glMatrixMode( GL_MODELVIEW );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** OpenGL display callback */
|
||||||
|
void displayFunc( )
|
||||||
|
{
|
||||||
|
glClear( GL_COLOR_BUFFER_BIT );
|
||||||
|
|
||||||
|
// render the background image from camera texture
|
||||||
|
glEnable( GL_TEXTURE_2D );
|
||||||
|
|
||||||
|
drawBackground( );
|
||||||
|
|
||||||
|
// clear th depth buffer bit so that the background is overdrawn
|
||||||
|
glClear( GL_DEPTH_BUFFER_BIT );
|
||||||
|
|
||||||
|
// everything will be white
|
||||||
|
glColor3f( 1, 1, 1 );
|
||||||
|
|
||||||
|
// start with fresh modelview matrix and apply the transform of the plane
|
||||||
|
glLoadIdentity( );
|
||||||
|
|
||||||
|
// enable the texture for a nice effect ;)
|
||||||
|
glDisable( GL_TEXTURE_2D );
|
||||||
|
|
||||||
|
glutSwapBuffers( );
|
||||||
|
glutPostRedisplay( );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Windows resize callback
|
||||||
|
|
||||||
|
void reshape( GLint width, GLint height )
|
||||||
|
{
|
||||||
|
glViewport( 0, 0, width, height );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keyboard callback
|
||||||
|
|
||||||
|
void keyFunc( unsigned char key, int x, int y )
|
||||||
|
{
|
||||||
|
cout << key << " pressed" << endl;
|
||||||
|
|
||||||
|
switch( key )
|
||||||
|
{
|
||||||
|
case 27:
|
||||||
|
gFinished = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void printHelp( const string &name )
|
||||||
|
{
|
||||||
|
cout << "Usage: " << endl << "\t" << name << " <videofile.avi> " << endl << endl << "Options: " << endl;
|
||||||
|
cout << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main( int argc, char** argv )
|
||||||
|
{
|
||||||
|
|
||||||
|
string videoFilename;
|
||||||
|
int imgInType;
|
||||||
|
|
||||||
|
long frameNumber = 0;
|
||||||
|
|
||||||
|
if( argc < 2 )
|
||||||
|
{
|
||||||
|
cerr << "Wrong number of parameters" << endl;
|
||||||
|
printHelp( string( argv[0] ) );
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
VideoCapture capture;
|
||||||
|
|
||||||
|
videoFilename.assign( argv[1] );
|
||||||
|
|
||||||
|
capture.open( videoFilename );
|
||||||
|
|
||||||
|
// check if capture has opened the video
|
||||||
|
if( !capture.isOpened( ) )
|
||||||
|
{
|
||||||
|
cerr << "Could not open video file " << videoFilename << endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
if( !getVideoSizeAndType(videoFilename, capture, singleSize, imgInType ) )
|
||||||
|
{
|
||||||
|
cerr << "Something wrong while checking the size and type of the video " << videoFilename << endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gResultImage = Mat( singleSize, imgInType );
|
||||||
|
|
||||||
|
|
||||||
|
// Setup GLUT rendering and callbacks
|
||||||
|
glutInit( &argc, argv );
|
||||||
|
glutCreateWindow( "Main" );
|
||||||
|
glutKeyboardFunc( keyFunc );
|
||||||
|
glutReshapeFunc( reshape );
|
||||||
|
// reshape the window with the size of the image
|
||||||
|
glutReshapeWindow( singleSize.width, singleSize.height );
|
||||||
|
glutDisplayFunc( displayFunc );
|
||||||
|
|
||||||
|
glInit( );
|
||||||
|
|
||||||
|
gFinished = false;
|
||||||
|
|
||||||
|
while( !gFinished )
|
||||||
|
{
|
||||||
|
|
||||||
|
Mat view0;
|
||||||
|
capture >> view0;
|
||||||
|
|
||||||
|
// get a copy of the frame
|
||||||
|
if( view0.empty( ) )
|
||||||
|
{
|
||||||
|
cerr << "no more images available" << endl;
|
||||||
|
gFinished = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
view0.copyTo( gResultImage );
|
||||||
|
|
||||||
|
cout << endl << endl << "****************** frame " << frameNumber << " ******************" << endl;
|
||||||
|
|
||||||
|
++frameNumber;
|
||||||
|
|
||||||
|
// update the texture to be displayed in OPENGL
|
||||||
|
updateTexture( );
|
||||||
|
|
||||||
|
// force Opengl to call the displayFunc
|
||||||
|
#if __APPLE__
|
||||||
|
glutCheckLoop( );
|
||||||
|
#else
|
||||||
|
glutMainLoopEvent( );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// sleep for 35ms
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(35));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
capture.release( );
|
||||||
|
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
561
src/tp/videoOGLOBJ.cpp
Normal file
|
@ -0,0 +1,561 @@
|
||||||
|
#include "tracker/Camera.hpp"
|
||||||
|
#include "tracker/ChessboardCameraTracker.hpp"
|
||||||
|
#include "tracker/ChessboardCameraTrackerKLT.hpp"
|
||||||
|
#include "tracker/utility.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
#include <opencv2/highgui/highgui.hpp>
|
||||||
|
#include <opencv2/calib3d/calib3d.hpp>
|
||||||
|
#include <opencv2/core/core.hpp>
|
||||||
|
#include <opencv2/imgproc/imgproc.hpp>
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#include <OpenGL/gl.h>
|
||||||
|
// #include <OpenGL/glu.h>
|
||||||
|
#include <GLUT/glut.h>
|
||||||
|
#else
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
#include <GL/gl.h>
|
||||||
|
// #include <GL/glu.h>
|
||||||
|
#include <GL/freeglut.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#include <glm.h>
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <iostream>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <chrono>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace cv;
|
||||||
|
|
||||||
|
// Display the help for the programm
|
||||||
|
void help( const char* programName );
|
||||||
|
|
||||||
|
// parse the input command line arguments
|
||||||
|
bool parseArgs( int argc, char**argv, Size &boardSize, string &inputFilename, string &calibFile, string &objFile );
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Common globals
|
||||||
|
*/
|
||||||
|
|
||||||
|
int gFinished;
|
||||||
|
|
||||||
|
// the OpenGL reference for the texture to display
|
||||||
|
GLuint gCameraTextureId;
|
||||||
|
// the global array containng the explicit modelview matrix
|
||||||
|
const float *gModelViewMatrix;
|
||||||
|
// the global array containng the explicit projection matrix
|
||||||
|
float gProjectionMatrix[16] = {0.f};
|
||||||
|
// this will physically contain the current frame that is used as texture
|
||||||
|
Mat gResultImage;
|
||||||
|
bool stop = false;
|
||||||
|
bool drawTeapot = true;
|
||||||
|
GLMmodel *model{nullptr};
|
||||||
|
|
||||||
|
// the size of the video frame
|
||||||
|
Size singleSize;
|
||||||
|
|
||||||
|
void DrawAxis( float scale )
|
||||||
|
{
|
||||||
|
glPushMatrix( );
|
||||||
|
glDisable( GL_LIGHTING );
|
||||||
|
// glDisable(GL_TEXTURE_2D);
|
||||||
|
glScalef( scale, scale, scale );
|
||||||
|
|
||||||
|
glBegin( GL_LINES );
|
||||||
|
|
||||||
|
glColor3f( 1.0, 0.0, 0.0 );
|
||||||
|
glVertex3f( .8f, 0.05f, 0.0 );
|
||||||
|
glVertex3f( 1.0, 0.25f, 0.0 ); /* Letter X */
|
||||||
|
glVertex3f( 0.8f, .25f, 0.0 );
|
||||||
|
glVertex3f( 1.0, 0.05f, 0.0 );
|
||||||
|
glVertex3f( 0.0, 0.0, 0.0 );
|
||||||
|
glVertex3f( 1.0, 0.0, 0.0 ); /* X axis */
|
||||||
|
|
||||||
|
glColor3f( 0.0, 1.0, 0.0 );
|
||||||
|
glVertex3f( 0.0, 0.0, 0.0 );
|
||||||
|
glVertex3f( 0.0, 1.0, 0.0 ); /* Y axis */
|
||||||
|
|
||||||
|
glColor3f( 0.0, 0.0, 1.0 );
|
||||||
|
glVertex3f( 0.0, 0.0, 0.0 );
|
||||||
|
glVertex3f( 0.0, 0.0, 1.0 ); /* Z axis */
|
||||||
|
glEnd( );
|
||||||
|
// if (lighting)
|
||||||
|
glEnable( GL_LIGHTING );
|
||||||
|
// if (lighting)
|
||||||
|
// glEnable(GL_TEXTURE_2D);
|
||||||
|
glColor3f( 1.0, 1.0, 1.0 );
|
||||||
|
glPopMatrix( );
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawPoints( float scale )
|
||||||
|
{
|
||||||
|
glPushMatrix( );
|
||||||
|
glDisable( GL_LIGHTING );
|
||||||
|
// glDisable(GL_TEXTURE_2D);
|
||||||
|
glScalef( scale, scale, scale );
|
||||||
|
glPointSize( 3 );
|
||||||
|
glBegin( GL_POINTS );
|
||||||
|
|
||||||
|
for( int i = 0; i < 6; i++ )
|
||||||
|
{
|
||||||
|
|
||||||
|
glColor3f( 1.0, ( float ) 40.0f * i / 255.0f, ( float ) 40.0f * i / 255.0f );
|
||||||
|
for( int j = 0; j < 9; j++ )
|
||||||
|
glVertex3f( j, i, 0.0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
glEnd( );
|
||||||
|
// if (lighting)
|
||||||
|
glEnable( GL_LIGHTING );
|
||||||
|
// if (lighting)
|
||||||
|
// glEnable(GL_TEXTURE_2D);
|
||||||
|
glColor3f( 1.0, 1.0, 1.0 );
|
||||||
|
glPopMatrix( );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OpenGL initialization
|
||||||
|
*/
|
||||||
|
void glInit( )
|
||||||
|
{
|
||||||
|
|
||||||
|
//******************************************************************
|
||||||
|
// enable the depth test
|
||||||
|
//******************************************************************
|
||||||
|
glEnable( GL_DEPTH_TEST );
|
||||||
|
glDepthFunc( GL_LESS );
|
||||||
|
|
||||||
|
glEnable( GL_TEXTURE_2D );
|
||||||
|
glGenTextures( 1, &gCameraTextureId );
|
||||||
|
|
||||||
|
//******************************************************************
|
||||||
|
// set the Gouraud shading
|
||||||
|
//******************************************************************
|
||||||
|
glShadeModel( GL_SMOOTH );
|
||||||
|
|
||||||
|
//******************************************************************
|
||||||
|
// set the LIGHT0 as a simple white, directional light with direction [1,2,-2]
|
||||||
|
//******************************************************************
|
||||||
|
GLfloat gLightPos[] = {100.0, 200.0, -200.0, 0.0};
|
||||||
|
glLightfv( GL_LIGHT0, GL_POSITION, gLightPos );
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************
|
||||||
|
// set the material properties for the teapot
|
||||||
|
// choose the values for ambient, diffuse, specular and shininess
|
||||||
|
// as you prefer. The teapot in the figure has is mainly gray with
|
||||||
|
// ambient 0.7, diffuse 0.8, specular 1.0 and shininess 100
|
||||||
|
//******************************************************************
|
||||||
|
GLfloat mat_ambient[] = {0.7, 0.7, 0.7, 1.0};
|
||||||
|
GLfloat mat_diffuse[] = {0.8, 0.8, 0.8, 1.0};
|
||||||
|
GLfloat mat_specular[] = {1.0, 1.0, 1.0, 1.0};
|
||||||
|
GLfloat high_shininess[] = {100.0};
|
||||||
|
|
||||||
|
glMaterialfv( GL_FRONT, GL_AMBIENT, mat_ambient );
|
||||||
|
glMaterialfv( GL_FRONT, GL_DIFFUSE, mat_diffuse );
|
||||||
|
glMaterialfv( GL_FRONT, GL_SPECULAR, mat_specular );
|
||||||
|
glMaterialfv( GL_FRONT, GL_SHININESS, high_shininess );
|
||||||
|
|
||||||
|
//******************************************************************
|
||||||
|
// enable the lights
|
||||||
|
//******************************************************************
|
||||||
|
glEnable( GL_LIGHTING );
|
||||||
|
glEnable( GL_LIGHT0 );
|
||||||
|
|
||||||
|
//******************************************************************
|
||||||
|
// set the opengl projection matrix to gProjectionMatrix:
|
||||||
|
// load the identity and multiply it by gProjectionMatrix using glMultMatrixf
|
||||||
|
//******************************************************************
|
||||||
|
glMatrixMode( GL_PROJECTION );
|
||||||
|
glLoadIdentity( );
|
||||||
|
glMultMatrixf( gProjectionMatrix );
|
||||||
|
|
||||||
|
//******************************************************************
|
||||||
|
// set back the modelview mode
|
||||||
|
//******************************************************************
|
||||||
|
glMatrixMode( GL_MODELVIEW );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Updates texture handle gCameraTextureId with OpenCV image in cv::Mat from gResultImage
|
||||||
|
|
||||||
|
void updateTexture( )
|
||||||
|
{
|
||||||
|
glBindTexture( GL_TEXTURE_2D, gCameraTextureId );
|
||||||
|
|
||||||
|
// set texture filter to linear - we do not build mipmaps for speed
|
||||||
|
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
|
||||||
|
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
|
||||||
|
|
||||||
|
// create the texture from OpenCV image data
|
||||||
|
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB8, singleSize.width, singleSize.height, 0,
|
||||||
|
#if _WIN32
|
||||||
|
GL_BGR_EXT,
|
||||||
|
#else
|
||||||
|
GL_BGR,
|
||||||
|
#endif
|
||||||
|
GL_UNSIGNED_BYTE, gResultImage.data );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw the background from the camera image
|
||||||
|
*/
|
||||||
|
void drawBackground( )
|
||||||
|
{
|
||||||
|
// set up the modelview matrix so that the view is between [-1,-1] and [1,1]
|
||||||
|
glMatrixMode( GL_PROJECTION );
|
||||||
|
glPushMatrix( );
|
||||||
|
glLoadIdentity( );
|
||||||
|
glOrtho( -1, 1, -1, 1, 0, 1 );
|
||||||
|
glMatrixMode( GL_MODELVIEW );
|
||||||
|
glLoadIdentity( );
|
||||||
|
|
||||||
|
// draw the quad textured with the camera image
|
||||||
|
glBindTexture( GL_TEXTURE_2D, gCameraTextureId );
|
||||||
|
glBegin( GL_QUADS );
|
||||||
|
glTexCoord2f( 0, 1 );
|
||||||
|
glVertex2f( -1, -1 );
|
||||||
|
glTexCoord2f( 0, 0 );
|
||||||
|
glVertex2f( -1, 1 );
|
||||||
|
glTexCoord2f( 1, 0 );
|
||||||
|
glVertex2f( 1, 1 );
|
||||||
|
glTexCoord2f( 1, 1 );
|
||||||
|
glVertex2f( 1, -1 );
|
||||||
|
glEnd( );
|
||||||
|
|
||||||
|
// reset the projection matrix
|
||||||
|
glMatrixMode( GL_PROJECTION );
|
||||||
|
glPopMatrix( );
|
||||||
|
glMatrixMode( GL_MODELVIEW );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** OpenGL display callback */
|
||||||
|
void displayFunc( )
|
||||||
|
{
|
||||||
|
glClear( GL_COLOR_BUFFER_BIT );
|
||||||
|
|
||||||
|
// render the background image from camera texture
|
||||||
|
glEnable( GL_TEXTURE_2D );
|
||||||
|
//******************************************************************
|
||||||
|
// disable the lighting before drawing the background
|
||||||
|
//******************************************************************
|
||||||
|
glDisable( GL_LIGHTING );
|
||||||
|
|
||||||
|
drawBackground( );
|
||||||
|
|
||||||
|
// clear th depth buffer bit so that the background is overdrawn
|
||||||
|
glClear( GL_DEPTH_BUFFER_BIT );
|
||||||
|
|
||||||
|
// everything will be white
|
||||||
|
glColor3f( 1, 1, 1 );
|
||||||
|
|
||||||
|
// start with fresh modelview matrix and apply the transform of the plane
|
||||||
|
glMatrixMode( GL_MODELVIEW );
|
||||||
|
glLoadIdentity( );
|
||||||
|
//******************************************************************
|
||||||
|
// apply the modelview matrix gModelViewMatrix using glMultMatrixf
|
||||||
|
//******************************************************************
|
||||||
|
glMultMatrixf( gModelViewMatrix );
|
||||||
|
// DrawPoints(25);
|
||||||
|
glRotatef( -90, 1, 0, 0 );
|
||||||
|
|
||||||
|
|
||||||
|
// enable the texture for a nice effect ;)
|
||||||
|
glDisable( GL_TEXTURE_2D );
|
||||||
|
//******************************************************************
|
||||||
|
// enable the lighting before drawing the teapot/the object
|
||||||
|
//******************************************************************
|
||||||
|
glEnable( GL_LIGHTING );
|
||||||
|
|
||||||
|
// DrawAxis(100);
|
||||||
|
|
||||||
|
glTranslatef( 0, 50, 0 );
|
||||||
|
//******************************************************************
|
||||||
|
// draw the teapot (the solid version)
|
||||||
|
//******************************************************************
|
||||||
|
if(drawTeapot)
|
||||||
|
glutSolidTeapot(45.0);
|
||||||
|
else
|
||||||
|
glmDraw(model, GLM_SMOOTH|GLM_TEXTURE);
|
||||||
|
|
||||||
|
glutSwapBuffers( );
|
||||||
|
glutPostRedisplay( );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Windows resize callback
|
||||||
|
|
||||||
|
void reshape( GLint width, GLint height )
|
||||||
|
{
|
||||||
|
glViewport( 0, 0, width, height );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keyboard callback
|
||||||
|
|
||||||
|
void keyFunc( unsigned char key, int x, int y )
|
||||||
|
{
|
||||||
|
cout << key << " pressed" << endl;
|
||||||
|
|
||||||
|
switch( key )
|
||||||
|
{
|
||||||
|
case 27:
|
||||||
|
gFinished = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 's':
|
||||||
|
stop = !stop;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main( int argc, char** argv )
|
||||||
|
{
|
||||||
|
string videoFilename, calibFilename, objFile;
|
||||||
|
int imgInType;
|
||||||
|
|
||||||
|
long frameNumber = 0;
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
/* VARIABLES TO USE */
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
// it will contain the size in terms of corners (width X height) of the chessboard
|
||||||
|
Size boardSize;
|
||||||
|
|
||||||
|
// Default pattern is chessboard
|
||||||
|
Pattern pattern = CHESSBOARD;
|
||||||
|
|
||||||
|
// Used to load the video and get the frames
|
||||||
|
VideoCapture capture;
|
||||||
|
|
||||||
|
// Camera object containing the calibration parameters
|
||||||
|
Camera cam;
|
||||||
|
|
||||||
|
// Camera Tracker object
|
||||||
|
ChessboardCameraTrackerKLT tracker;
|
||||||
|
|
||||||
|
// 3x4 camera pose matrix [R t]
|
||||||
|
Mat cameraPose;
|
||||||
|
|
||||||
|
// Mat dummyMatrix = Mat::eye( 4, 4, CV_32F );
|
||||||
|
// dummyMatrix.at<float>(0, 3) = 102;
|
||||||
|
// dummyMatrix.at<float>(1, 3) = 46;
|
||||||
|
// dummyMatrix.at<float>(2, 3) = 217;
|
||||||
|
// Mat dummyMatrix = (Mat_<float>(4,4) << -0.90750873, -0.0011025554, 0, 125.93854, 0.39205164, -0.0022058936, 0.00093782519, 43.355019, -0.15074302, 0.00085026468, 0.0024341263, 384.71075, 0,0,0,1);
|
||||||
|
Mat dummyMatrix = ( Mat_<float>( 4, 4 ) << 0.4830, -0.8756, 0.0077, 125.93854, 0.8365, 0.4588, -0.2996, 43.355019, 0.2588, 0.1511, 0.9540, 384.71075, 0, 0, 0, 1 );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cout << dummyMatrix << endl;
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
/* READ THE INPUT PARAMETERS - DO NOT MODIFY */
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
if( !parseArgs( argc, argv, boardSize, videoFilename, calibFilename, objFile ) )
|
||||||
|
{
|
||||||
|
cerr << "Aborting..." << endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the object
|
||||||
|
if(!objFile.empty())
|
||||||
|
{
|
||||||
|
model = glmReadOBJ(objFile.c_str());
|
||||||
|
if(model != nullptr)
|
||||||
|
{
|
||||||
|
drawTeapot = false;
|
||||||
|
glmUnitize(model);
|
||||||
|
glmScale(model, 140);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************
|
||||||
|
// init the Camera loading the calibration parameters
|
||||||
|
//******************************************************************
|
||||||
|
cam.init( calibFilename );
|
||||||
|
|
||||||
|
//******************************************************************
|
||||||
|
// get the corresponding projection matrix in OGL format
|
||||||
|
//******************************************************************
|
||||||
|
cam.getOGLProjectionMatrix( gProjectionMatrix, 10.f, 10000.f );
|
||||||
|
|
||||||
|
|
||||||
|
capture.open( videoFilename );
|
||||||
|
|
||||||
|
// check if capture has opened the video
|
||||||
|
if( !capture.isOpened( ) )
|
||||||
|
{
|
||||||
|
cerr << "Could not open video file " << videoFilename << endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
if( !getVideoSizeAndType(videoFilename, capture, singleSize, imgInType ) )
|
||||||
|
{
|
||||||
|
cerr << "Something wrong while checking the size and type of the video " << videoFilename << endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gResultImage = Mat( singleSize, imgInType );
|
||||||
|
|
||||||
|
|
||||||
|
// Setup GLUT rendering and callbacks
|
||||||
|
glutInit( &argc, argv );
|
||||||
|
glutCreateWindow( "Main" );
|
||||||
|
glutKeyboardFunc( keyFunc );
|
||||||
|
glutReshapeFunc( reshape );
|
||||||
|
// reshape the window with the size of the image
|
||||||
|
glutReshapeWindow( singleSize.width, singleSize.height );
|
||||||
|
glutDisplayFunc( displayFunc );
|
||||||
|
|
||||||
|
glInit( );
|
||||||
|
|
||||||
|
gFinished = false;
|
||||||
|
|
||||||
|
while( !gFinished )
|
||||||
|
{
|
||||||
|
|
||||||
|
if( !stop )
|
||||||
|
{
|
||||||
|
Mat view0;
|
||||||
|
capture >> view0;
|
||||||
|
|
||||||
|
// get a copy of the frame
|
||||||
|
if( view0.empty( ) )
|
||||||
|
{
|
||||||
|
cerr << "no more images available" << endl;
|
||||||
|
gFinished = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// undistort( view0, gResultImage, cam.matK, cam.distCoeff );
|
||||||
|
|
||||||
|
// process the image
|
||||||
|
if( tracker.process( view0, cameraPose, cam, boardSize, pattern ) )
|
||||||
|
{
|
||||||
|
Mat temp;
|
||||||
|
cameraPose.convertTo( temp, CV_32F );
|
||||||
|
PRINTVAR( temp );
|
||||||
|
temp.copyTo( dummyMatrix.rowRange( 0, 3 ) );
|
||||||
|
PRINTVAR( dummyMatrix );
|
||||||
|
// gModelViewMatrix = (float*) Mat(temp.t()).data;
|
||||||
|
gModelViewMatrix = ( float* ) Mat( dummyMatrix.t( ) ).data;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
view0.copyTo( gResultImage );
|
||||||
|
// gModelViewMatrix = (float*) Mat(dummyMatrix.t()).data;
|
||||||
|
|
||||||
|
// cout << endl << endl << "****************** frame " << frameNumber << " ******************" << endl;
|
||||||
|
|
||||||
|
++frameNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
// update the texture to be displayed in OPENGL
|
||||||
|
updateTexture( );
|
||||||
|
|
||||||
|
// force Opengl to call the displayFunc
|
||||||
|
#if __APPLE__
|
||||||
|
glutCheckLoop( );
|
||||||
|
#else
|
||||||
|
glutMainLoopEvent( );
|
||||||
|
#endif
|
||||||
|
// sleep for 35ms
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(35));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
capture.release( );
|
||||||
|
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display the help for the programm
|
||||||
|
|
||||||
|
void help( const char* programName )
|
||||||
|
{
|
||||||
|
cout << "Detect a chessboard in a given video and visualize a teapot on top of it" << endl
|
||||||
|
<< "Usage: " << programName << endl
|
||||||
|
<< " -w <board_width> # the number of inner corners per one of board dimension" << endl
|
||||||
|
<< " -h <board_height> # the number of inner corners per another board dimension" << endl
|
||||||
|
<< " -c <calib file> # the name of the calibration file" << endl
|
||||||
|
<< " -o <obj file> # the obj file containing the 3D model to display" << endl
|
||||||
|
<< " <video file> # the name of the video file" << endl
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// parse the input command line arguments
|
||||||
|
|
||||||
|
bool parseArgs( int argc, char**argv, Size &boardSize, string &inputFilename, string &calibFile, string &objFile )
|
||||||
|
{
|
||||||
|
// check the minimum number of arguments
|
||||||
|
if( argc < 3 )
|
||||||
|
{
|
||||||
|
help( argv[0] );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Read the input arguments
|
||||||
|
for( int i = 1; i < argc; i++ )
|
||||||
|
{
|
||||||
|
const char* s = argv[i];
|
||||||
|
if( strcmp( s, "-w" ) == 0 )
|
||||||
|
{
|
||||||
|
if( sscanf( argv[++i], "%u", &boardSize.width ) != 1 || boardSize.width <= 0 )
|
||||||
|
{
|
||||||
|
cerr << "Invalid board width" << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( strcmp( s, "-h" ) == 0 )
|
||||||
|
{
|
||||||
|
if( sscanf( argv[++i], "%u", &boardSize.height ) != 1 || boardSize.height <= 0 )
|
||||||
|
{
|
||||||
|
cerr << "Invalid board height" << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( s[0] != '-' )
|
||||||
|
{
|
||||||
|
inputFilename.assign( s );
|
||||||
|
}
|
||||||
|
else if( strcmp( s, "-c" ) == 0 )
|
||||||
|
{
|
||||||
|
if( i + 1 < argc )
|
||||||
|
calibFile.assign( argv[++i] );
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cerr << "Missing argument for option " << s << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( strcmp( s, "-o" ) == 0 )
|
||||||
|
{
|
||||||
|
if( i + 1 < argc )
|
||||||
|
objFile.assign( argv[++i] );
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cerr << "Missing argument for the obj file " << s << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cerr << "Unknown option " << s << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
471
src/tp/videoOGLTeapot.cpp
Normal file
|
@ -0,0 +1,471 @@
|
||||||
|
#include "tracker/Camera.hpp"
|
||||||
|
#include "tracker/ChessboardCameraTracker.hpp"
|
||||||
|
#include "tracker/ChessboardCameraTrackerKLT.hpp"
|
||||||
|
#include "tracker/utility.hpp"
|
||||||
|
|
||||||
|
#include <opencv2/highgui/highgui.hpp>
|
||||||
|
#include <opencv2/calib3d/calib3d.hpp>
|
||||||
|
#include <opencv2/core/core.hpp>
|
||||||
|
#include <opencv2/imgproc/imgproc.hpp>
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#include <OpenGL/gl.h>
|
||||||
|
// #include <OpenGL/glu.h>
|
||||||
|
#include <GLUT/glut.h>
|
||||||
|
#else
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
#include <GL/gl.h>
|
||||||
|
// #include <GL/glu.h>
|
||||||
|
#include <GL/freeglut.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#include <glm.h>
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <chrono>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace cv;
|
||||||
|
|
||||||
|
|
||||||
|
// Display the help for the programm
|
||||||
|
void help( const char* programName );
|
||||||
|
|
||||||
|
// parse the input command line arguments
|
||||||
|
bool parseArgs( int argc, char**argv, Size &boardSize, string &inputFilename, string &calibFile, string &objFile );
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Common globals
|
||||||
|
*/
|
||||||
|
|
||||||
|
int gFinished;
|
||||||
|
|
||||||
|
// the OpenGL reference for the texture to display
|
||||||
|
GLuint gCameraTextureId;
|
||||||
|
|
||||||
|
// the global array containng the explicit modelview matrix
|
||||||
|
const float *gModelViewMatrix;
|
||||||
|
|
||||||
|
// the global array containng the explicit projection matrix
|
||||||
|
float gProjectionMatrix[16] = {0.f};
|
||||||
|
|
||||||
|
// this will physically contain the current frame that is used as texture
|
||||||
|
Mat gResultImage;
|
||||||
|
bool stop = false;
|
||||||
|
|
||||||
|
// the size of the video frame
|
||||||
|
Size singleSize;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// OpenGL initialization
|
||||||
|
|
||||||
|
void glInit( )
|
||||||
|
{
|
||||||
|
//******************************************************************
|
||||||
|
// enable the depth test
|
||||||
|
//******************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
glEnable( GL_TEXTURE_2D );
|
||||||
|
glGenTextures( 1, &gCameraTextureId );
|
||||||
|
|
||||||
|
//******************************************************************
|
||||||
|
// set the Gouraud shading
|
||||||
|
//******************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************
|
||||||
|
// set the LIGHT0 as a simple white, directional light with direction [1,2,-2]
|
||||||
|
//******************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************
|
||||||
|
// set the material properties for the teapot
|
||||||
|
// choose the values for ambient, diffuse, specular and shininess
|
||||||
|
// as you prefer. The teapot in the figure has is mainly gray with
|
||||||
|
// ambient 0.7, diffuse 0.8, specular 1.0 and shininess 100
|
||||||
|
//******************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************
|
||||||
|
// enable the lights
|
||||||
|
//******************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************
|
||||||
|
// set the opengl projection matrix to gProjectionMatrix:
|
||||||
|
// load the identity and multiply it by gProjectionMatrix using glMultMatrixf
|
||||||
|
//******************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************
|
||||||
|
// set back the modelview mode
|
||||||
|
//******************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Updates texture handle gCameraTextureId with OpenCV image in cv::Mat from gResultImage
|
||||||
|
|
||||||
|
void updateTexture( )
|
||||||
|
{
|
||||||
|
glBindTexture( GL_TEXTURE_2D, gCameraTextureId );
|
||||||
|
|
||||||
|
// set texture filter to linear - we do not build mipmaps for speed
|
||||||
|
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
|
||||||
|
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
|
||||||
|
|
||||||
|
// create the texture from OpenCV image data
|
||||||
|
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB8, singleSize.width, singleSize.height, 0,
|
||||||
|
#if _WIN32
|
||||||
|
GL_BGR_EXT,
|
||||||
|
#else
|
||||||
|
GL_BGR,
|
||||||
|
#endif
|
||||||
|
GL_UNSIGNED_BYTE, gResultImage.data );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw the background from the camera image
|
||||||
|
*/
|
||||||
|
void drawBackground( )
|
||||||
|
{
|
||||||
|
// set up the modelview matrix so that the view is between [-1,-1] and [1,1]
|
||||||
|
glMatrixMode( GL_PROJECTION );
|
||||||
|
glPushMatrix( );
|
||||||
|
glLoadIdentity( );
|
||||||
|
glOrtho( -1, 1, -1, 1, 0, 1 );
|
||||||
|
glMatrixMode( GL_MODELVIEW );
|
||||||
|
glLoadIdentity( );
|
||||||
|
|
||||||
|
// draw the quad textured with the camera image
|
||||||
|
glBindTexture( GL_TEXTURE_2D, gCameraTextureId );
|
||||||
|
glBegin( GL_QUADS );
|
||||||
|
glTexCoord2f( 0, 1 );
|
||||||
|
glVertex2f( -1, -1 );
|
||||||
|
glTexCoord2f( 0, 0 );
|
||||||
|
glVertex2f( -1, 1 );
|
||||||
|
glTexCoord2f( 1, 0 );
|
||||||
|
glVertex2f( 1, 1 );
|
||||||
|
glTexCoord2f( 1, 1 );
|
||||||
|
glVertex2f( 1, -1 );
|
||||||
|
glEnd( );
|
||||||
|
|
||||||
|
// reset the projection matrix
|
||||||
|
glMatrixMode( GL_PROJECTION );
|
||||||
|
glPopMatrix( );
|
||||||
|
glMatrixMode( GL_MODELVIEW );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** OpenGL display callback */
|
||||||
|
void displayFunc( )
|
||||||
|
{
|
||||||
|
glClear( GL_COLOR_BUFFER_BIT );
|
||||||
|
|
||||||
|
// render the background image from camera texture
|
||||||
|
glEnable( GL_TEXTURE_2D );
|
||||||
|
//******************************************************************
|
||||||
|
// disable the lighting before drawing the background
|
||||||
|
//******************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
drawBackground( );
|
||||||
|
|
||||||
|
// clear th depth buffer bit so that the background is overdrawn
|
||||||
|
glClear( GL_DEPTH_BUFFER_BIT );
|
||||||
|
|
||||||
|
// everything will be white
|
||||||
|
glColor3f( 1, 1, 1 );
|
||||||
|
|
||||||
|
// start with fresh modelview matrix and apply the transform of the plane
|
||||||
|
glMatrixMode( GL_MODELVIEW );
|
||||||
|
glLoadIdentity( );
|
||||||
|
|
||||||
|
//******************************************************************
|
||||||
|
// apply the modelview matrix gModelViewMatrix using glMultMatrixf
|
||||||
|
//******************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
// enable the texture for a nice effect ;)
|
||||||
|
glDisable( GL_TEXTURE_2D );
|
||||||
|
|
||||||
|
//******************************************************************
|
||||||
|
// enable the lighting before drawing the teapot/the object
|
||||||
|
//******************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************
|
||||||
|
// draw the teapot (the solid version)
|
||||||
|
//******************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
glutSwapBuffers( );
|
||||||
|
glutPostRedisplay( );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Windows resize callback
|
||||||
|
|
||||||
|
void reshape( GLint width, GLint height )
|
||||||
|
{
|
||||||
|
glViewport( 0, 0, width, height );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keyboard callback
|
||||||
|
|
||||||
|
void keyFunc( unsigned char key, int x, int y )
|
||||||
|
{
|
||||||
|
cout << key << " pressed" << endl;
|
||||||
|
|
||||||
|
switch( key )
|
||||||
|
{
|
||||||
|
case 27:
|
||||||
|
gFinished = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 's':
|
||||||
|
stop = !stop;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main( int argc, char** argv )
|
||||||
|
{
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
/* VARIABLES TO USE */
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
// it will contain the size in terms of corners (width X height) of the chessboard
|
||||||
|
Size boardSize;
|
||||||
|
|
||||||
|
// Default pattern is chessboard
|
||||||
|
Pattern pattern = CHESSBOARD;
|
||||||
|
|
||||||
|
// the camera
|
||||||
|
Camera cam;
|
||||||
|
|
||||||
|
// the filenames for the video and the calibration
|
||||||
|
string videoFilename, calibFilename, objFile;
|
||||||
|
int imgInType;
|
||||||
|
|
||||||
|
long frameNumber = 0;
|
||||||
|
|
||||||
|
// the video capture
|
||||||
|
VideoCapture capture;
|
||||||
|
|
||||||
|
// the video capture a dummy matrix used to show the teapot in a fix position of the image
|
||||||
|
Mat dummyMatrix = Mat::eye( 4, 4, CV_32F );
|
||||||
|
dummyMatrix.at<float>( 1, 1 ) = -1;
|
||||||
|
dummyMatrix.at<float>( 2, 3 ) = 50;
|
||||||
|
|
||||||
|
cout << dummyMatrix << endl;
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
/* READ THE INPUT PARAMETERS - DO NOT MODIFY */
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
if( !parseArgs( argc, argv, boardSize, videoFilename, calibFilename, objFile ) )
|
||||||
|
{
|
||||||
|
cerr << "Aborting..." << endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//******************************************************************
|
||||||
|
// init the Camera loading the calibration parameters
|
||||||
|
//******************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************
|
||||||
|
// get the corresponding projection matrix in OGL format
|
||||||
|
//******************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
capture.open( videoFilename );
|
||||||
|
|
||||||
|
// check if capture has opened the video
|
||||||
|
if( !capture.isOpened( ) )
|
||||||
|
{
|
||||||
|
cerr << "Could not open video file " << videoFilename << endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
if( !getVideoSizeAndType(videoFilename, capture, singleSize, imgInType ) )
|
||||||
|
{
|
||||||
|
cerr << "Something wrong while checking the size and type of the video " << videoFilename << endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gResultImage = Mat( singleSize, imgInType );
|
||||||
|
|
||||||
|
|
||||||
|
// Setup GLUT rendering and callbacks
|
||||||
|
glutInit( &argc, argv );
|
||||||
|
glutCreateWindow( "Main" );
|
||||||
|
glutKeyboardFunc( keyFunc );
|
||||||
|
glutReshapeFunc( reshape );
|
||||||
|
// reshape the window with the size of the image
|
||||||
|
glutReshapeWindow( singleSize.width, singleSize.height );
|
||||||
|
glutDisplayFunc( displayFunc );
|
||||||
|
|
||||||
|
glInit( );
|
||||||
|
|
||||||
|
gFinished = false;
|
||||||
|
|
||||||
|
while( !gFinished )
|
||||||
|
{
|
||||||
|
|
||||||
|
if( !stop )
|
||||||
|
{
|
||||||
|
Mat view0;
|
||||||
|
capture >> view0;
|
||||||
|
|
||||||
|
// get a copy of the frame
|
||||||
|
if( view0.empty( ) )
|
||||||
|
{
|
||||||
|
cerr << "no more images available" << endl;
|
||||||
|
gFinished = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
view0.copyTo( gResultImage );
|
||||||
|
|
||||||
|
// set the gModelViewMatrix with the content of the dummy matrix
|
||||||
|
// OpenGL uses a column-major order for storing the matrix element, while OpenCV uses
|
||||||
|
// a row major order for storing the elements. Hence we need first to convert the dummy matrix
|
||||||
|
// to its transpose and only then pass the data pointer to gModelViewMatrix
|
||||||
|
gModelViewMatrix = ( float* ) Mat( dummyMatrix.t( ) ).data;
|
||||||
|
|
||||||
|
cout << endl << endl << "****************** frame " << frameNumber << " ******************" << endl;
|
||||||
|
|
||||||
|
++frameNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
// update the texture to be displayed in OPENGL
|
||||||
|
updateTexture( );
|
||||||
|
|
||||||
|
// force Opengl to call the displayFunc
|
||||||
|
#if __APPLE__
|
||||||
|
glutCheckLoop( );
|
||||||
|
#else
|
||||||
|
glutMainLoopEvent( );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// sleep for 35ms
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(35));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
capture.release( );
|
||||||
|
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display the help for the programm
|
||||||
|
|
||||||
|
void help( const char* programName )
|
||||||
|
{
|
||||||
|
cout << "Detect a chessboard in a given video and visualize a teapot on top of it" << endl
|
||||||
|
<< "Usage: " << programName << endl
|
||||||
|
<< " -w <board_width> # the number of inner corners per one of board dimension" << endl
|
||||||
|
<< " -h <board_height> # the number of inner corners per another board dimension" << endl
|
||||||
|
<< " -c <calib file> # the name of the calibration file" << endl
|
||||||
|
<< " [-o <obj file>] # the optional obj file containing the 3D model to display" << endl
|
||||||
|
<< " <video file> # the name of the video file" << endl
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// parse the input command line arguments
|
||||||
|
|
||||||
|
bool parseArgs( int argc, char**argv, Size &boardSize, string &inputFilename, string &calibFile, string &objFile )
|
||||||
|
{
|
||||||
|
// check the minimum number of arguments
|
||||||
|
if( argc < 3 )
|
||||||
|
{
|
||||||
|
help( argv[0] );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Read the input arguments
|
||||||
|
for( int i = 1; i < argc; i++ )
|
||||||
|
{
|
||||||
|
const char* s = argv[i];
|
||||||
|
|
||||||
|
if( strcmp( s, "-w" ) == 0 )
|
||||||
|
{
|
||||||
|
if( sscanf( argv[++i], "%u", &boardSize.width ) != 1 || boardSize.width <= 0 )
|
||||||
|
{
|
||||||
|
cerr << "Invalid board width" << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( strcmp( s, "-h" ) == 0 )
|
||||||
|
{
|
||||||
|
if( sscanf( argv[++i], "%u", &boardSize.height ) != 1 || boardSize.height <= 0 )
|
||||||
|
{
|
||||||
|
cerr << "Invalid board height" << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( s[0] != '-' )
|
||||||
|
{
|
||||||
|
inputFilename.assign( s );
|
||||||
|
}
|
||||||
|
else if( strcmp( s, "-c" ) == 0 )
|
||||||
|
{
|
||||||
|
if( i + 1 < argc )
|
||||||
|
calibFile.assign( argv[++i] );
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cerr << "Missing argument for option " << s << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( strcmp( s, "-o" ) == 0 )
|
||||||
|
{
|
||||||
|
if( i + 1 < argc )
|
||||||
|
objFile.assign( argv[++i] );
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cerr << "Missing argument for the obj file " << s << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cerr << "Unknown option " << s << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
553
src/tp/videoOGLTracking.cpp
Normal file
|
@ -0,0 +1,553 @@
|
||||||
|
#include "tracker/Camera.hpp"
|
||||||
|
#include "tracker/ChessboardCameraTracker.hpp"
|
||||||
|
#include "tracker/ChessboardCameraTrackerKLT.hpp"
|
||||||
|
#include "tracker/utility.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
#include <opencv2/highgui/highgui.hpp>
|
||||||
|
#include <opencv2/calib3d/calib3d.hpp>
|
||||||
|
#include <opencv2/core/core.hpp>
|
||||||
|
#include <opencv2/imgproc/imgproc.hpp>
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#include <OpenGL/gl.h>
|
||||||
|
// #include <OpenGL/glu.h>
|
||||||
|
#include <GLUT/glut.h>
|
||||||
|
#else
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
#include <GL/gl.h>
|
||||||
|
// #include <GL/glu.h>
|
||||||
|
#include <GL/freeglut.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#include <glm.h>
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <chrono>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace cv;
|
||||||
|
|
||||||
|
// Display the help for the program
|
||||||
|
void help( const char* programName );
|
||||||
|
|
||||||
|
// parse the input command line arguments
|
||||||
|
bool parseArgs( int argc, char**argv, Size &boardSize, string &inputFilename, string &calibFile, string &objFile );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Common globals
|
||||||
|
*/
|
||||||
|
|
||||||
|
int gFinished;
|
||||||
|
|
||||||
|
// the OpenGL reference for the texture to display
|
||||||
|
GLuint gCameraTextureId;
|
||||||
|
// the global array containg the explicit modelview matrix
|
||||||
|
const float *gModelViewMatrix;
|
||||||
|
// the global array containg the explicit projection matrix
|
||||||
|
float gProjectionMatrix[16] = {0.f};
|
||||||
|
// this will physically contain the current frame that is used as texture
|
||||||
|
Mat gResultImage;
|
||||||
|
bool stop = false;
|
||||||
|
|
||||||
|
// the size of the video frame
|
||||||
|
Size singleSize;
|
||||||
|
|
||||||
|
void DrawAxis( float scale )
|
||||||
|
{
|
||||||
|
glPushMatrix( );
|
||||||
|
glDisable( GL_LIGHTING );
|
||||||
|
// glDisable(GL_TEXTURE_2D);
|
||||||
|
glScalef( scale, scale, scale );
|
||||||
|
glLineWidth( 4.0 );
|
||||||
|
|
||||||
|
glBegin( GL_LINES );
|
||||||
|
|
||||||
|
glColor3f( 1.f, 0.f, 0.f);
|
||||||
|
glVertex3f( .8f, .05f, 0.f);
|
||||||
|
glVertex3f( 1.f, .25f, 0.f); /* Letter X */
|
||||||
|
glVertex3f( .8f, .25f, 0.f);
|
||||||
|
glVertex3f( 1.f, .05f, 0.f);
|
||||||
|
glVertex3f( 0.f, 0.f, 0.f);
|
||||||
|
glVertex3f( 1.f, 0.f, 0.f); /* X axis */
|
||||||
|
|
||||||
|
glColor3f( 0.f, 1.f, 0.f);
|
||||||
|
glVertex3f( 0.f, 0.f, 0.f);
|
||||||
|
glVertex3f( 0.f, 1.f, 0.f); /* Y axis */
|
||||||
|
|
||||||
|
glColor3f( 0.f, 0.f, 1.f );
|
||||||
|
glVertex3f( 0.f, 0.f, 0.f);
|
||||||
|
glVertex3f( 0.f, 0.f, 1.f ); /* Z axis */
|
||||||
|
glEnd( );
|
||||||
|
// if (lighting)
|
||||||
|
glEnable( GL_LIGHTING );
|
||||||
|
// if (lighting)
|
||||||
|
// glEnable(GL_TEXTURE_2D);
|
||||||
|
glColor3f( 1.f, 1.f, 1.f );
|
||||||
|
glPopMatrix( );
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawPoints( float scale )
|
||||||
|
{
|
||||||
|
glPushMatrix( );
|
||||||
|
glDisable( GL_LIGHTING );
|
||||||
|
// glDisable(GL_TEXTURE_2D);
|
||||||
|
glScalef( scale, scale, scale );
|
||||||
|
glPointSize( 5 );
|
||||||
|
glBegin( GL_POINTS );
|
||||||
|
|
||||||
|
for( int i = 0; i < 6; i++ )
|
||||||
|
{
|
||||||
|
|
||||||
|
glColor3f( 1.f, ( float ) 40.0f * i / 255.0f, ( float ) 40.0f * i / 255.0f );
|
||||||
|
for( int j = 0; j < 9; j++ )
|
||||||
|
glVertex3f( float(j), float(i), 0.f );
|
||||||
|
}
|
||||||
|
|
||||||
|
glEnd( );
|
||||||
|
// if (lighting)
|
||||||
|
glEnable( GL_LIGHTING );
|
||||||
|
// if (lighting)
|
||||||
|
// glEnable(GL_TEXTURE_2D);
|
||||||
|
glColor3f( 1.f, 1.f, 1.f );
|
||||||
|
glPopMatrix( );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OpenGL initialization
|
||||||
|
*/
|
||||||
|
void glInit( )
|
||||||
|
{
|
||||||
|
|
||||||
|
//******************************************************************
|
||||||
|
// enable the depth test
|
||||||
|
//******************************************************************
|
||||||
|
glEnable( GL_DEPTH_TEST );
|
||||||
|
glDepthFunc( GL_LESS );
|
||||||
|
|
||||||
|
glEnable( GL_TEXTURE_2D );
|
||||||
|
glGenTextures( 1, &gCameraTextureId );
|
||||||
|
|
||||||
|
//******************************************************************
|
||||||
|
// set the Gouraud shading
|
||||||
|
//******************************************************************
|
||||||
|
glShadeModel( GL_SMOOTH );
|
||||||
|
|
||||||
|
//******************************************************************
|
||||||
|
// set the LIGHT0 as a simple white, directional light with direction [1,2,-2]
|
||||||
|
//******************************************************************
|
||||||
|
GLfloat gLightPos[] = {100.f, 200.f, -200.f, 0.0};
|
||||||
|
glLightfv( GL_LIGHT0, GL_POSITION, gLightPos );
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************
|
||||||
|
// set the material properties for the teapot
|
||||||
|
// choose the values for ambient, diffuse, specular and shininess
|
||||||
|
// as you prefer. The teapot in the figure has is mainly gray with
|
||||||
|
// ambient 0.7, diffuse 0.8, specular 1.f and shininess 100
|
||||||
|
//******************************************************************
|
||||||
|
GLfloat mat_ambient[] = {0.7, 0.7, 0.7, 1.f};
|
||||||
|
GLfloat mat_diffuse[] = {0.8, 0.8, 0.8, 1.f};
|
||||||
|
GLfloat mat_specular[] = {1.f, 1.f, 1.f, 1.f};
|
||||||
|
GLfloat high_shininess[] = {100.0};
|
||||||
|
|
||||||
|
glMaterialfv( GL_FRONT, GL_AMBIENT, mat_ambient );
|
||||||
|
glMaterialfv( GL_FRONT, GL_DIFFUSE, mat_diffuse );
|
||||||
|
glMaterialfv( GL_FRONT, GL_SPECULAR, mat_specular );
|
||||||
|
glMaterialfv( GL_FRONT, GL_SHININESS, high_shininess );
|
||||||
|
|
||||||
|
//******************************************************************
|
||||||
|
// enable the lights
|
||||||
|
//******************************************************************
|
||||||
|
glEnable( GL_LIGHTING );
|
||||||
|
glEnable( GL_LIGHT0 );
|
||||||
|
|
||||||
|
//******************************************************************
|
||||||
|
// set the opengl projection matrix to gProjectionMatrix:
|
||||||
|
// load the identity and multiply it by gProjectionMatrix using glMultMatrixf
|
||||||
|
//******************************************************************
|
||||||
|
glMatrixMode( GL_PROJECTION );
|
||||||
|
glLoadIdentity( );
|
||||||
|
glMultMatrixf( gProjectionMatrix );
|
||||||
|
|
||||||
|
//******************************************************************
|
||||||
|
// set back the modelview mode
|
||||||
|
//******************************************************************
|
||||||
|
glMatrixMode( GL_MODELVIEW );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Updates texture handle gCameraTextureId with OpenCV image in cv::Mat from gResultImage
|
||||||
|
|
||||||
|
void updateTexture( )
|
||||||
|
{
|
||||||
|
glBindTexture( GL_TEXTURE_2D, gCameraTextureId );
|
||||||
|
|
||||||
|
// set texture filter to linear - we do not build mipmaps for speed
|
||||||
|
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
|
||||||
|
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
|
||||||
|
|
||||||
|
// create the texture from OpenCV image data
|
||||||
|
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB8, singleSize.width, singleSize.height, 0,
|
||||||
|
#if _WIN32
|
||||||
|
GL_BGR_EXT,
|
||||||
|
#else
|
||||||
|
GL_BGR,
|
||||||
|
#endif
|
||||||
|
GL_UNSIGNED_BYTE, gResultImage.data );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw the background from the camera image
|
||||||
|
*/
|
||||||
|
void drawBackground( )
|
||||||
|
{
|
||||||
|
// set up the modelview matrix so that the view is between [-1,-1] and [1,1]
|
||||||
|
glMatrixMode( GL_PROJECTION );
|
||||||
|
glPushMatrix( );
|
||||||
|
glLoadIdentity( );
|
||||||
|
glOrtho( -1, 1, -1, 1, 0, 1 );
|
||||||
|
glMatrixMode( GL_MODELVIEW );
|
||||||
|
glLoadIdentity( );
|
||||||
|
|
||||||
|
// draw the quad textured with the camera image
|
||||||
|
glBindTexture( GL_TEXTURE_2D, gCameraTextureId );
|
||||||
|
glBegin( GL_QUADS );
|
||||||
|
glTexCoord2f( 0, 1 );
|
||||||
|
glVertex2f( -1, -1 );
|
||||||
|
glTexCoord2f( 0, 0 );
|
||||||
|
glVertex2f( -1, 1 );
|
||||||
|
glTexCoord2f( 1, 0 );
|
||||||
|
glVertex2f( 1, 1 );
|
||||||
|
glTexCoord2f( 1, 1 );
|
||||||
|
glVertex2f( 1, -1 );
|
||||||
|
glEnd( );
|
||||||
|
|
||||||
|
// reset the projection matrix
|
||||||
|
glMatrixMode( GL_PROJECTION );
|
||||||
|
glPopMatrix( );
|
||||||
|
glMatrixMode( GL_MODELVIEW );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** OpenGL display callback */
|
||||||
|
void displayFunc( )
|
||||||
|
{
|
||||||
|
glClear( GL_COLOR_BUFFER_BIT );
|
||||||
|
|
||||||
|
// render the background image from camera texture
|
||||||
|
glEnable( GL_TEXTURE_2D );
|
||||||
|
//******************************************************************
|
||||||
|
// disable the lighting before drawing the background
|
||||||
|
//******************************************************************
|
||||||
|
glDisable( GL_LIGHTING );
|
||||||
|
|
||||||
|
drawBackground( );
|
||||||
|
|
||||||
|
// clear th depth buffer bit so that the background is overdrawn
|
||||||
|
glClear( GL_DEPTH_BUFFER_BIT );
|
||||||
|
|
||||||
|
// everything will be white
|
||||||
|
glColor3f( 1, 1, 1 );
|
||||||
|
|
||||||
|
// start with fresh modelview matrix and apply the transform of the plane
|
||||||
|
glMatrixMode( GL_MODELVIEW );
|
||||||
|
glLoadIdentity( );
|
||||||
|
//******************************************************************
|
||||||
|
// apply the modelview matrix gModelViewMatrix using glMultMatrixf
|
||||||
|
//******************************************************************
|
||||||
|
glMultMatrixf( gModelViewMatrix );
|
||||||
|
// DrawPoints( 25 );
|
||||||
|
glRotatef( -90, 1, 0, 0 );
|
||||||
|
|
||||||
|
|
||||||
|
// enable the texture for a nice effect ;)
|
||||||
|
glDisable( GL_TEXTURE_2D );
|
||||||
|
//******************************************************************
|
||||||
|
// enable the lighting before drawing the teapot/the object
|
||||||
|
//******************************************************************
|
||||||
|
glEnable( GL_LIGHTING );
|
||||||
|
|
||||||
|
// DrawAxis( 100 );
|
||||||
|
|
||||||
|
glTranslatef( 0, 50, 0 );
|
||||||
|
//******************************************************************
|
||||||
|
// draw the teapot (the solid version)
|
||||||
|
//******************************************************************
|
||||||
|
glutSolidTeapot( 45 );
|
||||||
|
|
||||||
|
glutSwapBuffers( );
|
||||||
|
glutPostRedisplay( );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Windows resize callback
|
||||||
|
|
||||||
|
void reshape( GLint width, GLint height )
|
||||||
|
{
|
||||||
|
glViewport( 0, 0, width, height );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keyboard callback
|
||||||
|
|
||||||
|
void keyFunc( unsigned char key, int x, int y )
|
||||||
|
{
|
||||||
|
cout << key << " pressed" << endl;
|
||||||
|
|
||||||
|
switch( key )
|
||||||
|
{
|
||||||
|
case 27:
|
||||||
|
gFinished = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 's':
|
||||||
|
stop = !stop;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main( int argc, char** argv )
|
||||||
|
{
|
||||||
|
string videoFilename, calibFilename, objFile;
|
||||||
|
int imgInType;
|
||||||
|
|
||||||
|
long frameNumber = 0;
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
/* VARIABLES TO USE */
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
// it will contain the size in terms of corners (width X height) of the chessboard
|
||||||
|
Size boardSize;
|
||||||
|
|
||||||
|
// Default pattern is chessboard
|
||||||
|
Pattern pattern = CHESSBOARD;
|
||||||
|
|
||||||
|
// Used to load the video and get the frames
|
||||||
|
VideoCapture capture;
|
||||||
|
|
||||||
|
// Camera object containing the calibration parameters
|
||||||
|
Camera cam;
|
||||||
|
|
||||||
|
// Camera Tracker object
|
||||||
|
ChessboardCameraTrackerKLT tracker;
|
||||||
|
|
||||||
|
// 3x4 camera pose matrix [R t]
|
||||||
|
Mat cameraPose;
|
||||||
|
|
||||||
|
// Mat dummyMatrix = Mat::eye( 4, 4, CV_32F );
|
||||||
|
// dummyMatrix.at<float>(0, 3) = 102;
|
||||||
|
// dummyMatrix.at<float>(1, 3) = 46;
|
||||||
|
// dummyMatrix.at<float>(2, 3) = 217;
|
||||||
|
// Mat dummyMatrix = (Mat_<float>(4,4) << -0.90750873, -0.0011025554, 0, 125.93854, 0.39205164, -0.0022058936, 0.00093782519, 43.355019, -0.15074302, 0.00085026468, 0.0024341263, 384.71075, 0,0,0,1);
|
||||||
|
Mat dummyMatrix = ( Mat_<float>( 4, 4 ) << 0.4830, -0.8756, 0.0077, 125.93854, 0.8365, 0.4588, -0.2996, 43.355019, 0.2588, 0.1511, 0.9540, 384.71075, 0, 0, 0, 1 );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cout << dummyMatrix << endl;
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
/* READ THE INPUT PARAMETERS - DO NOT MODIFY */
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
if( !parseArgs( argc, argv, boardSize, videoFilename, calibFilename, objFile ) )
|
||||||
|
{
|
||||||
|
cerr << "Aborting..." << endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//******************************************************************
|
||||||
|
// init the Camera loading the calibration parameters
|
||||||
|
//******************************************************************
|
||||||
|
cam.init( calibFilename );
|
||||||
|
|
||||||
|
//******************************************************************
|
||||||
|
// get the corresponding projection matrix in OGL format
|
||||||
|
//******************************************************************
|
||||||
|
cam.getOGLProjectionMatrix( gProjectionMatrix, 10.f, 10000.f );
|
||||||
|
|
||||||
|
|
||||||
|
capture.open( videoFilename );
|
||||||
|
|
||||||
|
// check if capture has opened the video
|
||||||
|
if( !capture.isOpened( ) )
|
||||||
|
{
|
||||||
|
cerr << "Could not open video file " << videoFilename << endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
if( !getVideoSizeAndType(videoFilename, capture, singleSize, imgInType ) )
|
||||||
|
{
|
||||||
|
cerr << "Something wrong while checking the size and type of the video " << videoFilename << endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gResultImage = Mat( singleSize, imgInType );
|
||||||
|
|
||||||
|
|
||||||
|
// Setup GLUT rendering and callbacks
|
||||||
|
glutInit( &argc, argv );
|
||||||
|
glutCreateWindow( "Main" );
|
||||||
|
glutKeyboardFunc( keyFunc );
|
||||||
|
glutReshapeFunc( reshape );
|
||||||
|
// reshape the window with the size of the image
|
||||||
|
glutReshapeWindow( singleSize.width, singleSize.height );
|
||||||
|
glutDisplayFunc( displayFunc );
|
||||||
|
|
||||||
|
glInit( );
|
||||||
|
|
||||||
|
gFinished = false;
|
||||||
|
|
||||||
|
while( !gFinished )
|
||||||
|
{
|
||||||
|
|
||||||
|
if( !stop )
|
||||||
|
{
|
||||||
|
Mat view0;
|
||||||
|
capture >> view0;
|
||||||
|
|
||||||
|
// get a copy of the frame
|
||||||
|
if( view0.empty( ) )
|
||||||
|
{
|
||||||
|
cerr << "no more images available" << endl;
|
||||||
|
gFinished = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// undistort( view0, gResultImage, cam.matK, cam.distCoeff );
|
||||||
|
|
||||||
|
// process the image
|
||||||
|
if( tracker.process( view0, cameraPose, cam, boardSize, pattern ) )
|
||||||
|
{
|
||||||
|
Mat temp;
|
||||||
|
cameraPose.convertTo( temp, CV_32F );
|
||||||
|
PRINTVAR( temp );
|
||||||
|
#if CV_MINOR_VERSION < 4
|
||||||
|
Mat fooMat = dummyMatrix.rowRange( 0, 3 );
|
||||||
|
temp.copyTo( fooMat );
|
||||||
|
#else
|
||||||
|
temp.copyTo( dummyMatrix.rowRange( 0, 3 ) );
|
||||||
|
#endif
|
||||||
|
PRINTVAR( dummyMatrix );
|
||||||
|
// gModelViewMatrix = (float*) Mat(temp.t()).data;
|
||||||
|
gModelViewMatrix = ( float* ) Mat( dummyMatrix.t( ) ).data;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
view0.copyTo( gResultImage );
|
||||||
|
// gModelViewMatrix = (float*) Mat(dummyMatrix.t()).data;
|
||||||
|
|
||||||
|
// cout << endl << endl << "****************** frame " << frameNumber << " ******************" << endl;
|
||||||
|
|
||||||
|
++frameNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
// update the texture to be displayed in OPENGL
|
||||||
|
updateTexture( );
|
||||||
|
|
||||||
|
// force Opengl to call the displayFunc
|
||||||
|
#if __APPLE__
|
||||||
|
glutCheckLoop( );
|
||||||
|
#else
|
||||||
|
glutMainLoopEvent( );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// sleep for 35ms
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(35));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
capture.release( );
|
||||||
|
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display the help for the programm
|
||||||
|
|
||||||
|
void help( const char* programName )
|
||||||
|
{
|
||||||
|
cout << "Detect a chessboard in a given video and visualize a teapot on top of it" << endl
|
||||||
|
<< "Usage: " << programName << endl
|
||||||
|
<< " -w <board_width> # the number of inner corners per one of board dimension" << endl
|
||||||
|
<< " -h <board_height> # the number of inner corners per another board dimension" << endl
|
||||||
|
<< " -c <calib file> # the name of the calibration file" << endl
|
||||||
|
<< " -o <obj file> # the obj file containing the 3D model to display" << endl
|
||||||
|
<< " <video file> # the name of the video file" << endl
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// parse the input command line arguments
|
||||||
|
|
||||||
|
bool parseArgs( int argc, char**argv, Size &boardSize, string &inputFilename, string &calibFile, string &objFile )
|
||||||
|
{
|
||||||
|
// check the minimum number of arguments
|
||||||
|
if( argc < 3 )
|
||||||
|
{
|
||||||
|
help( argv[0] );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Read the input arguments
|
||||||
|
for( int i = 1; i < argc; i++ )
|
||||||
|
{
|
||||||
|
const char* s = argv[i];
|
||||||
|
if( strcmp( s, "-w" ) == 0 )
|
||||||
|
{
|
||||||
|
if( sscanf( argv[++i], "%u", &boardSize.width ) != 1 || boardSize.width <= 0 )
|
||||||
|
{
|
||||||
|
cerr << "Invalid board width" << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( strcmp( s, "-h" ) == 0 )
|
||||||
|
{
|
||||||
|
if( sscanf( argv[++i], "%u", &boardSize.height ) != 1 || boardSize.height <= 0 )
|
||||||
|
{
|
||||||
|
cerr << "Invalid board height" << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( s[0] != '-' )
|
||||||
|
{
|
||||||
|
inputFilename.assign( s );
|
||||||
|
}
|
||||||
|
else if( strcmp( s, "-c" ) == 0 )
|
||||||
|
{
|
||||||
|
if( i + 1 < argc )
|
||||||
|
calibFile.assign( argv[++i] );
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cerr << "Missing argument for option " << s << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( strcmp( s, "-o" ) == 0 )
|
||||||
|
{
|
||||||
|
if( i + 1 < argc )
|
||||||
|
objFile.assign( argv[++i] );
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cerr << "Missing argument for the obj file " << s << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cerr << "Unknown option " << s << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
27
src/tutorials/CMakeLists.txt
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
#########################################################
|
||||||
|
#
|
||||||
|
# OPENCV TUTORIALS
|
||||||
|
#
|
||||||
|
#########################################################
|
||||||
|
|
||||||
|
|
||||||
|
add_executable( file_input_output file_input_output.cpp )
|
||||||
|
target_link_libraries( file_input_output ${OpenCV_LIBS} )
|
||||||
|
|
||||||
|
add_executable( load_and_display_video load_and_display_video.cpp )
|
||||||
|
target_link_libraries( load_and_display_video ${OpenCV_LIBS} )
|
||||||
|
|
||||||
|
add_executable( load_and_display_webcam load_and_display_webcam.cpp )
|
||||||
|
target_link_libraries( load_and_display_webcam ${OpenCV_LIBS} )
|
||||||
|
|
||||||
|
add_executable( display_image display_image.cpp )
|
||||||
|
target_link_libraries( display_image ${OpenCV_LIBS} )
|
||||||
|
|
||||||
|
add_executable( load_modify_image load_modify_image.cpp )
|
||||||
|
target_link_libraries( load_modify_image ${OpenCV_LIBS} )
|
||||||
|
|
||||||
|
add_executable( mat_the_basic_image_container mat_the_basic_image_container.cpp )
|
||||||
|
target_link_libraries( mat_the_basic_image_container ${OpenCV_LIBS} )
|
||||||
|
|
||||||
|
|
||||||
|
add_custom_target( tutorials DEPENDS file_input_output load_and_display_video load_modify_image display_image mat_the_basic_image_container )
|
31
src/tutorials/display_image.cpp
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#include <opencv2/core/core.hpp>
|
||||||
|
#include <opencv2/highgui/highgui.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
using namespace cv;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int main( int argc, char** argv )
|
||||||
|
{
|
||||||
|
if( argc != 2 )
|
||||||
|
{
|
||||||
|
cout << " Usage: display_image ImageToLoadAndDisplay" << endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mat image;
|
||||||
|
|
||||||
|
image = imread( argv[1], CV_LOAD_IMAGE_COLOR ); // Read the file
|
||||||
|
|
||||||
|
if( image.empty( ) ) // Check for invalid input
|
||||||
|
{
|
||||||
|
cout << "Could not open or find the image" << std::endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
namedWindow( "Display window", CV_WINDOW_AUTOSIZE ); // Create a window for display.
|
||||||
|
imshow( "Display window", image ); // Show our image inside it.
|
||||||
|
|
||||||
|
waitKey( 0 ); // Wait for a keystroke in the window
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
72
src/tutorials/file_input_output.cpp
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
#include <opencv2/core/core.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
using namespace cv;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
static void help( char** av )
|
||||||
|
{
|
||||||
|
cout << endl
|
||||||
|
<< av[0] << " shows the usage of the OpenCV serialization functionality." << endl
|
||||||
|
<< "usage: " << endl
|
||||||
|
<< av[0] << " outputfile.yml.gz" << endl
|
||||||
|
<< "The output file may be either XML (xml) or YAML (yml/yaml). You can even compress it by "
|
||||||
|
<< "specifying this in its extension like xml.gz yaml.gz etc... " << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main( int ac, char** av )
|
||||||
|
{
|
||||||
|
if( ac != 2 )
|
||||||
|
{
|
||||||
|
help( av );
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
string filename = av[1];
|
||||||
|
{ //write
|
||||||
|
Mat R = Mat( 3, 3, CV_8UC3 );
|
||||||
|
// fill the matrix with uniformly-distributed random values
|
||||||
|
randu( R, Scalar::all( 0 ), Scalar::all( 255 ) );
|
||||||
|
|
||||||
|
Mat T = Mat( 3, 1, CV_32FC3 );
|
||||||
|
// fill the matrix with normally distributed random values
|
||||||
|
randn( T, Scalar::all( 0 ), Scalar::all( 1 ) );
|
||||||
|
|
||||||
|
FileStorage fs( filename, FileStorage::WRITE );
|
||||||
|
|
||||||
|
fs << "R" << R; // cv::Mat
|
||||||
|
fs << "T" << T;
|
||||||
|
|
||||||
|
fs.release( ); // explicit close
|
||||||
|
cout << "Write Done." << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
{//read
|
||||||
|
cout << endl << "Reading: " << endl;
|
||||||
|
FileStorage fs;
|
||||||
|
fs.open( filename, FileStorage::READ );
|
||||||
|
|
||||||
|
if( !fs.isOpened( ) )
|
||||||
|
{
|
||||||
|
cerr << "Failed to open " << filename << endl;
|
||||||
|
help( av );
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mat R, T;
|
||||||
|
|
||||||
|
fs["R"] >> R; // Read cv::Mat
|
||||||
|
fs["T"] >> T;
|
||||||
|
|
||||||
|
cout << endl
|
||||||
|
<< "R = " << R << endl;
|
||||||
|
cout << "T = " << T << endl << endl;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
cout << endl
|
||||||
|
<< "Tip: Open up " << filename << " with a text editor to see the serialized data." << endl;
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
48
src/tutorials/load_and_display_video.cpp
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
#include <opencv2/core/core.hpp>
|
||||||
|
#include <opencv2/highgui/highgui.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
using namespace cv;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int main( int argc, char** argv )
|
||||||
|
{
|
||||||
|
if( argc != 2 )
|
||||||
|
{
|
||||||
|
cout << " Usage: display_video VideoToLoadAndDisplay" << endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
Mat image;
|
||||||
|
// Read the file
|
||||||
|
VideoCapture capture;
|
||||||
|
capture.open( argv[1] );
|
||||||
|
// Check if the video is loaded
|
||||||
|
if( !capture.isOpened( ) )
|
||||||
|
{
|
||||||
|
cout << "Could not open or find the video" << std::endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
cout << "FRAME_WIDTH: " << capture.get( CV_CAP_PROP_FRAME_WIDTH ) << endl;
|
||||||
|
cout << "FRAME_HEIGHT: " << capture.get( CV_CAP_PROP_FRAME_HEIGHT ) << endl;
|
||||||
|
cout << "FOURCC: " << capture.get( CV_CAP_PROP_FOURCC ) << endl;
|
||||||
|
cout << "FPS: " << capture.get( CV_CAP_PROP_FPS ) << endl;
|
||||||
|
// Create a window for display.
|
||||||
|
namedWindow( "Display window", CV_WINDOW_AUTOSIZE );
|
||||||
|
// infinite loop
|
||||||
|
while( 1 )
|
||||||
|
{
|
||||||
|
capture >> image;
|
||||||
|
|
||||||
|
//check if there are still frames
|
||||||
|
if( image.empty( ) )
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Show our image inside it.
|
||||||
|
imshow( "Display window", image );
|
||||||
|
|
||||||
|
if( waitKey( 10 ) == 'q' )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
59
src/tutorials/load_and_display_webcam.cpp
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
#include <opencv2/core/core.hpp>
|
||||||
|
#include <opencv2/highgui/highgui.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <cctype>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
using namespace cv;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int main( int argc, char** argv )
|
||||||
|
{
|
||||||
|
if( argc != 2 || !isdigit( *argv[1] ) )
|
||||||
|
{
|
||||||
|
cout << " Usage: " << argv[0] << " deviceNumber" << endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
int cameraId = 0;
|
||||||
|
sscanf( argv[1], "%d", &cameraId );
|
||||||
|
cout << cameraId << endl;
|
||||||
|
Mat image;
|
||||||
|
// Read the file
|
||||||
|
VideoCapture capture;
|
||||||
|
capture.open( cameraId );
|
||||||
|
// Check if the video is loaded
|
||||||
|
if( !capture.isOpened( ) )
|
||||||
|
{
|
||||||
|
cout << "Could not open or find the video" << std::endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
cout << "FRAME_WIDTH: " << capture.get( CV_CAP_PROP_FRAME_WIDTH ) << endl;
|
||||||
|
cout << "FRAME_HEIGHT: " << capture.get( CV_CAP_PROP_FRAME_HEIGHT ) << endl;
|
||||||
|
cout << "FOURCC: " << capture.get( CV_CAP_PROP_FOURCC ) << endl;
|
||||||
|
cout << "FPS: " << capture.get( CV_CAP_PROP_FPS ) << endl;
|
||||||
|
// Create a window for display.
|
||||||
|
|
||||||
|
capture.set( CV_CAP_PROP_FRAME_WIDTH, 640 );
|
||||||
|
capture.set( CV_CAP_PROP_FRAME_HEIGHT, 480 );
|
||||||
|
cout << capture.get( CV_CAP_PROP_FRAME_WIDTH ) << endl;
|
||||||
|
namedWindow( "Display window", CV_WINDOW_AUTOSIZE );
|
||||||
|
// infinite loop
|
||||||
|
while( 1 )
|
||||||
|
{
|
||||||
|
capture >> image;
|
||||||
|
|
||||||
|
//check if there are still frames
|
||||||
|
if( image.empty( ) )
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Show our image inside it.
|
||||||
|
imshow( "Display window", image );
|
||||||
|
|
||||||
|
if( waitKey( 10 ) == 'q' )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
37
src/tutorials/load_modify_image.cpp
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
#include <opencv2/core/core.hpp>
|
||||||
|
#include <opencv2/highgui/highgui.hpp>
|
||||||
|
#include <opencv2/imgproc/imgproc.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
using namespace cv;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int main( int argc, char** argv )
|
||||||
|
{
|
||||||
|
char* imageName = argv[1]; // Read the file
|
||||||
|
|
||||||
|
Mat image;
|
||||||
|
image = imread( imageName, 1 );
|
||||||
|
|
||||||
|
if( argc != 2 || image.empty( ) )
|
||||||
|
{
|
||||||
|
cerr << " No image data " << endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mat gray_image;
|
||||||
|
|
||||||
|
cvtColor( image, gray_image, CV_BGR2GRAY );
|
||||||
|
|
||||||
|
imwrite( "../../data/images/Gray_Image.jpg", gray_image );
|
||||||
|
|
||||||
|
namedWindow( imageName, CV_WINDOW_AUTOSIZE );
|
||||||
|
namedWindow( "Gray image", CV_WINDOW_AUTOSIZE );
|
||||||
|
|
||||||
|
imshow( imageName, image );
|
||||||
|
imshow( "Gray image", gray_image );
|
||||||
|
|
||||||
|
waitKey( 0 ); // Wait for a keystroke in the window
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
89
src/tutorials/mat_the_basic_image_container.cpp
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
/* For description look into the help() function. */
|
||||||
|
|
||||||
|
#include "opencv2/core/core.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace cv;
|
||||||
|
|
||||||
|
static void help( )
|
||||||
|
{
|
||||||
|
cout
|
||||||
|
<< "\n--------------------------------------------------------------------------" << endl
|
||||||
|
<< "This program shows how to create matrices(cv::Mat) in OpenCV and its serial"
|
||||||
|
<< " out capabilities" << endl
|
||||||
|
<< "That is, cv::Mat M(...); M.create and cout << M. " << endl
|
||||||
|
<< "Shows how output can be formated to OpenCV, python, numpy, csv and C styles." << endl
|
||||||
|
<< "Usage:" << endl
|
||||||
|
<< "./cvout_sample" << endl
|
||||||
|
<< "--------------------------------------------------------------------------" << endl
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main( int, char** )
|
||||||
|
{
|
||||||
|
help( );
|
||||||
|
// create by using the constructor
|
||||||
|
Mat M( 2, 2, CV_8UC3, Scalar( 0, 0, 255 ) );
|
||||||
|
cout << "M = " << endl << " " << M << endl << endl;
|
||||||
|
|
||||||
|
// create by using the create function()
|
||||||
|
M.create( 4, 4, CV_8UC( 2 ) );
|
||||||
|
cout << "M = " << endl << " " << M << endl << endl;
|
||||||
|
|
||||||
|
// create multidimensional matrices
|
||||||
|
int sz[3] = {2, 2, 2};
|
||||||
|
Mat L( 3, sz, CV_8UC( 1 ), Scalar::all( 0 ) );
|
||||||
|
// Cannot print via operator <<
|
||||||
|
|
||||||
|
// Create using MATLAB style eye, ones or zero matrix
|
||||||
|
Mat E = Mat::eye( 4, 4, CV_64F );
|
||||||
|
cout << "E = " << endl << " " << E << endl << endl;
|
||||||
|
|
||||||
|
Mat O = Mat::ones( 2, 2, CV_32F );
|
||||||
|
cout << "O = " << endl << " " << O << endl << endl;
|
||||||
|
|
||||||
|
Mat Z = Mat::zeros( 3, 3, CV_8UC1 );
|
||||||
|
cout << "Z = " << endl << " " << Z << endl << endl;
|
||||||
|
|
||||||
|
// create a 3x3 double-precision identity matrix
|
||||||
|
Mat C = ( Mat_<double>( 3, 3 ) << 0, -1, 0, -1, 5, -1, 0, -1, 0 );
|
||||||
|
cout << "C = " << endl << " " << C << endl << endl;
|
||||||
|
|
||||||
|
Mat RowClone = C.row( 1 ).clone( );
|
||||||
|
cout << "RowClone = " << endl << " " << RowClone << endl << endl;
|
||||||
|
|
||||||
|
// Fill a matrix with random values
|
||||||
|
Mat R = Mat( 3, 2, CV_8UC3 );
|
||||||
|
randu( R, Scalar::all( 0 ), Scalar::all( 255 ) );
|
||||||
|
|
||||||
|
// Demonstrate the output formating options
|
||||||
|
#if CV_MAJOR_VERSION < 3
|
||||||
|
cout << "R (default) = " << endl << R << endl << endl;
|
||||||
|
cout << "R (python) = " << endl << format( R, "python" ) << endl << endl;
|
||||||
|
cout << "R (numpy) = " << endl << format( R, "numpy" ) << endl << endl;
|
||||||
|
cout << "R (csv) = " << endl << format( R, "csv" ) << endl << endl;
|
||||||
|
cout << "R (c) = " << endl << format( R, "C" ) << endl << endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Point2f P( 5, 1 );
|
||||||
|
cout << "Point (2D) = " << P << endl << endl;
|
||||||
|
|
||||||
|
Point3f P3f( 2, 6, 7 );
|
||||||
|
cout << "Point (3D) = " << P3f << endl << endl;
|
||||||
|
|
||||||
|
|
||||||
|
vector<float> v;
|
||||||
|
v.push_back( ( float ) CV_PI );
|
||||||
|
v.push_back( 2 );
|
||||||
|
v.push_back( 3.01f );
|
||||||
|
|
||||||
|
cout << "Vector of floats via Mat = " << Mat( v ) << endl << endl;
|
||||||
|
|
||||||
|
vector<Point2f> vPoints( 20 );
|
||||||
|
for( size_t i = 0; i < vPoints.size( ); ++i )
|
||||||
|
vPoints[i] = Point2f( ( float ) ( i * 5 ), ( float ) ( i % 7 ) );
|
||||||
|
|
||||||
|
cout << "A vector of 2D Points = " << vPoints << endl << endl;
|
||||||
|
return 0;
|
||||||
|
}
|