Add 'find-object/' from commit '635efcd6220cabc258b88c54b1ae4279035bbe31'

git-subtree-dir: find-object
git-subtree-mainline: 9bd639e88c
git-subtree-split: 635efcd622
This commit is contained in:
2023-02-25 14:20:22 +05:30
142 changed files with 33699 additions and 0 deletions
+7
View File
@@ -0,0 +1,7 @@
ADD_SUBDIRECTORY( tcpClient )
ADD_SUBDIRECTORY( tcpImagesServer )
ADD_SUBDIRECTORY( tcpRequest )
ADD_SUBDIRECTORY( tcpService )
IF(NONFREE)
ADD_SUBDIRECTORY( similarity )
ENDIF(NONFREE)
@@ -0,0 +1,28 @@
SET(SRC_FILES
main.cpp
)
SET(INCLUDE_DIRS
${OpenCV_INCLUDE_DIRS}
)
SET(LIBRARIES
${OpenCV_LIBS}
)
# Make sure the compiler can find include files from our library.
INCLUDE_DIRECTORIES(${INCLUDE_DIRS})
# Add binary called "similarity" that is built from the source file "main.cpp".
# The extension is automatically found.
ADD_EXECUTABLE(similarity ${SRC_FILES})
TARGET_LINK_LIBRARIES(similarity ${LIBRARIES})
SET_TARGET_PROPERTIES( similarity
PROPERTIES OUTPUT_NAME ${PROJECT_PREFIX}-similarity)
INSTALL(TARGETS similarity
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT runtime
BUNDLE DESTINATION "${CMAKE_BUNDLE_LOCATION}" COMPONENT runtime)
+219
View File
@@ -0,0 +1,219 @@
/*
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 <stdio.h>
#include <stdlib.h>
// OpenCV stuff
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/calib3d/calib3d.hpp> // for homography
#include <opencv2/opencv_modules.hpp>
#ifdef HAVE_OPENCV_NONFREE
#if CV_MAJOR_VERSION == 2 && CV_MINOR_VERSION >=4
#include <opencv2/nonfree/gpu.hpp>
#include <opencv2/nonfree/features2d.hpp>
#endif
#endif
#ifdef HAVE_OPENCV_XFEATURES2D
#include <opencv2/xfeatures2d.hpp>
#include <opencv2/xfeatures2d/cuda.hpp>
#endif
void showUsage()
{
printf(
"\n"
"Return similarity between two images (the number of similar features between the images).\n"
"Usage :\n"
" ./find_object-similarity [option] object.png scene.png\n"
"Options: \n"
" -inliers return inliers percentage : inliers / (inliers + outliers)\n"
" -quiet don't show messages\n");
exit(-1);
}
enum {mTotal, mInliers};
int main(int argc, char * argv[])
{
bool quiet = false;
int method = mTotal; //total matches
if(argc<3)
{
printf("Two images required!\n");
showUsage();
}
else if(argc>3)
{
for(int i=1; i<argc-2; ++i)
{
if(std::string(argv[i]).compare("-inliers") == 0)
{
method = mInliers;
}
else if(std::string(argv[i]).compare("-quiet") == 0)
{
quiet = true;
}
else
{
printf("Option %s not recognized!", argv[1]);
showUsage();
}
}
}
//Load as grayscale
cv::Mat objectImg = cv::imread(argv[argc-2], cv::IMREAD_GRAYSCALE);
cv::Mat sceneImg = cv::imread(argv[argc-1], cv::IMREAD_GRAYSCALE);
int value = 0;
if(!objectImg.empty() && !sceneImg.empty())
{
std::vector<cv::KeyPoint> objectKeypoints;
std::vector<cv::KeyPoint> sceneKeypoints;
cv::Mat objectDescriptors;
cv::Mat sceneDescriptors;
#if CV_MAJOR_VERSION < 3
////////////////////////////
// EXTRACT KEYPOINTS
////////////////////////////
cv::SIFT sift;
sift.detect(objectImg, objectKeypoints);
sift.detect(sceneImg, sceneKeypoints);
////////////////////////////
// EXTRACT DESCRIPTORS
////////////////////////////
sift.compute(objectImg, objectKeypoints, objectDescriptors);
sift.compute(sceneImg, sceneKeypoints, sceneDescriptors);
#else
////////////////////////////
// EXTRACT KEYPOINTS
////////////////////////////
#if (CV_MAJOR_VERSION == 4 && CV_MINOR_VERSION <= 3) || (CV_MAJOR_VERSION == 3 && (CV_MINOR_VERSION < 4 || (CV_MINOR_VERSION==4 && CV_SUBMINOR_VERSION<11)))
cv::Ptr<cv::xfeatures2d::SIFT> sift = cv::xfeatures2d::SIFT::create();
#else
cv::Ptr<cv::SIFT> sift = cv::SIFT::create();
#endif
sift->detect(objectImg, objectKeypoints);
sift->detect(sceneImg, sceneKeypoints);
////////////////////////////
// EXTRACT DESCRIPTORS
////////////////////////////
sift->compute(objectImg, objectKeypoints, objectDescriptors);
sift->compute(sceneImg, sceneKeypoints, sceneDescriptors);
#endif
////////////////////////////
// NEAREST NEIGHBOR MATCHING USING FLANN LIBRARY (included in OpenCV)
////////////////////////////
cv::Mat results;
cv::Mat dists;
std::vector<std::vector<cv::DMatch> > matches;
int k=2; // find the 2 nearest neighbors
// Create Flann KDTree index
cv::flann::Index flannIndex(sceneDescriptors, cv::flann::KDTreeIndexParams(), cvflann::FLANN_DIST_EUCLIDEAN);
results = cv::Mat(objectDescriptors.rows, k, CV_32SC1); // Results index
dists = cv::Mat(objectDescriptors.rows, k, CV_32FC1); // Distance results are CV_32FC1
// search (nearest neighbor)
flannIndex.knnSearch(objectDescriptors, results, dists, k, cv::flann::SearchParams() );
////////////////////////////
// PROCESS NEAREST NEIGHBOR RESULTS
////////////////////////////
// Find correspondences by NNDR (Nearest Neighbor Distance Ratio)
float nndrRatio = 0.6f;
std::vector<cv::Point2f> mpts_1, mpts_2; // Used for homography
std::vector<int> indexes_1, indexes_2; // Used for homography
std::vector<uchar> outlier_mask; // Used for homography
// Check if this descriptor matches with those of the objects
for(int i=0; i<objectDescriptors.rows; ++i)
{
// Apply NNDR
if(dists.at<float>(i,0) <= nndrRatio * dists.at<float>(i,1))
{
mpts_1.push_back(objectKeypoints.at(i).pt);
indexes_1.push_back(i);
mpts_2.push_back(sceneKeypoints.at(results.at<int>(i,0)).pt);
indexes_2.push_back(results.at<int>(i,0));
}
}
if(method == mInliers)
{
// FIND HOMOGRAPHY
unsigned int minInliers = 8;
if(mpts_1.size() >= minInliers)
{
cv::Mat H = findHomography(mpts_1,
mpts_2,
cv::RANSAC,
1.0,
outlier_mask);
int inliers=0, outliers=0;
for(unsigned int k=0; k<mpts_1.size();++k)
{
if(outlier_mask.at(k))
{
++inliers;
}
else
{
++outliers;
}
}
if(!quiet)
printf("Total=%d Inliers=%d Outliers=%d\n", (int)mpts_1.size(), inliers, outliers);
value = (inliers*100) / (inliers+outliers);
}
}
else
{
value = (int)mpts_1.size();
}
}
else
{
printf("Images are not valid!\n");
showUsage();
}
if(!quiet)
printf("Similarity = %d\n", value);
return value;
}
@@ -0,0 +1,49 @@
SET(headers_ui
TcpClient.h
)
IF(QT4_FOUND)
QT4_WRAP_CPP(moc_srcs ${headers_ui})
ELSE()
QT5_WRAP_CPP(moc_srcs ${headers_ui})
ENDIF()
SET(SRC_FILES
TcpClient.cpp
main.cpp
${moc_srcs}
)
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
${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(tcpClient ${SRC_FILES})
TARGET_LINK_LIBRARIES(tcpClient ${LIBRARIES})
IF(Qt5_FOUND)
QT5_USE_MODULES(tcpClient Widgets Core Gui Network PrintSupport)
ENDIF(Qt5_FOUND)
SET_TARGET_PROPERTIES( tcpClient
PROPERTIES OUTPUT_NAME ${PROJECT_PREFIX}-tcpClient)
INSTALL(TARGETS tcpClient
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT runtime
BUNDLE DESTINATION "${CMAKE_BUNDLE_LOCATION}" COMPONENT runtime)
+164
View File
@@ -0,0 +1,164 @@
/*
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 "TcpClient.h"
#include "find_object/DetectionInfo.h"
#include <opencv2/opencv.hpp>
#include <QtGui/QTransform>
#include <QtCore/QPointF>
#include <QtCore/QTime>
TcpClient::TcpClient(QObject *parent) :
QTcpSocket(parent),
blockSize_(0)
{
connect(this, SIGNAL(readyRead()), this, SLOT(readReceivedData()));
connect(this, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(displayError(QAbstractSocket::SocketError)));
connect(this, SIGNAL(disconnected()), this, SLOT(connectionLost()));
}
void TcpClient::readReceivedData()
{
QDataStream in(this);
in.setVersion(QDataStream::Qt_4_0);
if (blockSize_ == 0)
{
if (this->bytesAvailable() < (int)sizeof(quint16))
{
return;
}
in >> blockSize_;
}
if (this->bytesAvailable() < blockSize_)
{
return;
}
blockSize_ = 0;
find_object::DetectionInfo info;
in >> info;
printf("---\n");
if(info.objDetected_.size() == 0)
{
printf("(%s) No objects detected.\n",
QTime::currentTime().toString("HH:mm:ss.zzz").toStdString().c_str());
}
else
{
QMultiMap<int, QSize>::const_iterator iterSizes = info.objDetectedSizes_.constBegin();
for(QMultiMap<int, QTransform>::const_iterator iter=info.objDetected_.constBegin();
iter!=info.objDetected_.constEnd();
++iter)
{
// get data
int id = (int)iter.key();
float objectWidth = iterSizes.value().width();
float objectHeight = iterSizes.value().height();
// Find corners Qt
QTransform qtHomography = iter.value();
QPointF qtTopLeft = qtHomography.map(QPointF(0,0));
QPointF qtTopRight = qtHomography.map(QPointF(objectWidth,0));
QPointF qtBottomLeft = qtHomography.map(QPointF(0,objectHeight));
QPointF qtBottomRight = qtHomography.map(QPointF(objectWidth,objectHeight));
printf("(%s) Object %d detected, Qt corners at (%f,%f) (%f,%f) (%f,%f) (%f,%f)\n",
QTime::currentTime().toString("HH:mm:ss.zzz").toStdString().c_str(),
id,
qtTopLeft.x(), qtTopLeft.y(),
qtTopRight.x(), qtTopRight.y(),
qtBottomLeft.x(), qtBottomLeft.y(),
qtBottomRight.x(), qtBottomRight.y());
// Example with OpenCV
if(0)
{
// Find corners OpenCV
cv::Mat cvHomography(3, 3, CV_32F);
cvHomography.at<float>(0,0) = qtHomography.m11();
cvHomography.at<float>(1,0) = qtHomography.m12();
cvHomography.at<float>(2,0) = qtHomography.m13();
cvHomography.at<float>(0,1) = qtHomography.m21();
cvHomography.at<float>(1,1) = qtHomography.m22();
cvHomography.at<float>(2,1) = qtHomography.m23();
cvHomography.at<float>(0,2) = qtHomography.m31();
cvHomography.at<float>(1,2) = qtHomography.m32();
cvHomography.at<float>(2,2) = qtHomography.m33();
std::vector<cv::Point2f> inPts, outPts;
inPts.push_back(cv::Point2f(0,0));
inPts.push_back(cv::Point2f(objectWidth,0));
inPts.push_back(cv::Point2f(0,objectHeight));
inPts.push_back(cv::Point2f(objectWidth,objectHeight));
cv::perspectiveTransform(inPts, outPts, cvHomography);
printf("(%s) Object %d detected, CV corners at (%f,%f) (%f,%f) (%f,%f) (%f,%f)\n",
QTime::currentTime().toString("HH:mm:ss.zzz").toStdString().c_str(),
id,
outPts.at(0).x, outPts.at(0).y,
outPts.at(1).x, outPts.at(1).y,
outPts.at(2).x, outPts.at(2).y,
outPts.at(3).x, outPts.at(3).y);
}
++iterSizes;
}
}
}
void TcpClient::displayError(QAbstractSocket::SocketError socketError)
{
switch (socketError)
{
case QAbstractSocket::RemoteHostClosedError:
break;
case QAbstractSocket::HostNotFoundError:
printf("Tcp error: The host was not found. Please "
"check the host name and port settings.\n");
break;
case QAbstractSocket::ConnectionRefusedError:
printf("The connection was refused by the peer. "
"Make sure Find-Object is running, "
"and check that the host name and port "
"settings are correct.\n");
break;
default:
printf("The following error occurred: %s.\n", this->errorString().toStdString().c_str());
break;
}
}
void TcpClient::connectionLost()
{
printf("Connection lost!\n");
}
+48
View File
@@ -0,0 +1,48 @@
/*
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.
*/
#ifndef TCPCLIENT_H_
#define TCPCLIENT_H_
#include <QtNetwork/QTcpSocket>
class TcpClient : public QTcpSocket
{
Q_OBJECT;
public:
TcpClient(QObject * parent = 0);
private Q_SLOTS:
void readReceivedData();
void displayError(QAbstractSocket::SocketError socketError);
void connectionLost();
private:
quint16 blockSize_;
};
#endif /* TCPCLIENT_H_ */
+83
View File
@@ -0,0 +1,83 @@
/*
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 <QtCore/QCoreApplication>
#include "TcpClient.h"
void showUsage()
{
printf("\ntcpObjectsClient [hostname] port\n");
exit(-1);
}
int main(int argc, char * argv[])
{
if(argc < 2 || argc > 3)
{
showUsage();
}
QString ipAddress;
quint16 port = 0;
if(argc == 2)
{
port = atoi(argv[1]);
}
else if(argc == 3)
{
ipAddress = argv[1];
port = atoi(argv[2]);
}
if(ipAddress.isEmpty())
{
ipAddress = QHostAddress(QHostAddress::LocalHost).toString();
}
QCoreApplication app(argc, argv);
printf("Connecting to \"%s:%d\"...\n", ipAddress.toStdString().c_str(), port);
TcpClient client;
client.connectToHost(ipAddress, port);
if(client.waitForConnected())
{
printf("Connecting to \"%s:%d\"... connected!\n", ipAddress.toStdString().c_str(), port);
app.exec();
}
else
{
printf("Connecting to \"%s:%d\"... connection failed!\n", ipAddress.toStdString().c_str(), port);
}
return 0;
}
@@ -0,0 +1,50 @@
SET(headers_ui
ImagesTcpServer.h
)
IF(QT4_FOUND)
QT4_WRAP_CPP(moc_srcs ${headers_ui})
ELSE()
QT5_WRAP_CPP(moc_srcs ${headers_ui})
ENDIF()
SET(SRC_FILES
ImagesTcpServer.cpp
main.cpp
${moc_srcs}
)
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
${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(tcpImagesServer ${SRC_FILES})
TARGET_LINK_LIBRARIES(tcpImagesServer find_object ${LIBRARIES})
IF(Qt5_FOUND)
QT5_USE_MODULES(tcpImagesServer Widgets Core Gui Network PrintSupport)
ENDIF(Qt5_FOUND)
SET_TARGET_PROPERTIES( tcpImagesServer
PROPERTIES OUTPUT_NAME ${PROJECT_PREFIX}-tcpImagesServer)
INSTALL(TARGETS tcpImagesServer
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT runtime
BUNDLE DESTINATION "${CMAKE_BUNDLE_LOCATION}" COMPONENT runtime)
@@ -0,0 +1,112 @@
/*
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 "find_object/Settings.h"
#include "find_object/QtOpenCV.h"
#include "ImagesTcpServer.h"
#include <QtNetwork/QNetworkInterface>
#include <QtNetwork/QTcpSocket>
#include <QtGui/QTransform>
ImagesTcpServer::ImagesTcpServer(float hz, const QString & path, QObject * parent) :
QTcpSocket(parent)
{
// Set camera parameters
find_object::Settings::setCamera_4imageRate(hz);
find_object::Settings::setCamera_5mediaPath(path);
connect(&camera_, SIGNAL(imageReceived(const cv::Mat &)), this, SLOT(publishImage(const cv::Mat &)));
connect(this, SIGNAL(connected()), this, SLOT(startCamera()));
}
QHostAddress ImagesTcpServer::getHostAddress()
{
QHostAddress hostAddress;
QList<QHostAddress> ipAddressesList = QNetworkInterface::allAddresses();
// use the first non-localhost IPv4 address
for (int i = 0; i < ipAddressesList.size(); ++i)
{
if (ipAddressesList.at(i) != QHostAddress::LocalHost && ipAddressesList.at(i).toIPv4Address())
{
hostAddress = ipAddressesList.at(i).toString();
break;
}
}
// if we did not find one, use IPv4 localhost
if (hostAddress.isNull())
{
hostAddress = QHostAddress(QHostAddress::LocalHost);
}
return hostAddress;
}
void ImagesTcpServer::publishImage(const cv::Mat & image)
{
if(image.empty())
{
printf("No more images...\n");
camera_.pause();
Q_EMIT connectionLost();
}
else
{
if(this->waitForConnected())
{
std::vector<unsigned char> buf;
cv::imencode(".png", image, buf);
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_0);
out << (quint64)0;
out.writeRawData((char*)buf.data(), (int)buf.size());
out.device()->seek(0);
out << (quint64)(block.size() - sizeof(quint64));
this->write(block);
}
else
{
printf("Lost connection...\n");
camera_.pause();
Q_EMIT connectionLost();
}
}
}
void ImagesTcpServer::startCamera()
{
if(!camera_.isRunning())
{
printf("Start...\n");
camera_.start();
}
}
@@ -0,0 +1,55 @@
/*
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.
*/
#ifndef IMAGESTCPSERVER_H_
#define IMAGESTCPSERVER_H_
#include "find_object/Camera.h"
#include <QtNetwork/QTcpSocket>
class ImagesTcpServer : public QTcpSocket
{
Q_OBJECT
public:
static QHostAddress getHostAddress();
public:
ImagesTcpServer(float hz = 10.0f, const QString & path = "", QObject * parent = 0);
private Q_SLOTS:
void startCamera();
void publishImage(const cv::Mat & image);
Q_SIGNALS:
void connectionLost();
private:
find_object::Camera camera_;
};
#endif /* TCPCLIENT_H_ */
+129
View File
@@ -0,0 +1,129 @@
/*
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 <QtCore/QCoreApplication>
#include "ImagesTcpServer.h"
void showUsage()
{
printf("\ntcpImagesServer [options] port\n"
" Options:\n"
" --hz #.# Image rate (default 10 Hz).\n"
" --host #.#.#.# Set host address.\n"
" --path \"\" Set a path of a directory of images or a video file.\n");
exit(-1);
}
int main(int argc, char * argv[])
{
QString ipAddress;
float hz = 10.0f;
QString path;
if(argc < 2)
{
showUsage();
}
for(int i=1; i<argc-1; ++i)
{
if(strcmp(argv[i], "-hz") == 0 || strcmp(argv[i], "--hz") == 0)
{
++i;
if(i < argc-1)
{
hz = std::atof(argv[i]);
if(hz < 0.0f)
{
printf("[ERROR] Image rate not valid : %s\n", argv[i]);
showUsage();
}
}
else
{
showUsage();
}
continue;
}
if(strcmp(argv[i], "-host") == 0 || strcmp(argv[i], "--host") == 0)
{
++i;
if(i < argc-1)
{
ipAddress = argv[i];
}
else
{
showUsage();
}
continue;
}
if(strcmp(argv[i], "-path") == 0 || strcmp(argv[i], "--path") == 0)
{
++i;
if(i < argc-1)
{
path = argv[i];
}
else
{
showUsage();
}
continue;
}
printf("Unrecognized option: %s\n", argv[i]);
showUsage();
}
quint16 port = std::atoi(argv[argc-1]);
if(!path.isEmpty())
{
printf("Using images from path \"%s\"\n", path.toStdString().c_str());
}
QCoreApplication app(argc, argv);
ImagesTcpServer server(hz, path);
QObject::connect(&server, SIGNAL(connectionLost()), &app, SLOT(quit()));
if(ipAddress.isEmpty())
{
ipAddress = server.getHostAddress().toString();
}
server.connectToHost(ipAddress, port);
if(!server.waitForReadyRead())
{
printf("ERROR: Unable to connect to %s:%d\n", ipAddress.toStdString().c_str(), port);
return -1;
}
return app.exec();
}
@@ -0,0 +1,51 @@
SET(headers_ui
TcpResponse.h
)
IF(QT4_FOUND)
QT4_WRAP_CPP(moc_srcs ${headers_ui})
ELSE()
QT5_WRAP_CPP(moc_srcs ${headers_ui})
ENDIF()
SET(SRC_FILES
TcpResponse.cpp
main.cpp
${moc_srcs}
)
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
${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(tcpRequest ${SRC_FILES})
TARGET_LINK_LIBRARIES(tcpRequest find_object ${LIBRARIES})
IF(Qt5_FOUND)
QT5_USE_MODULES(tcpRequest Widgets Core Gui Network PrintSupport)
ENDIF(Qt5_FOUND)
SET_TARGET_PROPERTIES( tcpRequest
PROPERTIES OUTPUT_NAME ${PROJECT_PREFIX}-tcpRequest)
INSTALL(TARGETS tcpRequest
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT runtime
BUNDLE DESTINATION "${CMAKE_BUNDLE_LOCATION}" COMPONENT runtime)
@@ -0,0 +1,99 @@
/*
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 "TcpResponse.h"
#include <opencv2/opencv.hpp>
#include <QtGui/QTransform>
#include <QtCore/QPointF>
#include <QtCore/QTime>
TcpResponse::TcpResponse(QObject *parent) :
QTcpSocket(parent),
blockSize_(0),
dataReceived_(false)
{
connect(this, SIGNAL(readyRead()), this, SLOT(readReceivedData()));
connect(this, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(displayError(QAbstractSocket::SocketError)));
connect(this, SIGNAL(disconnected()), this, SLOT(connectionLost()));
}
void TcpResponse::readReceivedData()
{
QDataStream in(this);
in.setVersion(QDataStream::Qt_4_0);
if (blockSize_ == 0)
{
if (this->bytesAvailable() < (int)sizeof(quint16))
{
return;
}
in >> blockSize_;
}
if (this->bytesAvailable() < blockSize_)
{
return;
}
blockSize_ = 0;
in >> info_;
dataReceived_ = true;
Q_EMIT detectionReceived();
}
void TcpResponse::displayError(QAbstractSocket::SocketError socketError)
{
switch (socketError)
{
case QAbstractSocket::RemoteHostClosedError:
break;
case QAbstractSocket::HostNotFoundError:
printf("Tcp error: The host was not found. Please "
"check the host name and port settings.\n");
break;
case QAbstractSocket::ConnectionRefusedError:
printf("The connection was refused by the peer. "
"Make sure Find-Object is running, "
"and check that the host name and port "
"settings are correct.\n");
break;
default:
printf("The following error occurred: %s.\n", this->errorString().toStdString().c_str());
break;
}
}
void TcpResponse::connectionLost()
{
printf("Connection lost!\n");
}
@@ -0,0 +1,60 @@
/*
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.
*/
#ifndef TCPRESPONSE_H_
#define TCPRESPONSE_H_
#include "find_object/DetectionInfo.h"
#include <QtNetwork/QTcpSocket>
#include <QtCore/QMultiMap>
#include <QtGui/QTransform>
#include <QtCore/QRect>
class TcpResponse : public QTcpSocket
{
Q_OBJECT;
public:
TcpResponse(QObject * parent = 0);
const find_object::DetectionInfo & info() const {return info_;}
bool dataReceived() const {return dataReceived_;}
private Q_SLOTS:
void readReceivedData();
void displayError(QAbstractSocket::SocketError socketError);
void connectionLost();
Q_SIGNALS:
void detectionReceived();
private:
quint16 blockSize_;
find_object::DetectionInfo info_;
bool dataReceived_;
};
#endif /* TCPCLIENT_H_ */
+300
View File
@@ -0,0 +1,300 @@
/*
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 <QtCore/QCoreApplication>
#include <QtCore/QFile>
#include <QtCore/QTime>
#include <opencv2/opencv.hpp>
#include <find_object/TcpServer.h>
#include "TcpResponse.h"
#include "find_object/JsonWriter.h"
void showUsage()
{
printf("\ntcpRequest [options] --scene image.png --out # --in #\n"
"\ntcpRequest [options] --scene image.png --port #\n"
" \"out\" is the port to which the image is sent.\n"
" \"in\" is the port from which the detection is received.\n"
" \"port\" is the bidirectional port from which the image is sent AND the detection is received.\n"
" Options:\n"
" --host #.#.#.# Set host address.\n"
" --json \"path\" Path to an output JSON file.\n"
" --help Show this help.\n");
exit(-1);
}
int main(int argc, char * argv[])
{
QString ipAddress;
QString scenePath;
QString jsonPath;
quint16 portOut = 0;
quint16 portIn = 0;
quint16 bidrectionalPort = 0;
for(int i=1; i<argc; ++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], "--scene") == 0 || strcmp(argv[i], "-scene") == 0)
{
++i;
if(i < argc)
{
scenePath = argv[i];
}
else
{
printf("error parsing --scene\n");
showUsage();
}
continue;
}
if(strcmp(argv[i], "--out") == 0 || strcmp(argv[i], "-out") == 0)
{
++i;
if(i < argc)
{
portOut = std::atoi(argv[i]);
}
else
{
printf("error parsing --out\n");
showUsage();
}
continue;
}
if(strcmp(argv[i], "--in") == 0 || strcmp(argv[i], "-in") == 0)
{
++i;
if(i < argc)
{
portIn = std::atoi(argv[i]);
}
else
{
printf("error parsing --in\n");
showUsage();
}
continue;
}
if(strcmp(argv[i], "--port") == 0 || strcmp(argv[i], "-port") == 0)
{
++i;
if(i < argc)
{
bidrectionalPort = std::atoi(argv[i]);
}
else
{
printf("error parsing --port\n");
showUsage();
}
continue;
}
if(strcmp(argv[i], "--json") == 0 || strcmp(argv[i], "-json") == 0)
{
++i;
if(i < argc)
{
jsonPath = argv[i];
}
else
{
printf("error parsing --json\n");
showUsage();
}
continue;
}
if(strcmp(argv[i], "-help") == 0 ||
strcmp(argv[i], "--help") == 0)
{
showUsage();
}
printf("Unrecognized option: %s\n", argv[i]);
showUsage();
}
if(bidrectionalPort == 0 && portOut == 0 && portIn == 0)
{
printf("Arguments --port or [--in and --out] should be set.\n");
showUsage();
}
else if(portOut == 0 && bidrectionalPort == 0)
{
printf("Argument --out should be set.\n");
showUsage();
}
else if(portIn == 0 && bidrectionalPort == 0)
{
printf("Argument --in should be set.\n");
showUsage();
}
else if(scenePath.isEmpty())
{
printf("Argument --scene should be set.\n");
showUsage();
}
if(ipAddress.isEmpty())
{
ipAddress = QHostAddress(QHostAddress::LocalHost).toString();
}
cv::Mat image = cv::imread(scenePath.toStdString());
if(image.empty())
{
printf("Cannot read image from \"%s\".\n", scenePath.toStdString().c_str());
showUsage();
}
QCoreApplication app(argc, argv);
QTcpSocket request;
TcpResponse response;
QObject::connect(&response, SIGNAL(detectionReceived()), &app, SLOT(quit()));
QObject::connect(&response, SIGNAL(disconnected()), &app, SLOT(quit()));
QObject::connect(&response, SIGNAL(error(QAbstractSocket::SocketError)), &app, SLOT(quit()));
QTcpSocket * requestPtr = &request;
if(bidrectionalPort == 0)
{
QObject::connect(&request, SIGNAL(disconnected()), &app, SLOT(quit()));
QObject::connect(&request, SIGNAL(error(QAbstractSocket::SocketError)), &app, SLOT(quit()));
request.connectToHost(ipAddress, portOut);
response.connectToHost(ipAddress, portIn);
if(!request.waitForConnected())
{
printf("ERROR: Unable to connect to %s:%d\n", ipAddress.toStdString().c_str(), portOut);
return -1;
}
}
else
{
printf("Using bidirectional port\n");
requestPtr = &response;
response.connectToHost(ipAddress, bidrectionalPort);
}
if(!response.waitForConnected())
{
printf("ERROR: Unable to connect to %s:%d\n", ipAddress.toStdString().c_str(), bidrectionalPort?bidrectionalPort:portIn);
return -1;
}
// publish image
std::vector<unsigned char> buf;
cv::imencode(".png", image, buf);
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_0);
out << (quint64)0;
if(bidrectionalPort)
{
out << (quint32)find_object::TcpServer::kDetectObject;
}
out.writeRawData((char*)buf.data(), (int)buf.size());
out.device()->seek(0);
out << (quint64)(block.size() - sizeof(quint64));
qint64 bytes = requestPtr->write(block);
printf("Image published (%d bytes), waiting for response...\n", (int)bytes);
QTime time;
time.start();
// wait for response
if(bidrectionalPort)
{
requestPtr->waitForBytesWritten();
response.waitForReadyRead();
}
else
{
app.exec();
}
if(response.dataReceived())
{
printf("Response received! (%d ms)\n", time.elapsed());
// print detected objects
if(response.info().objDetected_.size())
{
QList<int> ids = response.info().objDetected_.uniqueKeys();
for(int i=0; i<ids.size(); ++i)
{
int count = response.info().objDetected_.count(ids[i]);
if(count == 1)
{
printf("Object %d detected.\n", ids[i]);
}
else
{
printf("Object %d detected %d times.\n", ids[i], count);
}
}
}
else
{
printf("No objects detected.\n");
}
// write json
if(!jsonPath.isEmpty())
{
find_object::JsonWriter::write(response.info(), jsonPath);
printf("JSON written to \"%s\"\n", jsonPath.toStdString().c_str());
}
}
else
{
printf("Failed to receive a response...\n");
return -1;
}
return 0;
}
@@ -0,0 +1,38 @@
SET(SRC_FILES
main.cpp
)
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
${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})
IF(Qt5_FOUND)
QT5_USE_MODULES(tcpService Widgets Core Gui Network PrintSupport)
ENDIF(Qt5_FOUND)
SET_TARGET_PROPERTIES( tcpService
PROPERTIES OUTPUT_NAME ${PROJECT_PREFIX}-tcpService)
INSTALL(TARGETS tcpService
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT runtime
BUNDLE DESTINATION "${CMAKE_BUNDLE_LOCATION}" COMPONENT runtime)
+208
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\n"
" 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()));
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.waitForBytesWritten();
request.waitForReadyRead();
return 0;
}