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:
+72
-23
@@ -46,7 +46,8 @@ FindObject::FindObject(QObject * parent) :
|
||||
QObject(parent),
|
||||
vocabulary_(new Vocabulary()),
|
||||
detector_(Settings::createKeypointDetector()),
|
||||
extractor_(Settings::createDescriptorExtractor())
|
||||
extractor_(Settings::createDescriptorExtractor()),
|
||||
sessionModified_(false)
|
||||
{
|
||||
qRegisterMetaType<find_object::DetectionInfo>("find_object::DetectionInfo");
|
||||
UASSERT(detector_ != 0 && extractor_ != 0);
|
||||
@@ -101,7 +102,7 @@ bool FindObject::loadSession(const QString & path)
|
||||
// this will fill objectsDescriptors_ matrix
|
||||
updateVocabulary();
|
||||
}
|
||||
|
||||
sessionModified_ = false;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
@@ -111,7 +112,7 @@ bool FindObject::loadSession(const QString & path)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FindObject::saveSession(const QString & path) const
|
||||
bool FindObject::saveSession(const QString & path)
|
||||
{
|
||||
if(!path.isEmpty() && QFileInfo(path).suffix().compare("bin") == 0)
|
||||
{
|
||||
@@ -132,6 +133,7 @@ bool FindObject::saveSession(const QString & path) const
|
||||
}
|
||||
|
||||
file.close();
|
||||
sessionModified_ = false;
|
||||
return true;
|
||||
}
|
||||
UERROR("Path \"%s\" not valid (should be *.bin)", path.toStdString().c_str());
|
||||
@@ -243,6 +245,28 @@ void FindObject::removeAllObjects()
|
||||
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()
|
||||
{
|
||||
delete detector_;
|
||||
@@ -561,39 +585,63 @@ private:
|
||||
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();
|
||||
if(threadCounts == 0)
|
||||
{
|
||||
threadCounts = objects_.size();
|
||||
threadCounts = objectsList.size();
|
||||
}
|
||||
|
||||
QTime time;
|
||||
time.start();
|
||||
UINFO("Features extraction from %d objects...", objects_.size());
|
||||
QList<ObjSignature*> objectsList = objects_.values();
|
||||
for(int i=0; i<objectsList.size(); i+=threadCounts)
|
||||
|
||||
if(objectsList.size())
|
||||
{
|
||||
QVector<ExtractFeaturesThread*> threads;
|
||||
for(int k=i; k<i+threadCounts && k<objectsList.size(); ++k)
|
||||
UINFO("Features extraction from %d objects...", objectsList.size());
|
||||
for(int i=0; i<objectsList.size(); i+=threadCounts)
|
||||
{
|
||||
threads.push_back(new ExtractFeaturesThread(detector_, extractor_, objectsList.at(k)->id(), objectsList.at(k)->image()));
|
||||
threads.back()->start();
|
||||
}
|
||||
|
||||
for(int j=0; j<threads.size(); ++j)
|
||||
{
|
||||
threads[j]->wait();
|
||||
|
||||
int id = threads[j]->objectId();
|
||||
|
||||
objects_.value(id)->setData(threads[j]->keypoints(), threads[j]->descriptors());
|
||||
QVector<ExtractFeaturesThread*> threads;
|
||||
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()));
|
||||
threads.back()->start();
|
||||
}
|
||||
|
||||
for(int j=0; j<threads.size(); ++j)
|
||||
{
|
||||
threads[j]->wait();
|
||||
|
||||
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
|
||||
{
|
||||
@@ -667,6 +715,7 @@ void FindObject::updateVocabulary()
|
||||
|
||||
if(Settings::getGeneral_invertedSearch())
|
||||
{
|
||||
sessionModified_ = true;
|
||||
QTime time;
|
||||
time.start();
|
||||
bool incremental = Settings::getGeneral_vocabularyIncremental();
|
||||
|
||||
+95
-35
@@ -311,6 +311,10 @@ void MainWindow::setupTCPServer()
|
||||
ui_->label_ipAddress->setText(tcpServer_->getHostAddress().toString());
|
||||
ui_->label_port->setNum(tcpServer_->getPort());
|
||||
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)
|
||||
@@ -459,7 +463,7 @@ bool MainWindow::saveSettings(const QString & path) const
|
||||
|
||||
int MainWindow::loadObjects(const QString & dirPath)
|
||||
{
|
||||
int loadedObjects = 0;
|
||||
QList<int> loadedObjects;
|
||||
QString formats = Settings::getGeneral_imageFormats().remove('*').remove('.');
|
||||
UDirectory dir(dirPath.toStdString(), formats.toStdString());
|
||||
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
|
||||
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)
|
||||
@@ -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()
|
||||
{
|
||||
qDeleteAll(objWidgets_);
|
||||
@@ -677,12 +694,20 @@ void MainWindow::addObjectsFromFiles(const QStringList & fileNames)
|
||||
{
|
||||
if(fileNames.size())
|
||||
{
|
||||
QList<int> ids;
|
||||
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())));
|
||||
}
|
||||
|
||||
bool MainWindow::addObjectFromFile(const QString & filePath)
|
||||
int MainWindow::addObjectFromFile(const QString & filePath)
|
||||
{
|
||||
const ObjSignature * s = findObject_->addObject(filePath);
|
||||
if(s)
|
||||
@@ -701,12 +726,36 @@ bool MainWindow::addObjectFromFile(const QString & filePath)
|
||||
ui_->actionSave_objects->setEnabled(true);
|
||||
ui_->actionSave_session->setEnabled(true);
|
||||
this->showObject(obj);
|
||||
return true;
|
||||
return s->id();
|
||||
}
|
||||
else
|
||||
{
|
||||
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()
|
||||
{
|
||||
this->statusBar()->showMessage(tr("Updating %1 objects...").arg(findObject_->objects().size()));
|
||||
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();
|
||||
updateObjects(objWidgets_.keys());
|
||||
}
|
||||
|
||||
void MainWindow::updateVocabulary()
|
||||
@@ -1374,7 +1434,7 @@ void MainWindow::notifyParametersChanged(const QStringList & paramChanged)
|
||||
{
|
||||
if(detectorDescriptorParamsChanged)
|
||||
{
|
||||
this->updateObjects();
|
||||
this->updateObjects(objWidgets_.keys());
|
||||
}
|
||||
else if(nearestNeighborParamsChanged)
|
||||
{
|
||||
|
||||
+96
-2
@@ -30,6 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <QtNetwork/QNetworkInterface>
|
||||
#include <QtNetwork/QTcpSocket>
|
||||
#include <QtGui/QTransform>
|
||||
#include <opencv2/highgui/highgui.hpp>
|
||||
|
||||
namespace find_object {
|
||||
|
||||
@@ -98,8 +99,101 @@ void TcpServer::publishDetectionInfo(const DetectionInfo & info)
|
||||
|
||||
void TcpServer::addClient()
|
||||
{
|
||||
QTcpSocket * client = this->nextPendingConnection();
|
||||
connect(client, SIGNAL(disconnected()), client, SLOT(deleteLater()));
|
||||
while(this->hasPendingConnections())
|
||||
{
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user