Add 'find-object/' from commit '635efcd6220cabc258b88c54b1ae4279035bbe31'
git-subtree-dir: find-object git-subtree-mainline:9bd639e88cgit-subtree-split:635efcd622
This commit is contained in:
@@ -0,0 +1,164 @@
|
||||
|
||||
SET(headers_ui
|
||||
TcpServerPool.h
|
||||
)
|
||||
|
||||
IF(QT4_FOUND)
|
||||
QT4_WRAP_CPP(moc_srcs ${headers_ui})
|
||||
ELSE()
|
||||
QT5_WRAP_CPP(moc_srcs ${headers_ui})
|
||||
ENDIF()
|
||||
|
||||
SET(INCLUDE_DIRS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../include
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${OpenCV_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
IF(QT4_FOUND)
|
||||
INCLUDE(${QT_USE_FILE})
|
||||
ENDIF(QT4_FOUND)
|
||||
|
||||
SET(LIBRARIES
|
||||
${QT_LIBRARIES}
|
||||
${OpenCV_LIBS}
|
||||
)
|
||||
|
||||
if(Tcmalloc_FOUND)
|
||||
SET(LIBRARIES
|
||||
${LIBARIES}
|
||||
${Tcmalloc_LIBRARIES}
|
||||
)
|
||||
endif(Tcmalloc_FOUND)
|
||||
|
||||
|
||||
#include files
|
||||
INCLUDE_DIRECTORIES(${INCLUDE_DIRS})
|
||||
|
||||
SET(SRC_FILES main.cpp ${moc_srcs} )
|
||||
|
||||
# For Apple set the icns file containing icons
|
||||
IF(APPLE AND BUILD_AS_BUNDLE)
|
||||
# set how it shows up in the Info.plist file
|
||||
SET(MACOSX_BUNDLE_ICON_FILE ${PROJECT_NAME}.icns)
|
||||
# set where in the bundle to put the icns file
|
||||
SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
|
||||
# include the icns file in the target
|
||||
SET(SRC_FILES ${SRC_FILES} ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.icns)
|
||||
ENDIF(APPLE AND BUILD_AS_BUNDLE)
|
||||
|
||||
# Add exe icon resource
|
||||
IF(WIN32)
|
||||
IF( MINGW )
|
||||
# resource compilation for MinGW
|
||||
ADD_CUSTOM_COMMAND( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/AppIco.o
|
||||
COMMAND windres.exe -I${CMAKE_CURRENT_SOURCE_DIR} -i${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.rc
|
||||
-o ${CMAKE_CURRENT_BINARY_DIR}/AppIco.o )
|
||||
SET(SRC_FILES ${SRC_FILES} ${CMAKE_CURRENT_BINARY_DIR}/AppIco.o)
|
||||
ELSE( MINGW )
|
||||
SET(SRC_FILES ${SRC_FILES} ${PROJECT_NAME}.rc) # Error on visual studio 2008
|
||||
ENDIF( MINGW )
|
||||
ENDIF(WIN32)
|
||||
|
||||
# create an executable file
|
||||
IF(APPLE AND BUILD_AS_BUNDLE)
|
||||
ADD_EXECUTABLE(find_object_app MACOSX_BUNDLE ${SRC_FILES})
|
||||
ELSEIF(MINGW)
|
||||
ADD_EXECUTABLE(find_object_app WIN32 ${SRC_FILES})
|
||||
ELSE()
|
||||
ADD_EXECUTABLE(find_object_app ${SRC_FILES})
|
||||
ENDIF()
|
||||
# Linking with Qt libraries
|
||||
TARGET_LINK_LIBRARIES(find_object_app find_object ${LIBRARIES})
|
||||
IF(Qt5_FOUND)
|
||||
QT5_USE_MODULES(find_object_app Widgets Core Gui Network PrintSupport)
|
||||
ENDIF(Qt5_FOUND)
|
||||
|
||||
IF(APPLE AND BUILD_AS_BUNDLE)
|
||||
SET_TARGET_PROPERTIES(find_object_app PROPERTIES
|
||||
OUTPUT_NAME ${CMAKE_BUNDLE_NAME})
|
||||
ELSEIF(WIN32)
|
||||
SET_TARGET_PROPERTIES(find_object_app PROPERTIES
|
||||
OUTPUT_NAME ${PROJECT_NAME})
|
||||
ELSE()
|
||||
SET_TARGET_PROPERTIES(find_object_app PROPERTIES
|
||||
OUTPUT_NAME ${PROJECT_PREFIX})
|
||||
ENDIF()
|
||||
|
||||
#---------------------------
|
||||
# Installation stuff
|
||||
#---------------------------
|
||||
INSTALL(TARGETS find_object_app
|
||||
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT runtime
|
||||
BUNDLE DESTINATION "${CMAKE_BUNDLE_LOCATION}" COMPONENT runtime)
|
||||
|
||||
#---------------------------
|
||||
# Dependencies packaging
|
||||
#---------------------------
|
||||
IF(APPLE AND BUILD_AS_BUNDLE)
|
||||
INSTALL(CODE "execute_process(COMMAND ln -s \"../MacOS/${CMAKE_BUNDLE_NAME}\" ${PROJECT_NAME}
|
||||
WORKING_DIRECTORY \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/bin)")
|
||||
ENDIF(APPLE AND BUILD_AS_BUNDLE)
|
||||
|
||||
IF((APPLE AND BUILD_AS_BUNDLE) OR WIN32)
|
||||
SET(APPS "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/bin/${PROJECT_NAME}${CMAKE_EXECUTABLE_SUFFIX}")
|
||||
SET(plugin_dest_dir bin)
|
||||
SET(qtconf_dest_dir bin)
|
||||
IF(APPLE)
|
||||
SET(plugin_dest_dir MacOS)
|
||||
SET(qtconf_dest_dir Resources)
|
||||
SET(APPS "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/MacOS/${CMAKE_BUNDLE_NAME}")
|
||||
ENDIF(APPLE)
|
||||
|
||||
# Install needed Qt plugins by copying directories from the qt installation
|
||||
# One can cull what gets copied by using 'REGEX "..." EXCLUDE'
|
||||
# Exclude debug libraries
|
||||
IF(QT_PLUGINS_DIR)
|
||||
INSTALL(DIRECTORY "${QT_PLUGINS_DIR}/imageformats"
|
||||
DESTINATION ${plugin_dest_dir}/plugins
|
||||
COMPONENT runtime
|
||||
REGEX ".*d4.dll" EXCLUDE
|
||||
REGEX ".*d4.a" EXCLUDE)
|
||||
ELSE()
|
||||
#Qt5
|
||||
foreach(plugin ${Qt5Gui_PLUGINS})
|
||||
get_target_property(plugin_loc ${plugin} LOCATION)
|
||||
get_filename_component(plugin_dir ${plugin_loc} DIRECTORY)
|
||||
string(REPLACE "plugins" ";" loc_list ${plugin_dir})
|
||||
list(GET loc_list 1 plugin_type)
|
||||
#MESSAGE(STATUS "Qt5 plugin \"${plugin_loc}\" installed in \"${plugin_dest_dir}/plugins${plugin_type}\"")
|
||||
INSTALL(FILES ${plugin_loc}
|
||||
DESTINATION ${plugin_dest_dir}/plugins${plugin_type}
|
||||
COMPONENT runtime)
|
||||
endforeach()
|
||||
ENDIF()
|
||||
|
||||
# install a qt.conf file
|
||||
# this inserts some cmake code into the install script to write the file
|
||||
SET(QT_CONF_FILE [Paths]\nPlugins=plugins)
|
||||
IF(APPLE)
|
||||
SET(QT_CONF_FILE [Paths]\nPlugins=MacOS/plugins)
|
||||
ENDIF(APPLE)
|
||||
INSTALL(CODE "
|
||||
file(WRITE \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${qtconf_dest_dir}/qt.conf\" \"${QT_CONF_FILE}\")
|
||||
" COMPONENT runtime)
|
||||
|
||||
# directories to look for dependencies
|
||||
SET(DIRS ${QT_LIBRARY_DIRS} ${PROJECT_SOURCE_DIR}/bin)
|
||||
IF(APPLE)
|
||||
SET(DIRS ${DIRS} /usr/local /usr/local/lib)
|
||||
ENDIF(APPLE)
|
||||
|
||||
# Now the work of copying dependencies into the bundle/package
|
||||
# The quotes are escaped and variables to use at install time have their $ escaped
|
||||
# An alternative is the do a configure_file() on a script and use install(SCRIPT ...).
|
||||
# Note that the image plugins depend on QtSvg and QtXml, and it got those copied
|
||||
# over.
|
||||
# To find dependencies, cmake use "otool" on Apple and "dumpbin" on Windows (make sure you have one of them).
|
||||
install(CODE "
|
||||
file(GLOB_RECURSE QTPLUGINS \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${plugin_dest_dir}/plugins/*${CMAKE_SHARED_LIBRARY_SUFFIX}\")
|
||||
include(\"BundleUtilities\")
|
||||
fixup_bundle(\"${APPS}\" \"\${QTPLUGINS}\" \"${DIRS}\")
|
||||
" COMPONENT runtime)
|
||||
ENDIF((APPLE AND BUILD_AS_BUNDLE) OR WIN32)
|
||||
|
||||
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 70 KiB |
Binary file not shown.
@@ -0,0 +1 @@
|
||||
IDI_ICON1 ICON DISCARDABLE "Find-Object.ico"
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* TcpServerPool.h
|
||||
*
|
||||
* Created on: Nov 29, 2015
|
||||
* Author: mathieu
|
||||
*/
|
||||
|
||||
#ifndef TCPSERVERPOOL_H_
|
||||
#define TCPSERVERPOOL_H_
|
||||
|
||||
#include <find_object/FindObject.h>
|
||||
#include <find_object/TcpServer.h>
|
||||
#include <find_object/utilite/ULogger.h>
|
||||
#include <QtCore/QThread>
|
||||
#include <QtCore/QSemaphore>
|
||||
|
||||
class FindObjectWorker : public QObject
|
||||
{
|
||||
Q_OBJECT;
|
||||
|
||||
public:
|
||||
FindObjectWorker(
|
||||
find_object::FindObject * sharedFindObject,
|
||||
QSemaphore * sharedSemaphore,
|
||||
int maxSemaphoreResources,
|
||||
QObject * parent = 0) :
|
||||
QObject(parent),
|
||||
sharedFindObject_(sharedFindObject),
|
||||
sharedSemaphore_(sharedSemaphore),
|
||||
maxSemaphoreResources_(maxSemaphoreResources)
|
||||
{
|
||||
UASSERT(sharedFindObject != 0);
|
||||
UASSERT(sharedSemaphore != 0);
|
||||
UASSERT(maxSemaphoreResources > 0);
|
||||
}
|
||||
|
||||
public Q_SLOTS:
|
||||
void detect(const cv::Mat & image)
|
||||
{
|
||||
sharedSemaphore_->acquire(1);
|
||||
UINFO("Thread %p detecting...", (void *)this->thread());
|
||||
find_object::DetectionInfo info;
|
||||
sharedFindObject_->detect(image, info);
|
||||
Q_EMIT objectsFound(info);
|
||||
sharedSemaphore_->release(1);
|
||||
}
|
||||
|
||||
void addObjectAndUpdate(const cv::Mat & image, int id, const QString & filePath)
|
||||
{
|
||||
//block everyone!
|
||||
sharedSemaphore_->acquire(maxSemaphoreResources_);
|
||||
UINFO("Thread %p adding object %d (%s)...", (void *)this->thread(), id, filePath.toStdString().c_str());
|
||||
sharedFindObject_->addObjectAndUpdate(image, id, filePath);
|
||||
sharedSemaphore_->release(maxSemaphoreResources_);
|
||||
}
|
||||
void removeObjectAndUpdate(int id)
|
||||
{
|
||||
//block everyone!
|
||||
sharedSemaphore_->acquire(maxSemaphoreResources_);
|
||||
UINFO("Thread %p removing object %d...", (void *)this->thread(), id);
|
||||
sharedFindObject_->removeObjectAndUpdate(id);
|
||||
sharedSemaphore_->release(maxSemaphoreResources_);
|
||||
}
|
||||
|
||||
Q_SIGNALS:
|
||||
void objectsFound(const find_object::DetectionInfo &);
|
||||
|
||||
private:
|
||||
find_object::FindObject * sharedFindObject_; //shared findobject
|
||||
QSemaphore * sharedSemaphore_;
|
||||
int maxSemaphoreResources_;
|
||||
};
|
||||
|
||||
class TcpServerPool : public QObject
|
||||
{
|
||||
Q_OBJECT;
|
||||
public:
|
||||
TcpServerPool(find_object::FindObject * sharedFindObject, int threads, int port) :
|
||||
sharedSemaphore_(threads)
|
||||
{
|
||||
UASSERT(sharedFindObject != 0);
|
||||
UASSERT(threads>=1);
|
||||
|
||||
qRegisterMetaType<cv::Mat>("cv::Mat");
|
||||
|
||||
threadPool_.resize(threads);
|
||||
for(int i=0; i<threads; ++i)
|
||||
{
|
||||
find_object::TcpServer * tcpServer = new find_object::TcpServer(port!=0?port++:0);
|
||||
UINFO("TcpServer set on port: %d (IP=%s)",
|
||||
tcpServer->getPort(),
|
||||
tcpServer->getHostAddress().toString().toStdString().c_str());
|
||||
|
||||
threadPool_[i] = new QThread(this);
|
||||
FindObjectWorker * worker = new FindObjectWorker(sharedFindObject, &sharedSemaphore_, threads);
|
||||
|
||||
tcpServer->moveToThread(threadPool_[i]);
|
||||
worker->moveToThread(threadPool_[i]);
|
||||
connect(threadPool_[i], SIGNAL(finished()), tcpServer, SLOT(deleteLater()));
|
||||
connect(threadPool_[i], SIGNAL(finished()), worker, SLOT(deleteLater()));
|
||||
|
||||
// connect stuff:
|
||||
QObject::connect(worker, SIGNAL(objectsFound(find_object::DetectionInfo)), tcpServer, SLOT(publishDetectionInfo(find_object::DetectionInfo)));
|
||||
QObject::connect(tcpServer, SIGNAL(detectObject(const cv::Mat &)), worker, SLOT(detect(const cv::Mat &)));
|
||||
QObject::connect(tcpServer, SIGNAL(addObject(const cv::Mat &, int, const QString &)), worker, SLOT(addObjectAndUpdate(const cv::Mat &, int, const QString &)));
|
||||
QObject::connect(tcpServer, SIGNAL(removeObject(int)), worker, SLOT(removeObjectAndUpdate(int)));
|
||||
threadPool_[i]->start();
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~TcpServerPool()
|
||||
{
|
||||
for(int i=0; i<threadPool_.size(); ++i)
|
||||
{
|
||||
threadPool_[i]->quit();
|
||||
threadPool_[i]->wait();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
QVector<QThread*> threadPool_;
|
||||
QSemaphore sharedSemaphore_;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* TCPSERVERPOOL_H_ */
|
||||
@@ -0,0 +1,685 @@
|
||||
/*
|
||||
Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the Universite de Sherbrooke nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <QApplication>
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QFile>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include "find_object/MainWindow.h"
|
||||
#include "find_object/Settings.h"
|
||||
#include "find_object/FindObject.h"
|
||||
#include "find_object/Camera.h"
|
||||
#include "find_object/TcpServer.h"
|
||||
#include "find_object/JsonWriter.h"
|
||||
#include "find_object/utilite/ULogger.h"
|
||||
#include "TcpServerPool.h"
|
||||
|
||||
bool running = true;
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
BOOL WINAPI my_handler(DWORD signal)
|
||||
{
|
||||
if (signal == CTRL_C_EVENT)
|
||||
{
|
||||
printf("\nCtrl-C caught! Quitting application...\n");
|
||||
QCoreApplication::quit();
|
||||
}
|
||||
return TRUE;
|
||||
running = false;
|
||||
}
|
||||
#else
|
||||
#include <signal.h>
|
||||
void my_handler(int s)
|
||||
{
|
||||
printf("\nCtrl-C caught! Quitting application...\n");
|
||||
QCoreApplication::quit();
|
||||
running = false;
|
||||
}
|
||||
inline void Sleep(unsigned int ms)
|
||||
{
|
||||
struct timespec req;
|
||||
struct timespec rem;
|
||||
req.tv_sec = ms / 1000;
|
||||
req.tv_nsec = (ms - req.tv_sec * 1000) * 1000 * 1000;
|
||||
nanosleep (&req, &rem);
|
||||
}
|
||||
#endif
|
||||
|
||||
void setupQuitSignal()
|
||||
{
|
||||
// Catch ctrl-c to close Qt
|
||||
#ifdef WIN32
|
||||
if (!SetConsoleCtrlHandler(my_handler, TRUE))
|
||||
{
|
||||
UERROR("Could not set control (ctrl-c) handler");
|
||||
}
|
||||
#else
|
||||
struct sigaction sigIntHandler;
|
||||
sigIntHandler.sa_handler = my_handler;
|
||||
sigemptyset(&sigIntHandler.sa_mask);
|
||||
sigIntHandler.sa_flags = 0;
|
||||
sigaction(SIGINT, &sigIntHandler, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
void showUsage()
|
||||
{
|
||||
printf("\nUsage:\n"
|
||||
#ifdef WIN32
|
||||
" Find-Object.exe [options]\n"
|
||||
#else
|
||||
" find_object [options]\n"
|
||||
#endif
|
||||
"Options:\n"
|
||||
" --console Don't use the GUI (by default the camera will be\n"
|
||||
" started automatically). Option --objects must also be\n"
|
||||
" used with valid objects.\n"
|
||||
" --session \"path\" Path to a session to load (*.bin). Use \"--session_new\" to\n"
|
||||
" create a session instead (will be saved to \"path\" on exit, only\n"
|
||||
" on console mode).\n"
|
||||
" --object \"path\" Path to an object to detect.\n"
|
||||
" --objects \"path\" Directory of the objects to detect (--object is ignored).\n"
|
||||
" --config \"path\" Path to configuration file (default: %s).\n"
|
||||
" If set to \"\", default parameters are used\n"
|
||||
" without saving modified parameters on closing.\n"
|
||||
" --scene \"path\" Path to a scene image file.\n"
|
||||
" --vocabulary \"path\" Path to a vocabulary file (*.yaml *.xml). Parameters \"General/invertedSearch\"\n"
|
||||
" and \"General/vocabularyFixed\" will be also enabled. Ignored if \"--session\" is set.\n"
|
||||
" --images_not_saved Don't keep images in RAM after the features are extracted (only\n"
|
||||
" in console mode). Images won't be saved if an output session is set.\n"
|
||||
" --tcp_threads # Number of TCP threads (default 1, only in --console mode). \"--General/port\" parameter should not be 0.\n"
|
||||
" Port numbers start from \"General/port\" value. \"Detect\" TCP service can be\n"
|
||||
" executed at the same time by multiple threads. \"Add/Remove\" TCP services\n"
|
||||
" cannot be called by multiple threads, so calling these services on a port\n "
|
||||
" will block all other threads on the other ports.\n"
|
||||
" --debug Show debug log.\n"
|
||||
" --log-time Show log with time.\n"
|
||||
" --params Show all parameters.\n"
|
||||
" --defaults Use default parameters (--config is ignored).\n"
|
||||
" --My/Parameter \"value\" Set find-Object's parameter (look --params for parameters' name).\n"
|
||||
" It will override the one in --config. Example to set 4 threads:\n"
|
||||
" $ find_object --General/threads 4\n"
|
||||
" --json \"path\" Path to an output JSON file (only in --console mode with --scene).\n"
|
||||
" --help Show usage.\n"
|
||||
, find_object::Settings::iniDefaultPath().toStdString().c_str());
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
ULogger::setType(ULogger::kTypeConsole);
|
||||
ULogger::setLevel(ULogger::kInfo);
|
||||
ULogger::setPrintWhere(false);
|
||||
ULogger::setPrintTime(false);
|
||||
|
||||
//////////////////////////
|
||||
// parse options BEGIN
|
||||
//////////////////////////
|
||||
bool guiMode = true;
|
||||
QString sessionPath = "";
|
||||
bool sessionNew = false;
|
||||
QString objectsPath = "";
|
||||
QString objectPath = "";
|
||||
QString scenePath = "";
|
||||
QString configPath = "";
|
||||
QString vocabularyPath = "";
|
||||
QString jsonPath;
|
||||
find_object::ParametersMap customParameters;
|
||||
bool imagesSaved = true;
|
||||
int tcpThreads = 1;
|
||||
|
||||
for(int i=1; i<argc; ++i)
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
if(QString(argv[i]).startsWith("-psn"))
|
||||
{
|
||||
//safely ignore
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if(strcmp(argv[i], "-objs") == 0 ||
|
||||
strcmp(argv[i], "--objs") == 0 ||
|
||||
strcmp(argv[i], "-objects") == 0 ||
|
||||
strcmp(argv[i], "--objects") == 0)
|
||||
{
|
||||
++i;
|
||||
if(i < argc)
|
||||
{
|
||||
objectsPath = argv[i];
|
||||
if(objectsPath.contains('~'))
|
||||
{
|
||||
objectsPath.replace('~', QDir::homePath());
|
||||
}
|
||||
if(!QDir(objectsPath).exists())
|
||||
{
|
||||
UERROR("Objects path not valid : %s", objectsPath.toStdString().c_str());
|
||||
showUsage();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
showUsage();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(strcmp(argv[i], "-session") == 0 ||
|
||||
strcmp(argv[i], "--session") == 0 ||
|
||||
strcmp(argv[i], "-session_new") == 0 ||
|
||||
strcmp(argv[i], "--session_new") == 0)
|
||||
{
|
||||
if(strcmp(argv[i], "-session_new") == 0 ||
|
||||
strcmp(argv[i], "--session_new") == 0)
|
||||
{
|
||||
sessionNew = true;
|
||||
}
|
||||
++i;
|
||||
if(i < argc)
|
||||
{
|
||||
sessionPath = argv[i];
|
||||
if(sessionPath.contains('~'))
|
||||
{
|
||||
sessionPath.replace('~', QDir::homePath());
|
||||
}
|
||||
|
||||
if(!sessionNew && !QFile(sessionPath).exists())
|
||||
{
|
||||
UERROR("Session path not valid : %s (if you want to create a new session, use \"--session_new\")", sessionPath.toStdString().c_str());
|
||||
showUsage();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
showUsage();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(strcmp(argv[i], "-object") == 0 ||
|
||||
strcmp(argv[i], "--object") == 0)
|
||||
{
|
||||
++i;
|
||||
if(i < argc)
|
||||
{
|
||||
objectPath = argv[i];
|
||||
if(objectPath.contains('~'))
|
||||
{
|
||||
objectPath.replace('~', QDir::homePath());
|
||||
}
|
||||
if(!QFile(objectPath).exists())
|
||||
{
|
||||
UERROR("Object path not valid : %s", objectPath.toStdString().c_str());
|
||||
showUsage();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
showUsage();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(strcmp(argv[i], "-scene") == 0 ||
|
||||
strcmp(argv[i], "--scene") == 0)
|
||||
{
|
||||
++i;
|
||||
if(i < argc)
|
||||
{
|
||||
scenePath = argv[i];
|
||||
if(scenePath.contains('~'))
|
||||
{
|
||||
scenePath.replace('~', QDir::homePath());
|
||||
}
|
||||
if(!QFile(scenePath).exists())
|
||||
{
|
||||
UERROR("Scene path not valid : %s", scenePath.toStdString().c_str());
|
||||
showUsage();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
showUsage();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(strcmp(argv[i], "-vocabulary") == 0 ||
|
||||
strcmp(argv[i], "--vocabulary") == 0)
|
||||
{
|
||||
++i;
|
||||
if(i < argc)
|
||||
{
|
||||
vocabularyPath = argv[i];
|
||||
if(vocabularyPath.contains('~'))
|
||||
{
|
||||
vocabularyPath.replace('~', QDir::homePath());
|
||||
}
|
||||
if(!QFile(vocabularyPath).exists())
|
||||
{
|
||||
UERROR("Vocabulary path not valid : %s", vocabularyPath.toStdString().c_str());
|
||||
showUsage();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
showUsage();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(strcmp(argv[i], "-config") == 0 ||
|
||||
strcmp(argv[i], "--config") == 0)
|
||||
{
|
||||
++i;
|
||||
if(i < argc)
|
||||
{
|
||||
configPath = argv[i];
|
||||
if(configPath.contains('~'))
|
||||
{
|
||||
configPath.replace('~', QDir::homePath());
|
||||
}
|
||||
if(!configPath.isEmpty() && !QFile::exists(configPath))
|
||||
{
|
||||
UWARN("Configuration file \"%s\" doesn't exist, it will be created with default values...", configPath.toStdString().c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
showUsage();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(strcmp(argv[i], "-console") == 0 ||
|
||||
strcmp(argv[i], "--console") == 0)
|
||||
{
|
||||
guiMode = false;
|
||||
continue;
|
||||
}
|
||||
if(strcmp(argv[i], "-images_not_saved") == 0 ||
|
||||
strcmp(argv[i], "--images_not_saved") == 0)
|
||||
{
|
||||
imagesSaved = false;
|
||||
continue;
|
||||
}
|
||||
if(strcmp(argv[i], "-debug") == 0 ||
|
||||
strcmp(argv[i], "--debug") == 0)
|
||||
{
|
||||
customParameters.insert(find_object::Settings::kGeneral_debug(), true);
|
||||
continue;
|
||||
}
|
||||
if(strcmp(argv[i], "-log-time") == 0 ||
|
||||
strcmp(argv[i], "--log-time") == 0)
|
||||
{
|
||||
ULogger::setPrintWhere(true);
|
||||
ULogger::setPrintTime(true);
|
||||
continue;
|
||||
}
|
||||
if(strcmp(argv[i], "-help") == 0 ||
|
||||
strcmp(argv[i], "--help") == 0)
|
||||
{
|
||||
showUsage();
|
||||
}
|
||||
if(strcmp(argv[i], "-json") == 0 ||
|
||||
strcmp(argv[i], "--json") == 0)
|
||||
{
|
||||
++i;
|
||||
if(i < argc)
|
||||
{
|
||||
jsonPath = argv[i];
|
||||
if(jsonPath.contains('~'))
|
||||
{
|
||||
jsonPath.replace('~', QDir::homePath());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
showUsage();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(strcmp(argv[i], "-tcp_threads") == 0 ||
|
||||
strcmp(argv[i], "--tcp_threads") == 0)
|
||||
{
|
||||
++i;
|
||||
if(i < argc)
|
||||
{
|
||||
tcpThreads = atoi(argv[i]);
|
||||
if(tcpThreads < 1)
|
||||
{
|
||||
printf("tcp_threads should be >= 1!\n");
|
||||
showUsage();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
showUsage();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(strcmp(argv[i], "--params") == 0)
|
||||
{
|
||||
find_object::ParametersMap parameters = find_object::Settings::getDefaultParameters();
|
||||
for(find_object::ParametersMap::iterator iter=parameters.begin(); iter!=parameters.end(); ++iter)
|
||||
{
|
||||
std::string str = "Param: " + iter.key().toStdString() + " = \"" + iter.value().toString().toStdString() + "\"";
|
||||
std::cout <<
|
||||
str <<
|
||||
std::setw(60 - str.size()) <<
|
||||
" [" <<
|
||||
find_object::Settings::getDescriptions().value(iter.key()).toStdString().c_str() <<
|
||||
"]" <<
|
||||
std::endl;
|
||||
}
|
||||
UINFO("Node will now exit after showing default Find-Object's parameters because "
|
||||
"argument \"--params\" is detected!");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// Check for custom parameters:
|
||||
find_object::ParametersMap parameters = find_object::Settings::getDefaultParameters();
|
||||
QString name = argv[i];
|
||||
if(name.size() > 2)
|
||||
{
|
||||
//strip the "--"
|
||||
name.remove(0, 2);
|
||||
if(parameters.contains(name))
|
||||
{
|
||||
++i;
|
||||
if(i < argc)
|
||||
{
|
||||
customParameters.insert(name, argv[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
showUsage();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
UERROR("Unrecognized option : %s", argv[i]);
|
||||
showUsage();
|
||||
}
|
||||
|
||||
UINFO("Options:");
|
||||
UINFO(" GUI mode = %s", guiMode?"true":"false");
|
||||
if(!sessionPath.isEmpty())
|
||||
{
|
||||
if(sessionNew)
|
||||
{
|
||||
UINFO(" Session path: \"%s\" [NEW]", sessionPath.toStdString().c_str());
|
||||
if(configPath.isEmpty() && guiMode)
|
||||
{
|
||||
configPath = find_object::Settings::iniDefaultPath();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UINFO(" Session path: \"%s\"", sessionPath.toStdString().c_str());
|
||||
if(!vocabularyPath.isEmpty())
|
||||
{
|
||||
UWARN("Vocabulary \"%s\" is not loaded as a session \"%s\" is already "
|
||||
"loaded, ignoring vocabulary file...",
|
||||
vocabularyPath.toStdString().c_str(),
|
||||
sessionPath.toStdString().c_str());
|
||||
vocabularyPath.clear();
|
||||
}
|
||||
if(!configPath.isEmpty())
|
||||
{
|
||||
UWARN("A session \"%s\" is loaded and a config file is also used, "
|
||||
"the parameters of the session will be overwritten by "
|
||||
"those in the config file \"%s\".",
|
||||
sessionPath.toStdString().c_str(),
|
||||
configPath.toStdString().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(configPath.isEmpty() && guiMode)
|
||||
{
|
||||
configPath = find_object::Settings::iniDefaultPath();
|
||||
}
|
||||
if(!objectsPath.isEmpty())
|
||||
{
|
||||
UINFO(" Objects path: \"%s\"", objectsPath.toStdString().c_str());
|
||||
}
|
||||
else if(!objectPath.isEmpty())
|
||||
{
|
||||
UINFO(" Object path: \"%s\"", objectPath.toStdString().c_str());
|
||||
}
|
||||
UINFO(" Scene path: \"%s\"", scenePath.toStdString().c_str());
|
||||
if(!guiMode)
|
||||
{
|
||||
UINFO(" JSON path: \"%s\"", jsonPath.toStdString().c_str());
|
||||
}
|
||||
UINFO(" Settings path: \"%s\"", configPath.toStdString().c_str());
|
||||
UINFO(" Vocabulary path: \"%s\"", vocabularyPath.toStdString().c_str());
|
||||
|
||||
if(!vocabularyPath.isEmpty())
|
||||
{
|
||||
if(customParameters.contains(find_object::Settings::kGeneral_vocabularyFixed()))
|
||||
{
|
||||
UWARN("\"General/vocabularyFixed\" custom parameter overwritten as a fixed vocabulary is used.");
|
||||
}
|
||||
if(customParameters.contains(find_object::Settings::kGeneral_invertedSearch()))
|
||||
{
|
||||
UWARN("\"General/invertedSearch\" custom parameter overwritten as a fixed vocabulary is used.");
|
||||
}
|
||||
customParameters[find_object::Settings::kGeneral_vocabularyFixed()] = true;
|
||||
customParameters[find_object::Settings::kGeneral_invertedSearch()] = true;
|
||||
}
|
||||
|
||||
for(find_object::ParametersMap::iterator iter= customParameters.begin(); iter!=customParameters.end(); ++iter)
|
||||
{
|
||||
UINFO(" Param \"%s\"=\"%s\"", iter.key().toStdString().c_str(), iter.value().toString().toStdString().c_str());
|
||||
}
|
||||
|
||||
//////////////////////////
|
||||
// parse options END
|
||||
//////////////////////////
|
||||
|
||||
// Load settings, should be loaded before creating other objects
|
||||
find_object::ParametersMap parameters;
|
||||
if(!configPath.isEmpty())
|
||||
{
|
||||
parameters = find_object::Settings::init(configPath);
|
||||
}
|
||||
|
||||
// Override custom parameters:
|
||||
for(find_object::ParametersMap::iterator iter= customParameters.begin(); iter!=customParameters.end(); ++iter)
|
||||
{
|
||||
find_object::Settings::setParameter(iter.key(), iter.value());
|
||||
parameters.insert(iter.key(), iter.value());
|
||||
}
|
||||
|
||||
|
||||
// Create FindObject
|
||||
find_object::FindObject * findObject = new find_object::FindObject(guiMode || imagesSaved);
|
||||
|
||||
// Load objects if path is set
|
||||
int objectsLoaded = 0;
|
||||
if(!sessionPath.isEmpty() && !sessionNew)
|
||||
{
|
||||
if(!findObject->loadSession(sessionPath, parameters))
|
||||
{
|
||||
UERROR("Could not load session \"%s\"", sessionPath.toStdString().c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
objectsLoaded = findObject->objects().size();
|
||||
}
|
||||
}
|
||||
else if(!vocabularyPath.isEmpty() && !findObject->loadVocabulary(vocabularyPath))
|
||||
{
|
||||
UERROR("Failed to load vocabulary \"%s\"", vocabularyPath.toStdString().c_str());
|
||||
}
|
||||
|
||||
if(!objectsPath.isEmpty())
|
||||
{
|
||||
if(!vocabularyPath.isEmpty() && !findObject->loadVocabulary(vocabularyPath))
|
||||
{
|
||||
UERROR("Failed to load vocabulary \"%s\"", vocabularyPath.toStdString().c_str());
|
||||
}
|
||||
objectsLoaded = findObject->loadObjects(objectsPath);
|
||||
if(!objectsLoaded)
|
||||
{
|
||||
UWARN("No objects loaded from \"%s\"", objectsPath.toStdString().c_str());
|
||||
}
|
||||
}
|
||||
else if(!objectPath.isEmpty())
|
||||
{
|
||||
if(!vocabularyPath.isEmpty() && !findObject->loadVocabulary(vocabularyPath))
|
||||
{
|
||||
UERROR("Failed to load vocabulary \"%s\"", vocabularyPath.toStdString().c_str());
|
||||
}
|
||||
|
||||
const find_object::ObjSignature * obj = findObject->addObject(objectPath);
|
||||
if(obj)
|
||||
{
|
||||
++objectsLoaded;
|
||||
findObject->updateObjects();
|
||||
findObject->updateVocabulary();
|
||||
}
|
||||
else
|
||||
{
|
||||
UWARN("No object loaded from \"%s\"", objectsPath.toStdString().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
cv::Mat scene;
|
||||
if(!scenePath.isEmpty())
|
||||
{
|
||||
scene = cv::imread(scenePath.toStdString());
|
||||
if(scene.empty())
|
||||
{
|
||||
UERROR("Failed to load scene \"%s\"", scenePath.toStdString().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if(guiMode)
|
||||
{
|
||||
QApplication app(argc, argv);
|
||||
find_object::MainWindow mainWindow(findObject, 0); // ownership transfered
|
||||
|
||||
app.connect( &app, SIGNAL( lastWindowClosed() ), &app, SLOT( quit() ) );
|
||||
mainWindow.show();
|
||||
|
||||
if(!scene.empty())
|
||||
{
|
||||
mainWindow.update(scene);
|
||||
}
|
||||
|
||||
app.exec();
|
||||
|
||||
// Save settings
|
||||
find_object::Settings::saveSettings();
|
||||
}
|
||||
else
|
||||
{
|
||||
QCoreApplication app(argc, argv);
|
||||
|
||||
if(!scene.empty())
|
||||
{
|
||||
// process the scene and exit
|
||||
QTime time;
|
||||
time.start();
|
||||
find_object::DetectionInfo info;
|
||||
findObject->detect(scene, info);
|
||||
|
||||
if(info.objDetected_.size() > 1)
|
||||
{
|
||||
UINFO("%d objects detected! (%d ms)", (int)info.objDetected_.size(), time.elapsed());
|
||||
}
|
||||
else if(info.objDetected_.size() == 1)
|
||||
{
|
||||
UINFO("Object %d detected! (%d ms)", (int)info.objDetected_.begin().key(), time.elapsed());
|
||||
}
|
||||
else if(find_object::Settings::getGeneral_sendNoObjDetectedEvents())
|
||||
{
|
||||
UINFO("No objects detected. (%d ms)", time.elapsed());
|
||||
}
|
||||
|
||||
if(!jsonPath.isEmpty())
|
||||
{
|
||||
find_object::JsonWriter::write(info, jsonPath);
|
||||
UINFO("JSON written to \"%s\"", jsonPath.toStdString().c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TcpServerPool tcpServerPool(findObject, tcpThreads, find_object::Settings::getGeneral_port());
|
||||
|
||||
setupQuitSignal();
|
||||
|
||||
//If TCP camera is used
|
||||
find_object::Camera * camera = 0;
|
||||
if(find_object::Settings::getCamera_6useTcpCamera())
|
||||
{
|
||||
camera = new find_object::Camera();
|
||||
|
||||
// [Camera] ---Image---> [FindObject]
|
||||
QObject::connect(camera, SIGNAL(imageReceived(const cv::Mat &)), findObject, SLOT(detect(const cv::Mat &)));
|
||||
QObject::connect(camera, SIGNAL(finished()), &app, SLOT(quit()));
|
||||
|
||||
if(!camera->start())
|
||||
{
|
||||
UERROR("Camera initialization failed!");
|
||||
running = false;
|
||||
}
|
||||
}
|
||||
|
||||
// start processing!
|
||||
if(running)
|
||||
{
|
||||
app.exec();
|
||||
|
||||
if(!sessionPath.isEmpty())
|
||||
{
|
||||
if(findObject->isSessionModified())
|
||||
{
|
||||
UINFO("The session has been modified, updating the session file...");
|
||||
if(findObject->saveSession(sessionPath))
|
||||
{
|
||||
UINFO("Session \"%s\" successfully saved (%d objects)!",
|
||||
sessionPath.toStdString().c_str(), findObject->objects().size());
|
||||
}
|
||||
}
|
||||
else if(sessionNew)
|
||||
{
|
||||
UINFO("The session has not been modified, session file not created...");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// cleanup
|
||||
if(camera)
|
||||
{
|
||||
camera->stop();
|
||||
delete camera;
|
||||
}
|
||||
}
|
||||
|
||||
delete findObject;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user