Added tcpService tool to Add/Remove objects through TCP

git-svn-id: http://find-object.googlecode.com/svn/trunk/find_object@420 620bd6b2-0a58-f614-fd9a-1bd335dccda9
This commit is contained in:
matlabbe 2015-01-12 01:19:09 +00:00
parent 5d1f30cc09
commit 82f953b911
10 changed files with 546 additions and 63 deletions

View File

@ -509,6 +509,10 @@ int main(int argc, char* argv[])
QObject::connect(&camera, SIGNAL(imageReceived(const cv::Mat &)), findObject, SLOT(detect(const cv::Mat &))); QObject::connect(&camera, SIGNAL(imageReceived(const cv::Mat &)), findObject, SLOT(detect(const cv::Mat &)));
QObject::connect(&camera, SIGNAL(finished()), &app, SLOT(quit())); QObject::connect(&camera, SIGNAL(finished()), &app, SLOT(quit()));
//connect services
QObject::connect(&tcpServer, SIGNAL(addObject(const cv::Mat &, int, const QString &)), findObject, SLOT(addObjectAndUpdate(const cv::Mat &, int, const QString &)));
QObject::connect(&tcpServer, SIGNAL(removeObject(int)), findObject, SLOT(removeObjectAndUpdate(int)));
//use camera in settings //use camera in settings
setupQuitSignal(); setupQuitSignal();
@ -521,6 +525,16 @@ int main(int argc, char* argv[])
if(running) if(running)
{ {
app.exec(); app.exec();
if(!sessionPath.isEmpty() && 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());
}
}
} }
// cleanup // cleanup

View File

@ -66,7 +66,8 @@ public:
virtual ~FindObject(); virtual ~FindObject();
bool loadSession(const QString & path); bool loadSession(const QString & path);
bool saveSession(const QString & path) const; bool saveSession(const QString & path);
bool isSessionModified() const {return sessionModified_;}
int loadObjects(const QString & dirPath); // call updateObjects() int loadObjects(const QString & dirPath); // call updateObjects()
const ObjSignature * addObject(const QString & filePath); const ObjSignature * addObject(const QString & filePath);
@ -78,13 +79,15 @@ public:
bool detect(const cv::Mat & image, find_object::DetectionInfo & info); bool detect(const cv::Mat & image, find_object::DetectionInfo & info);
void updateDetectorExtractor(); void updateDetectorExtractor();
void updateObjects(); void updateObjects(const QList<int> & ids = QList<int>());
void updateVocabulary(); void updateVocabulary();
const QMap<int, ObjSignature*> & objects() const {return objects_;} const QMap<int, ObjSignature*> & objects() const {return objects_;}
const Vocabulary * vocabulary() const {return vocabulary_;} const Vocabulary * vocabulary() const {return vocabulary_;}
public Q_SLOTS: public Q_SLOTS:
void addObjectAndUpdate(const cv::Mat & image, int id=0, const QString & filename = QString());
void removeObjectAndUpdate(int id);
void detect(const cv::Mat & image); // emit objectsFound() void detect(const cv::Mat & image); // emit objectsFound()
Q_SIGNALS: Q_SIGNALS:
@ -100,6 +103,7 @@ private:
QMap<int, int> dataRange_; // <last id of object's descriptor, id> QMap<int, int> dataRange_; // <last id of object's descriptor, id>
KeypointDetector * detector_; KeypointDetector * detector_;
DescriptorExtractor * extractor_; DescriptorExtractor * extractor_;
bool sessionModified_;
}; };
} // namespace find_object } // namespace find_object

View File

@ -90,12 +90,14 @@ private Q_SLOTS:
void addObjectFromScene(); void addObjectFromScene();
void addObjectsFromFiles(const QStringList & fileNames); void addObjectsFromFiles(const QStringList & fileNames);
void addObjectsFromFiles(); void addObjectsFromFiles();
void addObjectFromTcp(const cv::Mat & image, int id, const QString & filePath);
void loadSceneFromFile(const QStringList & fileNames); void loadSceneFromFile(const QStringList & fileNames);
void loadSceneFromFile(); void loadSceneFromFile();
void setupCameraFromVideoFile(); void setupCameraFromVideoFile();
void setupCameraFromImagesDirectory(); void setupCameraFromImagesDirectory();
void setupCameraFromTcpIp(); void setupCameraFromTcpIp();
void removeObject(find_object::ObjWidget * object); void removeObject(find_object::ObjWidget * object);
void removeObject(int id);
void removeAllObjects(); void removeAllObjects();
void updateObjectsSize(); void updateObjectsSize();
void updateMirrorView(); void updateMirrorView();
@ -116,10 +118,11 @@ private:
int loadObjects(const QString & dirPath); int loadObjects(const QString & dirPath);
int saveObjects(const QString & dirPath); int saveObjects(const QString & dirPath);
void setupTCPServer(); void setupTCPServer();
bool addObjectFromFile(const QString & filePath); int addObjectFromFile(const QString & filePath);
void showObject(find_object::ObjWidget * obj); void showObject(find_object::ObjWidget * obj);
void updateObjectSize(find_object::ObjWidget * obj); void updateObjectSize(find_object::ObjWidget * obj);
void updateVocabulary(); void updateVocabulary();
void updateObjects(const QList<int> & ids);
private: private:
Ui_mainWindow * ui_; Ui_mainWindow * ui_;

View File

@ -31,6 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "find_object/FindObjectExp.h" // DLL export/import defines #include "find_object/FindObjectExp.h" // DLL export/import defines
#include "find_object/DetectionInfo.h" #include "find_object/DetectionInfo.h"
#include <opencv2/opencv.hpp>
#include <QtNetwork/QTcpServer> #include <QtNetwork/QTcpServer>
@ -42,6 +43,12 @@ class FINDOBJECT_EXP TcpServer : public QTcpServer
{ {
Q_OBJECT Q_OBJECT
public:
enum Service {
kAddObject, // id fileName imageSize image
kRemoveObject // id
};
public: public:
TcpServer(quint16 port = 0, QObject * parent = 0); TcpServer(quint16 port = 0, QObject * parent = 0);
@ -53,6 +60,16 @@ public Q_SLOTS:
private Q_SLOTS: private Q_SLOTS:
void addClient(); void addClient();
void readReceivedData();
void displayError(QAbstractSocket::SocketError socketError);
void connectionLost();
Q_SIGNALS:
void addObject(const cv::Mat &, int, const QString &);
void removeObject(int);
private:
QMap<int, quint64> blockSizes_;
}; };
} // namespace find_object } // namespace find_object

View File

@ -46,7 +46,8 @@ FindObject::FindObject(QObject * parent) :
QObject(parent), QObject(parent),
vocabulary_(new Vocabulary()), vocabulary_(new Vocabulary()),
detector_(Settings::createKeypointDetector()), detector_(Settings::createKeypointDetector()),
extractor_(Settings::createDescriptorExtractor()) extractor_(Settings::createDescriptorExtractor()),
sessionModified_(false)
{ {
qRegisterMetaType<find_object::DetectionInfo>("find_object::DetectionInfo"); qRegisterMetaType<find_object::DetectionInfo>("find_object::DetectionInfo");
UASSERT(detector_ != 0 && extractor_ != 0); UASSERT(detector_ != 0 && extractor_ != 0);
@ -101,7 +102,7 @@ bool FindObject::loadSession(const QString & path)
// this will fill objectsDescriptors_ matrix // this will fill objectsDescriptors_ matrix
updateVocabulary(); updateVocabulary();
} }
sessionModified_ = false;
return true; return true;
} }
else else
@ -111,7 +112,7 @@ bool FindObject::loadSession(const QString & path)
return false; return false;
} }
bool FindObject::saveSession(const QString & path) const bool FindObject::saveSession(const QString & path)
{ {
if(!path.isEmpty() && QFileInfo(path).suffix().compare("bin") == 0) if(!path.isEmpty() && QFileInfo(path).suffix().compare("bin") == 0)
{ {
@ -132,6 +133,7 @@ bool FindObject::saveSession(const QString & path) const
} }
file.close(); file.close();
sessionModified_ = false;
return true; return true;
} }
UERROR("Path \"%s\" not valid (should be *.bin)", path.toStdString().c_str()); UERROR("Path \"%s\" not valid (should be *.bin)", path.toStdString().c_str());
@ -243,6 +245,28 @@ void FindObject::removeAllObjects()
clearVocabulary(); clearVocabulary();
} }
void FindObject::addObjectAndUpdate(const cv::Mat & image, int id, const QString & filename)
{
const ObjSignature * s = this->addObject(image, id, filename);
if(s)
{
QList<int> ids;
ids.push_back(s->id());
updateObjects(ids);
updateVocabulary();
}
}
void FindObject::removeObjectAndUpdate(int id)
{
if(objects_.contains(id))
{
delete objects_.value(id);
objects_.remove(id);
}
updateVocabulary();
}
void FindObject::updateDetectorExtractor() void FindObject::updateDetectorExtractor()
{ {
delete detector_; delete detector_;
@ -561,39 +585,63 @@ private:
int timeExtraction_; int timeExtraction_;
}; };
void FindObject::updateObjects() void FindObject::updateObjects(const QList<int> & ids)
{ {
if(objects_.size()) QList<ObjSignature*> objectsList;
if(ids.size())
{ {
for(int i=0; i<ids.size(); ++i)
{
if(objects_.contains(ids[i]))
{
objectsList.push_back(objects_[ids[i]]);
}
else
{
UERROR("Not found object %d!", ids[i]);
}
}
}
else
{
objectsList = objects_.values();
}
if(objectsList.size())
{
sessionModified_ = true;
int threadCounts = Settings::getGeneral_threads(); int threadCounts = Settings::getGeneral_threads();
if(threadCounts == 0) if(threadCounts == 0)
{ {
threadCounts = objects_.size(); threadCounts = objectsList.size();
} }
QTime time; QTime time;
time.start(); time.start();
UINFO("Features extraction from %d objects...", objects_.size());
QList<ObjSignature*> objectsList = objects_.values(); if(objectsList.size())
for(int i=0; i<objectsList.size(); i+=threadCounts)
{ {
QVector<ExtractFeaturesThread*> threads; UINFO("Features extraction from %d objects...", objectsList.size());
for(int k=i; k<i+threadCounts && k<objectsList.size(); ++k) for(int i=0; i<objectsList.size(); i+=threadCounts)
{ {
threads.push_back(new ExtractFeaturesThread(detector_, extractor_, objectsList.at(k)->id(), objectsList.at(k)->image())); QVector<ExtractFeaturesThread*> threads;
threads.back()->start(); for(int k=i; k<i+threadCounts && k<objectsList.size(); ++k)
} {
threads.push_back(new ExtractFeaturesThread(detector_, extractor_, objectsList.at(k)->id(), objectsList.at(k)->image()));
for(int j=0; j<threads.size(); ++j) threads.back()->start();
{ }
threads[j]->wait();
for(int j=0; j<threads.size(); ++j)
int id = threads[j]->objectId(); {
threads[j]->wait();
objects_.value(id)->setData(threads[j]->keypoints(), threads[j]->descriptors());
int id = threads[j]->objectId();
objects_.value(id)->setData(threads[j]->keypoints(), threads[j]->descriptors());
}
} }
UINFO("Features extraction from %d objects... done! (%d ms)", objectsList.size(), time.elapsed());
} }
UINFO("Features extraction from %d objects... done! (%d ms)", objects_.size(), time.elapsed());
} }
else else
{ {
@ -667,6 +715,7 @@ void FindObject::updateVocabulary()
if(Settings::getGeneral_invertedSearch()) if(Settings::getGeneral_invertedSearch())
{ {
sessionModified_ = true;
QTime time; QTime time;
time.start(); time.start();
bool incremental = Settings::getGeneral_vocabularyIncremental(); bool incremental = Settings::getGeneral_vocabularyIncremental();

View File

@ -311,6 +311,10 @@ void MainWindow::setupTCPServer()
ui_->label_ipAddress->setText(tcpServer_->getHostAddress().toString()); ui_->label_ipAddress->setText(tcpServer_->getHostAddress().toString());
ui_->label_port->setNum(tcpServer_->getPort()); ui_->label_port->setNum(tcpServer_->getPort());
UINFO("Detection sent on port: %d (IP=%s)", tcpServer_->getPort(), tcpServer_->getHostAddress().toString().toStdString().c_str()); UINFO("Detection sent on port: %d (IP=%s)", tcpServer_->getPort(), tcpServer_->getHostAddress().toString().toStdString().c_str());
//connect services
connect(tcpServer_, SIGNAL(addObject(const cv::Mat &, int, const QString &)), this, SLOT(addObjectFromTcp(const cv::Mat &, int, const QString &)));
connect(tcpServer_, SIGNAL(removeObject(int)), this, SLOT(removeObject(int)));
} }
void MainWindow::setSourceImageText(const QString & text) void MainWindow::setSourceImageText(const QString & text)
@ -459,7 +463,7 @@ bool MainWindow::saveSettings(const QString & path) const
int MainWindow::loadObjects(const QString & dirPath) int MainWindow::loadObjects(const QString & dirPath)
{ {
int loadedObjects = 0; QList<int> loadedObjects;
QString formats = Settings::getGeneral_imageFormats().remove('*').remove('.'); QString formats = Settings::getGeneral_imageFormats().remove('*').remove('.');
UDirectory dir(dirPath.toStdString(), formats.toStdString()); UDirectory dir(dirPath.toStdString(), formats.toStdString());
if(dir.isValid()) if(dir.isValid())
@ -467,17 +471,18 @@ int MainWindow::loadObjects(const QString & dirPath)
const std::list<std::string> & names = dir.getFileNames(); // sorted in natural order const std::list<std::string> & names = dir.getFileNames(); // sorted in natural order
for(std::list<std::string>::const_iterator iter=names.begin(); iter!=names.end(); ++iter) for(std::list<std::string>::const_iterator iter=names.begin(); iter!=names.end(); ++iter)
{ {
if(this->addObjectFromFile((dirPath.toStdString()+dir.separator()+*iter).c_str())) int id = this->addObjectFromFile((dirPath.toStdString()+dir.separator()+*iter).c_str());
if(id >= 0)
{ {
++loadedObjects; loadedObjects.push_back(id);
} }
} }
if(loadedObjects) if(loadedObjects.size())
{ {
this->updateObjects(); this->updateObjects(loadedObjects);
} }
} }
return loadedObjects; return loadedObjects.size();
} }
int MainWindow::saveObjects(const QString & dirPath) int MainWindow::saveObjects(const QString & dirPath)
@ -560,6 +565,18 @@ void MainWindow::removeObject(find_object::ObjWidget * object)
} }
} }
void MainWindow::removeObject(int id)
{
if(objWidgets_.contains(id))
{
removeObject(objWidgets_[id]);
}
else
{
UERROR("Remove object: Object %d not found!", id);
}
}
void MainWindow::removeAllObjects() void MainWindow::removeAllObjects()
{ {
qDeleteAll(objWidgets_); qDeleteAll(objWidgets_);
@ -677,12 +694,20 @@ void MainWindow::addObjectsFromFiles(const QStringList & fileNames)
{ {
if(fileNames.size()) if(fileNames.size())
{ {
QList<int> ids;
for(int i=0; i<fileNames.size(); ++i) for(int i=0; i<fileNames.size(); ++i)
{ {
this->addObjectFromFile(fileNames.at(i)); int id = this->addObjectFromFile(fileNames.at(i));
if(id >= 0)
{
ids.push_back(id);
}
}
if(ids.size())
{
objectsModified_ = true;
updateObjects(ids);
} }
objectsModified_ = true;
updateObjects();
} }
} }
@ -691,7 +716,7 @@ void MainWindow::addObjectsFromFiles()
addObjectsFromFiles(QFileDialog::getOpenFileNames(this, tr("Add objects..."), Settings::workingDirectory(), tr("Image Files (%1)").arg(Settings::getGeneral_imageFormats()))); addObjectsFromFiles(QFileDialog::getOpenFileNames(this, tr("Add objects..."), Settings::workingDirectory(), tr("Image Files (%1)").arg(Settings::getGeneral_imageFormats())));
} }
bool MainWindow::addObjectFromFile(const QString & filePath) int MainWindow::addObjectFromFile(const QString & filePath)
{ {
const ObjSignature * s = findObject_->addObject(filePath); const ObjSignature * s = findObject_->addObject(filePath);
if(s) if(s)
@ -701,12 +726,36 @@ bool MainWindow::addObjectFromFile(const QString & filePath)
ui_->actionSave_objects->setEnabled(true); ui_->actionSave_objects->setEnabled(true);
ui_->actionSave_session->setEnabled(true); ui_->actionSave_session->setEnabled(true);
this->showObject(obj); this->showObject(obj);
return true; return s->id();
} }
else else
{ {
QMessageBox::critical(this, tr("Error adding object"), tr("Failed to add object from \"%1\"").arg(filePath)); QMessageBox::critical(this, tr("Error adding object"), tr("Failed to add object from \"%1\"").arg(filePath));
return false; return -1;
}
}
void MainWindow::addObjectFromTcp(const cv::Mat & image, int id, const QString & filePath)
{
if(objWidgets_.contains(id))
{
UERROR("Add Object: Object %d is already added.", id);
}
const ObjSignature * s = findObject_->addObject(image, id, filePath);
if(s)
{
ObjWidget * obj = new ObjWidget(s->id(), std::vector<cv::KeyPoint>(), cvtCvMat2QImage(s->image()));
objWidgets_.insert(obj->id(), obj);
ui_->actionSave_objects->setEnabled(true);
ui_->actionSave_session->setEnabled(true);
this->showObject(obj);
QList<int> ids;
ids.push_back(obj->id());
updateObjects(ids);
}
else
{
UERROR("Add Object: Error adding object %d.", id);
} }
} }
@ -883,30 +932,41 @@ void MainWindow::showObject(ObjWidget * obj)
} }
} }
void MainWindow::updateObjects(const QList<int> & ids)
{
if(ids.size())
{
this->statusBar()->showMessage(tr("Updating %1 objects...").arg(ids.size()));
QApplication::processEvents();
findObject_->updateObjects(ids);
updateVocabulary();
QList<ObjSignature*> signatures = findObject_->objects().values();
for(int i=0; i<signatures.size(); ++i)
{
if(ids.contains(signatures[i]->id()))
{
objWidgets_.value(signatures[i]->id())->setData(signatures[i]->keypoints(), cvtCvMat2QImage(signatures[i]->image()));
//update object labels
QLabel * title = qFindChild<QLabel*>(this, QString("%1title").arg(signatures[i]->id()));
title->setText(QString("%1 (%2)").arg(signatures[i]->id()).arg(QString::number(signatures[i]->keypoints().size())));
}
}
if(!camera_->isRunning() && !sceneImage_.empty())
{
this->update(sceneImage_);
}
this->statusBar()->clearMessage();
}
}
void MainWindow::updateObjects() void MainWindow::updateObjects()
{ {
this->statusBar()->showMessage(tr("Updating %1 objects...").arg(findObject_->objects().size())); updateObjects(objWidgets_.keys());
QApplication::processEvents();
findObject_->updateObjects();
updateVocabulary();
QList<ObjSignature*> signatures = findObject_->objects().values();
for(int i=0; i<signatures.size(); ++i)
{
objWidgets_.value(signatures[i]->id())->setData(signatures[i]->keypoints(), cvtCvMat2QImage(signatures[i]->image()));
//update object labels
QLabel * title = qFindChild<QLabel*>(this, QString("%1title").arg(signatures[i]->id()));
title->setText(QString("%1 (%2)").arg(signatures[i]->id()).arg(QString::number(signatures[i]->keypoints().size())));
}
if(!camera_->isRunning() && !sceneImage_.empty())
{
this->update(sceneImage_);
}
this->statusBar()->clearMessage();
} }
void MainWindow::updateVocabulary() void MainWindow::updateVocabulary()
@ -1374,7 +1434,7 @@ void MainWindow::notifyParametersChanged(const QStringList & paramChanged)
{ {
if(detectorDescriptorParamsChanged) if(detectorDescriptorParamsChanged)
{ {
this->updateObjects(); this->updateObjects(objWidgets_.keys());
} }
else if(nearestNeighborParamsChanged) else if(nearestNeighborParamsChanged)
{ {

View File

@ -30,6 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <QtNetwork/QNetworkInterface> #include <QtNetwork/QNetworkInterface>
#include <QtNetwork/QTcpSocket> #include <QtNetwork/QTcpSocket>
#include <QtGui/QTransform> #include <QtGui/QTransform>
#include <opencv2/highgui/highgui.hpp>
namespace find_object { namespace find_object {
@ -98,8 +99,101 @@ void TcpServer::publishDetectionInfo(const DetectionInfo & info)
void TcpServer::addClient() void TcpServer::addClient()
{ {
QTcpSocket * client = this->nextPendingConnection(); while(this->hasPendingConnections())
connect(client, SIGNAL(disconnected()), client, SLOT(deleteLater())); {
QTcpSocket * client = this->nextPendingConnection();
connect(client, SIGNAL(readyRead()), this, SLOT(readReceivedData()));
connect(client, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(displayError(QAbstractSocket::SocketError)));
connect(client, SIGNAL(disconnected()), this, SLOT(connectionLost()));
}
}
void TcpServer::readReceivedData()
{
QTcpSocket * client = (QTcpSocket*)sender();
QDataStream in(client);
in.setVersion(QDataStream::Qt_4_0);
if (blockSizes_.value(client->socketDescriptor(), 0) == 0)
{
if (client->bytesAvailable() < (int)sizeof(quint64))
{
return;
}
in >> blockSizes_[client->socketDescriptor()];
}
if (client->bytesAvailable() < (int)blockSizes_[client->socketDescriptor()])
{
return;
}
quint32 serviceType;
in >> serviceType;
bool ok = true;
if(serviceType == kAddObject)
{
int id;
in >> id;
QString fileName;
in >> fileName;
quint64 imageSize;
in >> imageSize;
std::vector<unsigned char> buf(imageSize);
in.readRawData((char*)buf.data(), imageSize);
cv::Mat image = cv::imdecode(buf, cv::IMREAD_UNCHANGED);
UINFO("TCP service: Add %d \"%s\"", id, fileName.toStdString().c_str());
Q_EMIT addObject(image, id, fileName);
}
else if(serviceType == kRemoveObject)
{
int id;
in >> id;
UINFO("TCP service: Remove %d", id);
Q_EMIT removeObject(id);
}
else
{
UERROR("Unknown service type called %d", serviceType);
ok = false;
}
blockSizes_.remove(client->socketDescriptor());
client->write(QByteArray(ok?"1":"0")); // send acknowledge
}
void TcpServer::displayError(QAbstractSocket::SocketError socketError)
{
switch (socketError)
{
case QAbstractSocket::RemoteHostClosedError:
break;
case QAbstractSocket::HostNotFoundError:
UWARN("CameraTcp: Tcp error: The host was not found. Please "
"check the host name and port settings.\n");
break;
case QAbstractSocket::ConnectionRefusedError:
UWARN("CameraTcp: The connection was refused by the peer. "
"Make sure your images server is running, "
"and check that the host name and port "
"settings are correct.");
break;
default:
//UERROR("The following error occurred: %s.", this->errorString().toStdString().c_str());
break;
}
}
void TcpServer::connectionLost()
{
//printf("[WARNING] CameraTcp: Connection lost!\n");
blockSizes_.remove(((QTcpSocket*)sender())->socketDescriptor());
((QTcpSocket*)sender())->close();
sender()->deleteLater();
} }
} // namespace find_object } // namespace find_object

View File

@ -1,4 +1,5 @@
ADD_SUBDIRECTORY( tcpClient ) ADD_SUBDIRECTORY( tcpClient )
ADD_SUBDIRECTORY( tcpImagesServer ) ADD_SUBDIRECTORY( tcpImagesServer )
ADD_SUBDIRECTORY( tcpRequest ) ADD_SUBDIRECTORY( tcpRequest )
ADD_SUBDIRECTORY( tcpService )
ADD_SUBDIRECTORY( similarity ) ADD_SUBDIRECTORY( similarity )

View File

@ -0,0 +1,33 @@
SET(SRC_FILES
main.cpp
)
SET(INCLUDE_DIRS
${CMAKE_CURRENT_SOURCE_DIR}/../../include
${CMAKE_CURRENT_SOURCE_DIR}
${OpenCV_INCLUDE_DIRS}
)
INCLUDE(${QT_USE_FILE})
SET(LIBRARIES
${OpenCV_LIBS}
${QT_LIBRARIES}
)
# Make sure the compiler can find include files from our library.
INCLUDE_DIRECTORIES(${INCLUDE_DIRS})
# Add binary called "example" that is built from the source file "main.cpp".
# The extension is automatically found.
ADD_EXECUTABLE(tcpService ${SRC_FILES})
TARGET_LINK_LIBRARIES(tcpService find_object ${LIBRARIES})
SET_TARGET_PROPERTIES( tcpService
PROPERTIES OUTPUT_NAME ${PROJECT_PREFIX}-tcpService)
INSTALL(TARGETS tcpService
RUNTIME DESTINATION bin COMPONENT runtime
BUNDLE DESTINATION "${CMAKE_BUNDLE_LOCATION}" COMPONENT runtime)

208
tools/tcpService/main.cpp Normal file
View File

@ -0,0 +1,208 @@
/*
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 <QtNetwork/QNetworkInterface>
#include <QtNetwork/QTcpSocket>
#include <QtCore/QCoreApplication>
#include <QtCore/QFile>
#include <QtCore/QFileInfo>
#include <QtCore/QTime>
#include <opencv2/opencv.hpp>
#include <find_object/TcpServer.h>
void showUsage()
{
printf("\ntcpService [options] port\n"
" Options:\n"
" --add \"image.png\" # Add object (file name + id). Set id=0 "
" will make the server generating an id.\n"
" --remove # Remove object by ID.\n"
" --host #.#.#.# Set host address.\n"
" --help Show this help.\n"
" Examples:\n"
" Add: $ tcpService --add image.png 1 --host 127.0.0.1 4000\n"
" Remove: $ tcpService --remove 1 --host 127.0.0.1 4000\n");
exit(-1);
}
int main(int argc, char * argv[])
{
QString ipAddress;
QString fileName;
int addId = 0;
int removeId = -1;
quint16 port = 0;
for(int i=1; i<argc-1; ++i)
{
if(strcmp(argv[i], "--host") == 0 || strcmp(argv[i], "-host") == 0)
{
++i;
if(i < argc)
{
ipAddress = argv[i];
}
else
{
printf("error parsing --host\n");
showUsage();
}
continue;
}
if(strcmp(argv[i], "--add") == 0 || strcmp(argv[i], "-add") == 0)
{
++i;
if(i < argc-1)
{
fileName = argv[i];
++i;
if(i < argc)
{
addId = atoi(argv[i]);
}
else
{
printf("error parsing --add\n");
}
}
else
{
printf("error parsing --add\n");
showUsage();
}
continue;
}
if(strcmp(argv[i], "--remove") == 0 || strcmp(argv[i], "-remove") == 0)
{
++i;
if(i < argc)
{
removeId = std::atoi(argv[i]);
}
else
{
printf("error parsing --remove\n");
showUsage();
}
continue;
}
if(strcmp(argv[i], "-help") == 0 ||
strcmp(argv[i], "--help") == 0)
{
showUsage();
}
printf("Unrecognized option: %s\n", argv[i]);
showUsage();
}
port = atoi(argv[argc-1]);
if(fileName.isEmpty() && removeId == -1)
{
printf("Arguments --add or --remove should be set.\n");
showUsage();
}
else if(port <=0)
{
printf("Port should be set!\n");
showUsage();
}
if(ipAddress.isEmpty())
{
ipAddress = QHostAddress(QHostAddress::LocalHost).toString();
}
cv::Mat image;
if(!fileName.isEmpty())
{
image = cv::imread(fileName.toStdString());
if(image.empty())
{
printf("Cannot read image from \"%s\".\n", fileName.toStdString().c_str());
showUsage();
}
fileName = QFileInfo(fileName).fileName();
}
QCoreApplication app(argc, argv);
QTcpSocket request;
QObject::connect(&request, SIGNAL(disconnected()), &app, SLOT(quit()));
QObject::connect(&request, SIGNAL(error(QAbstractSocket::SocketError)), &app, SLOT(quit()));
QObject::connect(&request, SIGNAL(bytesWritten(quint64)), &app, SLOT(quit()));
printf("Connecting to \"%s:%d\"...\n", ipAddress.toStdString().c_str(), port);
request.connectToHost(ipAddress, port);
if(!request.waitForConnected())
{
printf("Connecting to \"%s:%d\"... connection failed!\n", ipAddress.toStdString().c_str(), port);
return -1;
}
else
{
printf("Connecting to \"%s:%d\"... connected!\n", ipAddress.toStdString().c_str(), port);
}
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_0);
out << (quint64)0;
if(!image.empty())
{
// publish image
std::vector<unsigned char> buf;
cv::imencode(".png", image, buf);
out << (quint32)find_object::TcpServer::kAddObject;
out << addId;
out << fileName;
quint64 imageSize = buf.size();
out << imageSize;
out.writeRawData((char*)buf.data(), (int)buf.size());
printf("Add object %d \"%s\"\n", addId, fileName.toStdString().c_str());
}
else if(removeId)
{
out << (quint32)find_object::TcpServer::kRemoveObject;
out << removeId;
printf("Remove object %d\n", removeId);
}
out.device()->seek(0);
out << (quint64)(block.size() - sizeof(quint64));
qint64 bytes = request.write(block);
printf("Service published (%d bytes)!\n", (int)bytes);
request.waitForReadyRead();
return 0;
}