Created a library find_object for convenience
Updated version to 0.5.0 git-svn-id: http://find-object.googlecode.com/svn/trunk/find_object@357 620bd6b2-0a58-f614-fd9a-1bd335dccda9
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (C) 2011, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
|
||||
*/
|
||||
|
||||
#ifndef CAMERA_H_
|
||||
#define CAMERA_H_
|
||||
|
||||
#include "find_object/FindObjectExp.h" // DLL export/import defines
|
||||
|
||||
#include <opencv2/highgui/highgui.hpp>
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtGui/QImage>
|
||||
|
||||
class CameraTcpClient;
|
||||
|
||||
class FINDOBJECT_EXP Camera : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
Camera(QObject * parent = 0);
|
||||
virtual ~Camera();
|
||||
|
||||
virtual bool start();
|
||||
virtual void stop();
|
||||
virtual bool isRunning() {return cameraTimer_.isActive();}
|
||||
|
||||
void pause();
|
||||
int getTotalFrames();
|
||||
int getCurrentFrameIndex();
|
||||
void moveToFrame(int frame);
|
||||
|
||||
Q_SIGNALS:
|
||||
void imageReceived(const cv::Mat & image);
|
||||
|
||||
public Q_SLOTS:
|
||||
virtual void updateImageRate();
|
||||
virtual void takeImage();
|
||||
|
||||
protected:
|
||||
void startTimer();
|
||||
void stopTimer();
|
||||
|
||||
private:
|
||||
cv::VideoCapture capture_;
|
||||
QTimer cameraTimer_;
|
||||
QList<std::string> images_;
|
||||
unsigned int currentImageIndex_;
|
||||
CameraTcpClient * cameraTcpClient_;
|
||||
};
|
||||
|
||||
#endif /* CAMERA_H_ */
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* FindObject.h
|
||||
*
|
||||
* Created on: 2014-07-30
|
||||
* Author: mathieu
|
||||
*/
|
||||
|
||||
#ifndef FINDOBJECT_H_
|
||||
#define FINDOBJECT_H_
|
||||
|
||||
#include "find_object/FindObjectExp.h" // DLL export/import defines
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QMultiMap>
|
||||
#include <QtCore/QPair>
|
||||
#include <QtCore/QVector>
|
||||
#include <QtGui/QTransform>
|
||||
#include <QtCore/QRect>
|
||||
#include <opencv2/opencv.hpp>
|
||||
#include <vector>
|
||||
|
||||
class ObjSignature;
|
||||
class Vocabulary;
|
||||
class KeypointDetector;
|
||||
class DescriptorExtractor;
|
||||
|
||||
class FINDOBJECT_EXP FindObject : public QObject
|
||||
{
|
||||
Q_OBJECT;
|
||||
|
||||
public:
|
||||
enum TimeStamp{kTimeKeypointDetection, kTimeDescriptorExtraction, kTimeIndexing, kTimeMatching, kTimeHomography, kTimeTotal};
|
||||
|
||||
public:
|
||||
FindObject(QObject * parent = 0);
|
||||
virtual ~FindObject();
|
||||
|
||||
int loadObjects(const QString & dirPath); // call updateObjects()
|
||||
const ObjSignature * addObject(const QString & filePath);
|
||||
const ObjSignature * addObject(const cv::Mat & image, int id=0);
|
||||
bool addObject(ObjSignature * obj); // take ownership when true is returned
|
||||
void removeObject(int id);
|
||||
void removeAllObjects();
|
||||
|
||||
bool detect(const cv::Mat & image, QMultiMap<int,QPair<QRect,QTransform> > & objectsDetected);
|
||||
|
||||
void updateDetectorExtractor();
|
||||
void updateObjects();
|
||||
void updateVocabulary();
|
||||
|
||||
const QMap<int, ObjSignature*> & objects() const {return objects_;}
|
||||
const Vocabulary * vocabulary() const {return vocabulary_;}
|
||||
|
||||
const QMap<TimeStamp, float> & timeStamps() const {return timeStamps_;}
|
||||
const std::vector<cv::KeyPoint> & sceneKeypoints() const {return sceneKeypoints_;}
|
||||
const cv::Mat & sceneDescriptors() const {return sceneDescriptors_;}
|
||||
const QMultiMap<int, int> & sceneWords() const {return sceneWords_;}
|
||||
const QMap<int, QMultiMap<int, int> > & matches() const {return matches_;}
|
||||
const QMultiMap<int, QMultiMap<int, int> > & inliers() const {return inliers_;}
|
||||
const QMultiMap<int, QMultiMap<int, int> > & outliers() const {return outliers_;}
|
||||
const QMultiMap<int, QMultiMap<int, int> > & rejectedInliers() const {return rejectedInliers_;}
|
||||
const QMultiMap<int, QMultiMap<int, int> > & rejectedOutliers() const {return rejectedOutliers_;}
|
||||
float minMatchedDistance() const {return minMatchedDistance_;}
|
||||
float maxMatchedDistance() const {return maxMatchedDistance_;}
|
||||
|
||||
public Q_SLOTS:
|
||||
void detect(const cv::Mat & image);
|
||||
|
||||
Q_SIGNALS:
|
||||
void objectsFound(const QMultiMap<int, QPair<QRect, QTransform> > &);
|
||||
|
||||
private:
|
||||
void clearVocabulary();
|
||||
|
||||
private:
|
||||
QMap<int, ObjSignature*> objects_;
|
||||
Vocabulary * vocabulary_;
|
||||
QMap<int, cv::Mat> objectsDescriptors_;
|
||||
QMap<int, int> dataRange_; // <last id of object's descriptor, id>
|
||||
KeypointDetector * detector_;
|
||||
DescriptorExtractor * extractor_;
|
||||
|
||||
QMap<TimeStamp, float> timeStamps_;
|
||||
std::vector<cv::KeyPoint> sceneKeypoints_;
|
||||
cv::Mat sceneDescriptors_;
|
||||
QMultiMap<int, int> sceneWords_;
|
||||
QMap<int, QMultiMap<int, int> > matches_; // ObjectID Map< ObjectDescriptorIndex, SceneDescriptorIndex >, match the number of objects
|
||||
QMultiMap<int, QMultiMap<int, int> > inliers_; // ObjectID Map< ObjectDescriptorIndex, SceneDescriptorIndex >, match the number of detected objects
|
||||
QMultiMap<int, QMultiMap<int, int> > outliers_; // ObjectID Map< ObjectDescriptorIndex, SceneDescriptorIndex >, match the number of detected objects
|
||||
QMultiMap<int, QMultiMap<int, int> > rejectedInliers_; // ObjectID Map< ObjectDescriptorIndex, SceneDescriptorIndex >
|
||||
QMultiMap<int, QMultiMap<int, int> > rejectedOutliers_; // ObjectID Map< ObjectDescriptorIndex, SceneDescriptorIndex >
|
||||
float minMatchedDistance_;
|
||||
float maxMatchedDistance_;
|
||||
};
|
||||
|
||||
#endif /* FINDOBJECT_H_ */
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2011, Mathieu Labbe and IntRoLab - Universite de Sherbrooke
|
||||
*
|
||||
* This file is part of RTAB-Map.
|
||||
*
|
||||
* RTAB-Map is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* RTAB-Map is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with RTAB-Map. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef FINDOBJECTEXP_H
|
||||
#define FINDOBJECTEXP_H
|
||||
|
||||
#if defined(_WIN32)
|
||||
#if defined(find_object_EXPORTS)
|
||||
#define FINDOBJECT_EXP __declspec( dllexport )
|
||||
#else
|
||||
#define FINDOBJECT_EXP __declspec( dllimport )
|
||||
#endif
|
||||
#else
|
||||
#define FINDOBJECT_EXP
|
||||
#endif
|
||||
|
||||
#endif // RTABMAPEXP_H
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (C) 2011, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
|
||||
*/
|
||||
|
||||
#ifndef MAINWINDOW_H_
|
||||
#define MAINWINDOW_H_
|
||||
|
||||
#include "find_object/FindObjectExp.h" // DLL export/import defines
|
||||
|
||||
#include <QtGui/QMainWindow>
|
||||
#include <QtCore/QSet>
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtCore/QTime>
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QByteArray>
|
||||
|
||||
#include <opencv2/opencv.hpp>
|
||||
|
||||
class Ui_mainWindow;
|
||||
class ObjWidget;
|
||||
class Camera;
|
||||
class ParametersToolBox;
|
||||
class QLabel;
|
||||
class AboutDialog;
|
||||
class TcpServer;
|
||||
class KeypointDetector;
|
||||
class DescriptorExtractor;
|
||||
class Vocabulary;
|
||||
class FindObject;
|
||||
|
||||
namespace rtabmap
|
||||
{
|
||||
class PdfPlotCurve;
|
||||
}
|
||||
|
||||
class FINDOBJECT_EXP MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MainWindow(FindObject * findObject, Camera * camera = 0, QWidget * parent = 0);
|
||||
virtual ~MainWindow();
|
||||
|
||||
void setSourceImageText(const QString & text);
|
||||
|
||||
protected:
|
||||
virtual void closeEvent(QCloseEvent * event);
|
||||
|
||||
public Q_SLOTS:
|
||||
void startProcessing();
|
||||
void stopProcessing();
|
||||
void pauseProcessing();
|
||||
|
||||
private Q_SLOTS:
|
||||
void loadSettings();
|
||||
void saveSettings();
|
||||
void loadObjects();
|
||||
bool saveObjects();
|
||||
void addObjectFromScene();
|
||||
void addObjectsFromFiles();
|
||||
void loadSceneFromFile();
|
||||
void setupCameraFromVideoFile();
|
||||
void setupCameraFromImagesDirectory();
|
||||
void setupCameraFromTcpIp();
|
||||
void removeObject(ObjWidget * object);
|
||||
void removeAllObjects();
|
||||
void updateObjectsSize();
|
||||
void updateMirrorView();
|
||||
void showHideControls();
|
||||
void update(const cv::Mat & image = cv::Mat());
|
||||
void updateObjects();
|
||||
void notifyParametersChanged(const QStringList & param);
|
||||
void moveCameraFrame(int frame);
|
||||
void rectHovered(int objId);
|
||||
|
||||
Q_SIGNALS:
|
||||
void objectsFound(const QMultiMap<int, QPair<QRect, QTransform> > &);
|
||||
|
||||
private:
|
||||
bool loadSettings(const QString & path);
|
||||
bool saveSettings(const QString & path);
|
||||
int loadObjects(const QString & dirPath);
|
||||
int saveObjects(const QString & dirPath);
|
||||
void setupTCPServer();
|
||||
bool addObjectFromFile(const QString & filePath);
|
||||
void showObject(ObjWidget * obj);
|
||||
void updateObjectSize(ObjWidget * obj);
|
||||
void updateVocabulary();
|
||||
|
||||
private:
|
||||
Ui_mainWindow * ui_;
|
||||
Camera * camera_;
|
||||
FindObject * findObject_;
|
||||
rtabmap::PdfPlotCurve * likelihoodCurve_;
|
||||
rtabmap::PdfPlotCurve * inliersCurve_;
|
||||
AboutDialog * aboutDialog_;
|
||||
QMap<int, ObjWidget*> objWidgets_;
|
||||
QTime updateRate_;
|
||||
QTime refreshStartTime_;
|
||||
int lowestRefreshRate_;
|
||||
bool objectsModified_;
|
||||
QMap<int, QByteArray> imagesMap_;
|
||||
QMap<QString, QVariant> lastObjectsUpdateParameters_; // ParametersMap
|
||||
TcpServer * tcpServer_;
|
||||
cv::Mat sceneImage_;
|
||||
};
|
||||
|
||||
#endif /* MainWindow_H_ */
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (C) 2011, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
|
||||
*/
|
||||
|
||||
#ifndef OBJWIDGET_H_
|
||||
#define OBJWIDGET_H_
|
||||
|
||||
#include "find_object/FindObjectExp.h" // DLL export/import defines
|
||||
|
||||
#include <opencv2/features2d/features2d.hpp>
|
||||
#include <QtGui/QWidget>
|
||||
#include <QtCore/QMultiMap>
|
||||
|
||||
class KeypointItem;
|
||||
class ImageKptsView;
|
||||
class QAction;
|
||||
class QMenu;
|
||||
class QGraphicsView;
|
||||
class QGraphicsScene;
|
||||
class QGraphicsRectItem;
|
||||
class QGraphicsItem;
|
||||
class QLabel;
|
||||
|
||||
class FINDOBJECT_EXP ObjWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ObjWidget(QWidget * parent = 0);
|
||||
ObjWidget(int id, const std::vector<cv::KeyPoint> & keypoints, const QImage & image, QWidget * parent = 0);
|
||||
virtual ~ObjWidget();
|
||||
|
||||
void setId(int id);
|
||||
void setData(const std::vector<cv::KeyPoint> & keypoints, const QImage & image);
|
||||
void setTextLabel(const QString & text);
|
||||
void resetKptsColor();
|
||||
void setKptColor(int index, const QColor & color);
|
||||
void setGraphicsViewMode(bool on);
|
||||
void setAutoScale(bool autoScale);
|
||||
void setSizedFeatures(bool on);
|
||||
void setMirrorView(bool on);
|
||||
void setAlpha(int alpha);
|
||||
void setDeletable(bool deletable);
|
||||
void setImageShown(bool shown);
|
||||
void setFeaturesShown(bool shown);
|
||||
void addRect(QGraphicsRectItem * rect);
|
||||
void clearRoiSelection() {mousePressedPos_ = mouseCurrentPos_ = QPoint();update();}
|
||||
|
||||
int id() const {return id_;}
|
||||
const std::vector<cv::KeyPoint> keypoints() const {return keypoints_;}
|
||||
const QPixmap & pixmap() const {return pixmap_;}
|
||||
QColor defaultColor() const;
|
||||
bool isImageShown() const;
|
||||
bool isFeaturesShown() const;
|
||||
bool isSizedFeatures() const;
|
||||
bool isMirrorView() const;
|
||||
//QGraphicsScene * scene() const;
|
||||
std::vector<cv::KeyPoint> selectedKeypoints() const;
|
||||
QList<QGraphicsItem*> selectedItems() const;
|
||||
|
||||
QPixmap getSceneAsPixmap();
|
||||
|
||||
protected:
|
||||
virtual void paintEvent(QPaintEvent *event);
|
||||
virtual void contextMenuEvent(QContextMenuEvent * event);
|
||||
virtual void resizeEvent(QResizeEvent* event);
|
||||
virtual void mousePressEvent(QMouseEvent * event);
|
||||
virtual void mouseMoveEvent(QMouseEvent * event);
|
||||
virtual void mouseReleaseEvent(QMouseEvent * event);
|
||||
|
||||
Q_SIGNALS:
|
||||
void removalTriggered(ObjWidget *);
|
||||
void selectionChanged();
|
||||
void roiChanged(const cv::Rect &);
|
||||
|
||||
private:
|
||||
void setupGraphicsView();
|
||||
void drawKeypoints(QPainter * painter = 0);
|
||||
void setupUi();
|
||||
void updateItemsShown();
|
||||
void computeScaleOffsets(float & scale, float & offsetX, float & offsetY);
|
||||
|
||||
private:
|
||||
int id_;
|
||||
std::vector<cv::KeyPoint> keypoints_;
|
||||
QPixmap pixmap_;
|
||||
QList<KeypointItem*> keypointItems_;
|
||||
QGraphicsView * graphicsView_;
|
||||
QVector<QColor> kptColors_;
|
||||
QList<QGraphicsRectItem*> rectItems_;
|
||||
bool graphicsViewInitialized_;
|
||||
int alpha_;
|
||||
QLabel * label_;
|
||||
|
||||
// menu stuff
|
||||
QString savedFileName_;
|
||||
QMenu * menu_;
|
||||
QAction * showImage_;
|
||||
QAction * showFeatures_;
|
||||
QAction * saveImage_;
|
||||
QAction * mirrorView_;
|
||||
QAction * delete_;
|
||||
QAction * graphicsViewMode_;
|
||||
QAction * autoScale_;
|
||||
QAction * sizedFeatures_;
|
||||
QAction * setAlpha_;
|
||||
|
||||
// selection stuff
|
||||
QPoint mousePressedPos_;
|
||||
QPoint mouseCurrentPos_;
|
||||
};
|
||||
|
||||
|
||||
#endif /* OBJWIDGET_H_ */
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2011, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
|
||||
*/
|
||||
|
||||
#ifndef QTOPENCV_H
|
||||
#define QTOPENCV_H
|
||||
|
||||
#include "find_object/FindObjectExp.h" // DLL export/import defines
|
||||
|
||||
#include <QtGui/QImage>
|
||||
#include <opencv2/core/core.hpp>
|
||||
|
||||
// Convert OpenCV matrix to QImage
|
||||
QImage FINDOBJECT_EXP cvtCvMat2QImage(const cv::Mat & image, bool isBgr = true);
|
||||
|
||||
// Convert QImage to OpenCV matrix
|
||||
cv::Mat FINDOBJECT_EXP cvtQImage2CvMat(const QImage & image);
|
||||
|
||||
// Convert IplImage to QImage
|
||||
QImage FINDOBJECT_EXP cvtIplImage2QImage(const IplImage * image);
|
||||
|
||||
// Convert QImage to IplImage
|
||||
IplImage * FINDOBJECT_EXP cvtQImage2IplImage(const QImage & image);
|
||||
|
||||
#endif // QTOPENCV_H
|
||||
@@ -0,0 +1,281 @@
|
||||
/*
|
||||
* Copyright (C) 2011, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
|
||||
*/
|
||||
|
||||
#ifndef SETTINGS_H_
|
||||
#define SETTINGS_H_
|
||||
|
||||
#include "find_object/FindObjectExp.h" // DLL export/import defines
|
||||
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QVariant>
|
||||
#include <QtCore/QByteArray>
|
||||
#include <opencv2/features2d/features2d.hpp>
|
||||
|
||||
class KeypointDetector;
|
||||
class DescriptorExtractor;
|
||||
class GPUFeature2D;
|
||||
|
||||
typedef QMap<QString, QVariant> ParametersMap; // Key, value
|
||||
typedef QMap<QString, QString> ParametersType; // Key, type
|
||||
typedef QMap<QString, QString> DescriptionsMap; // Key, description
|
||||
|
||||
typedef unsigned int uint;
|
||||
|
||||
// MACRO BEGIN
|
||||
|
||||
#define PARAMETER_GETTER_bool(PREFIX, NAME) \
|
||||
static bool get##PREFIX##_##NAME() {return parameters_.value(#PREFIX "/" #NAME).toBool();}
|
||||
#define PARAMETER_GETTER_int(PREFIX, NAME) \
|
||||
static int get##PREFIX##_##NAME() {return parameters_.value(#PREFIX "/" #NAME).toInt();}
|
||||
#define PARAMETER_GETTER_uint(PREFIX, NAME) \
|
||||
static uint get##PREFIX##_##NAME() {return parameters_.value(#PREFIX "/" #NAME).toUInt();}
|
||||
#define PARAMETER_GETTER_float(PREFIX, NAME) \
|
||||
static float get##PREFIX##_##NAME() {return parameters_.value(#PREFIX "/" #NAME).toFloat();}
|
||||
#define PARAMETER_GETTER_double(PREFIX, NAME) \
|
||||
static double get##PREFIX##_##NAME() {return parameters_.value(#PREFIX "/" #NAME).toDouble();}
|
||||
#define PARAMETER_GETTER_QString(PREFIX, NAME) \
|
||||
static QString get##PREFIX##_##NAME() {return parameters_.value(#PREFIX "/" #NAME).toString();}
|
||||
|
||||
#define PARAMETER(PREFIX, NAME, TYPE, DEFAULT_VALUE, DESCRIPTION) \
|
||||
public: \
|
||||
static QString k##PREFIX##_##NAME() {return QString(#PREFIX "/" #NAME);} \
|
||||
static TYPE default##PREFIX##_##NAME() {return DEFAULT_VALUE;} \
|
||||
static QString type##PREFIX##_##NAME() {return QString(#TYPE);} \
|
||||
static QString description##PREFIX##_##NAME() {return QString(DESCRIPTION);} \
|
||||
PARAMETER_GETTER_##TYPE(PREFIX, NAME) \
|
||||
static void set##PREFIX##_##NAME(const TYPE & value) {parameters_[#PREFIX "/" #NAME] = value;} \
|
||||
private: \
|
||||
class Dummy##PREFIX##_##NAME { \
|
||||
public: \
|
||||
Dummy##PREFIX##_##NAME() { \
|
||||
defaultParameters_.insert(#PREFIX "/" #NAME, QVariant(DEFAULT_VALUE)); \
|
||||
parameters_.insert(#PREFIX "/" #NAME, DEFAULT_VALUE); \
|
||||
parametersType_.insert(#PREFIX "/" #NAME, #TYPE); \
|
||||
descriptions_.insert(#PREFIX "/" #NAME, DESCRIPTION);} \
|
||||
}; \
|
||||
Dummy##PREFIX##_##NAME dummy##PREFIX##_##NAME;
|
||||
// MACRO END
|
||||
|
||||
class FINDOBJECT_EXP Settings
|
||||
{
|
||||
PARAMETER(Camera, 1deviceId, int, 0, "Device ID (default 0).");
|
||||
PARAMETER(Camera, 2imageWidth, int, 640, "Image width (0 means default width from camera).");
|
||||
PARAMETER(Camera, 3imageHeight, int, 480, "Image height (0 means default height from camera).");
|
||||
PARAMETER(Camera, 4imageRate, double, 2.0, "Image rate in Hz (0 Hz means as fast as possible)."); // Hz
|
||||
PARAMETER(Camera, 5mediaPath, QString, "", "Video file or directory of images. If set, the camera is not used. See General->videoFormats and General->imageFormats for available formats.");
|
||||
PARAMETER(Camera, 6useTcpCamera, bool, false, "Use TCP/IP input camera.");
|
||||
PARAMETER(Camera, 7IP, QString, "127.0.0.1", "The images server's IP to connect when useTcpCamera is checked.");
|
||||
PARAMETER(Camera, 8port, int, 5000, "The images server's port to connect when useTcpCamera is checked.");
|
||||
PARAMETER(Camera, 9queueSize, int, 1, "Maximum images buffered from TCP. If 0, all images are buffered.");
|
||||
|
||||
//List format : [Index:item0;item1;item3;...]
|
||||
PARAMETER(Feature2D, 1Detector, QString, "7:Dense;Fast;GFTT;MSER;ORB;SIFT;Star;SURF;BRISK" , "Keypoint detector.");
|
||||
PARAMETER(Feature2D, 2Descriptor, QString, "3:Brief;ORB;SIFT;SURF;BRISK;FREAK", "Keypoint descriptor.");
|
||||
PARAMETER(Feature2D, 3MaxFeatures, int, 0, "Maximum features per image. If the number of features extracted is over this threshold, only X features with the highest response are kept. 0 means all features are kept.");
|
||||
|
||||
PARAMETER(Feature2D, Brief_bytes, int, 32, "Bytes is a length of descriptor in bytes. It can be equal 16, 32 or 64 bytes.");
|
||||
|
||||
PARAMETER(Feature2D, Dense_initFeatureScale, float, 1.f, "");
|
||||
PARAMETER(Feature2D, Dense_featureScaleLevels, int, 1, "");
|
||||
PARAMETER(Feature2D, Dense_featureScaleMul, float, 0.1f, "");
|
||||
PARAMETER(Feature2D, Dense_initXyStep, int, 6, "");
|
||||
PARAMETER(Feature2D, Dense_initImgBound, int, 0, "");
|
||||
PARAMETER(Feature2D, Dense_varyXyStepWithScale, bool, true, "");
|
||||
PARAMETER(Feature2D, Dense_varyImgBoundWithScale, bool, false, "");
|
||||
|
||||
PARAMETER(Feature2D, Fast_threshold, int, 10, "Threshold on difference between intensity of the central pixel and pixels of a circle around this pixel.");
|
||||
PARAMETER(Feature2D, Fast_nonmaxSuppression, bool, true, "If true, non-maximum suppression is applied to detected corners (keypoints).");
|
||||
PARAMETER(Feature2D, Fast_gpu, bool, false, "GPU-FAST: Use GPU version of FAST. This option is enabled only if OpenCV is built with CUDA and GPUs are detected.");
|
||||
PARAMETER(Feature2D, Fast_keypointsRatio, double, 0.05, "Used with FAST GPU.");
|
||||
|
||||
PARAMETER(Feature2D, GFTT_maxCorners, int, 1000, "");
|
||||
PARAMETER(Feature2D, GFTT_qualityLevel, double, 0.01, "");
|
||||
PARAMETER(Feature2D, GFTT_minDistance, double, 1, "");
|
||||
PARAMETER(Feature2D, GFTT_blockSize, int, 3, "");
|
||||
PARAMETER(Feature2D, GFTT_useHarrisDetector, bool, false, "");
|
||||
PARAMETER(Feature2D, GFTT_k, double, 0.04, "");
|
||||
|
||||
PARAMETER(Feature2D, ORB_nFeatures, int, 500, "The maximum number of features to retain.");
|
||||
PARAMETER(Feature2D, ORB_scaleFactor, float, 1.2f, "Pyramid decimation ratio, greater than 1. scaleFactor==2 means the classical pyramid, where each next level has 4x less pixels than the previous, but such a big scale factor will degrade feature matching scores dramatically. On the other hand, too close to 1 scale factor will mean that to cover certain scale range you will need more pyramid levels and so the speed will suffer.");
|
||||
PARAMETER(Feature2D, ORB_nLevels, int, 8, "The number of pyramid levels. The smallest level will have linear size equal to input_image_linear_size/pow(scaleFactor, nlevels).");
|
||||
PARAMETER(Feature2D, ORB_edgeThreshold, int, 31, "This is size of the border where the features are not detected. It should roughly match the patchSize parameter.");
|
||||
PARAMETER(Feature2D, ORB_firstLevel, int, 0, "It should be 0 in the current implementation.");
|
||||
PARAMETER(Feature2D, ORB_WTA_K, int, 2, "The number of points that produce each element of the oriented BRIEF descriptor. The default value 2 means the BRIEF where we take a random point pair and compare their brightnesses, so we get 0/1 response. Other possible values are 3 and 4. For example, 3 means that we take 3 random points (of course, those point coordinates are random, but they are generated from the pre-defined seed, so each element of BRIEF descriptor is computed deterministically from the pixel rectangle), find point of maximum brightness and output index of the winner (0, 1 or 2). Such output will occupy 2 bits, and therefore it will need a special variant of Hamming distance, denoted as NORM_HAMMING2 (2 bits per bin). When WTA_K=4, we take 4 random points to compute each bin (that will also occupy 2 bits with possible values 0, 1, 2 or 3).");
|
||||
PARAMETER(Feature2D, ORB_scoreType, int, 0, "The default HARRIS_SCORE=0 means that Harris algorithm is used to rank features (the score is written to KeyPoint::score and is used to retain best nfeatures features); FAST_SCORE=1 is alternative value of the parameter that produces slightly less stable keypoints, but it is a little faster to compute.");
|
||||
PARAMETER(Feature2D, ORB_patchSize, int, 31, "size of the patch used by the oriented BRIEF descriptor. Of course, on smaller pyramid layers the perceived image area covered by a feature will be larger.");
|
||||
PARAMETER(Feature2D, ORB_gpu, bool, false, "GPU-ORB: Use GPU version of ORB. This option is enabled only if OpenCV is built with CUDA and GPUs are detected.");
|
||||
|
||||
PARAMETER(Feature2D, MSER_delta, int, 5, "");
|
||||
PARAMETER(Feature2D, MSER_minArea, int, 60, "");
|
||||
PARAMETER(Feature2D, MSER_maxArea, int, 14400, "");
|
||||
PARAMETER(Feature2D, MSER_maxVariation, double, 0.25, "");
|
||||
PARAMETER(Feature2D, MSER_minDiversity, double, 0.2, "");
|
||||
PARAMETER(Feature2D, MSER_maxEvolution, int, 200, "");
|
||||
PARAMETER(Feature2D, MSER_areaThreshold, double, 1.01, "");
|
||||
PARAMETER(Feature2D, MSER_minMargin, double, 0.003, "");
|
||||
PARAMETER(Feature2D, MSER_edgeBlurSize, int, 5, "");
|
||||
|
||||
PARAMETER(Feature2D, SIFT_nfeatures, int, 0, "The number of best features to retain. The features are ranked by their scores (measured in SIFT algorithm as the local contrast).");
|
||||
PARAMETER(Feature2D, SIFT_nOctaveLayers, int, 3, "The number of layers in each octave. 3 is the value used in D. Lowe paper. The number of octaves is computed automatically from the image resolution.");
|
||||
PARAMETER(Feature2D, SIFT_contrastThreshold, double, 0.04, "The contrast threshold used to filter out weak features in semi-uniform (low-contrast) regions. The larger the threshold, the less features are produced by the detector.");
|
||||
PARAMETER(Feature2D, SIFT_edgeThreshold, double, 10, "The threshold used to filter out edge-like features. Note that the its meaning is different from the contrastThreshold, i.e. the larger the edgeThreshold, the less features are filtered out (more features are retained).");
|
||||
PARAMETER(Feature2D, SIFT_sigma, double, 1.6, "The sigma of the Gaussian applied to the input image at the octave #0. If your image is captured with a weak camera with soft lenses, you might want to reduce the number.");
|
||||
|
||||
PARAMETER(Feature2D, Star_maxSize, int, 45, "");
|
||||
PARAMETER(Feature2D, Star_responseThreshold, int, 30, "");
|
||||
PARAMETER(Feature2D, Star_lineThresholdProjected, int, 10, "");
|
||||
PARAMETER(Feature2D, Star_lineThresholdBinarized, int, 8, "");
|
||||
PARAMETER(Feature2D, Star_suppressNonmaxSize, int, 5, "");
|
||||
|
||||
PARAMETER(Feature2D, SURF_hessianThreshold, double, 600.0, "Threshold for hessian keypoint detector used in SURF.");
|
||||
PARAMETER(Feature2D, SURF_nOctaves, int, 4, "Number of pyramid octaves the keypoint detector will use.");
|
||||
PARAMETER(Feature2D, SURF_nOctaveLayers, int, 2, "Number of octave layers within each octave.");
|
||||
PARAMETER(Feature2D, SURF_extended, bool, true, "Extended descriptor flag (true - use extended 128-element descriptors; false - use 64-element descriptors).");
|
||||
PARAMETER(Feature2D, SURF_upright, bool, false, "Up-right or rotated features flag (true - do not compute orientation of features; false - compute orientation).");
|
||||
PARAMETER(Feature2D, SURF_gpu, bool, false, "GPU-SURF: Use GPU version of SURF. This option is enabled only if OpenCV is built with CUDA and GPUs are detected.");
|
||||
PARAMETER(Feature2D, SURF_keypointsRatio, float, 0.01f, "Used with SURF GPU.");
|
||||
|
||||
PARAMETER(Feature2D, BRISK_thresh, int, 30, "FAST/AGAST detection threshold score.");
|
||||
PARAMETER(Feature2D, BRISK_octaves, int, 3, "Detection octaves. Use 0 to do single scale.");
|
||||
PARAMETER(Feature2D, BRISK_patternScale, float, 1.0f, "Apply this scale to the pattern used for sampling the neighbourhood of a keypoint.");
|
||||
|
||||
PARAMETER(Feature2D, FREAK_orientationNormalized, bool, true, "Enable orientation normalization.");
|
||||
PARAMETER(Feature2D, FREAK_scaleNormalized, bool, true, "Enable scale normalization.");
|
||||
PARAMETER(Feature2D, FREAK_patternScale, float, 22.0f, "Scaling of the description pattern.");
|
||||
PARAMETER(Feature2D, FREAK_nOctaves, int, 4, "Number of octaves covered by the detected keypoints.");
|
||||
|
||||
PARAMETER(NearestNeighbor, 1Strategy, QString, "1:Linear;KDTree;KMeans;Composite;Autotuned;Lsh", "Nearest neighbor strategy.");
|
||||
PARAMETER(NearestNeighbor, 2Distance_type, QString, "0:EUCLIDEAN_L2;MANHATTAN_L1;MINKOWSKI;MAX;HIST_INTERSECT;HELLINGER;CHI_SQUARE_CS;KULLBACK_LEIBLER_KL;HAMMING", "Distance type.");
|
||||
PARAMETER(NearestNeighbor, 3nndrRatioUsed, bool, true, "Nearest neighbor distance ratio approach to accept the best match.");
|
||||
PARAMETER(NearestNeighbor, 4nndrRatio, float, 0.8f, "Nearest neighbor distance ratio.");
|
||||
PARAMETER(NearestNeighbor, 5minDistanceUsed, bool, false, "Minimum distance with the nearest descriptor to accept a match.");
|
||||
PARAMETER(NearestNeighbor, 6minDistance, float, 1.6f, "Minimum distance. You can look at top of this panel where minimum and maximum distances are shown to properly set this parameter depending of the descriptor used.");
|
||||
|
||||
PARAMETER(NearestNeighbor, 7search_checks, int, 32, "The number of times the tree(s) in the index should be recursively traversed. A higher value for this parameter would give better search precision, but also take more time. If automatic configuration was used when the index was created, the number of checks required to achieve the specified precision was also computed, in which case this parameter is ignored.");
|
||||
PARAMETER(NearestNeighbor, 8search_eps, float, 0, "");
|
||||
PARAMETER(NearestNeighbor, 9search_sorted, bool, true, "");
|
||||
|
||||
PARAMETER(NearestNeighbor, KDTree_trees, int, 4, "The number of parallel kd-trees to use. Good values are in the range [1..16].");
|
||||
|
||||
PARAMETER(NearestNeighbor, Composite_trees, int, 4, "The number of parallel kd-trees to use. Good values are in the range [1..16].");
|
||||
PARAMETER(NearestNeighbor, Composite_branching, int, 32, "The branching factor to use for the hierarchical k-means tree.");
|
||||
PARAMETER(NearestNeighbor, Composite_iterations, int, 11, "The maximum number of iterations to use in the k-means clustering stage when building the k-means tree. A value of -1 used here means that the k-means clustering should be iterated until convergence.");
|
||||
PARAMETER(NearestNeighbor, Composite_centers_init, QString, "0:RANDOM;GONZALES;KMEANSPP", "The algorithm to use for selecting the initial centers when performing a k-means clustering step. The possible values are CENTERS_RANDOM (picks the initial cluster centers randomly), CENTERS_GONZALES (picks the initial centers using Gonzales’ algorithm) and CENTERS_KMEANSPP (picks the initial centers using the algorithm suggested in arthur_kmeanspp_2007 ).");
|
||||
PARAMETER(NearestNeighbor, Composite_cb_index, double, 0.2, "This parameter (cluster boundary index) influences the way exploration is performed in the hierarchical kmeans tree. When cb_index is zero the next kmeans domain to be explored is chosen to be the one with the closest center. A value greater then zero also takes into account the size of the domain.");
|
||||
|
||||
PARAMETER(NearestNeighbor, Autotuned_target_precision, double, 0.8, "Is a number between 0 and 1 specifying the percentage of the approximate nearest-neighbor searches that return the exact nearest-neighbor. Using a higher value for this parameter gives more accurate results, but the search takes longer. The optimum value usually depends on the application.");
|
||||
PARAMETER(NearestNeighbor, Autotuned_build_weight, double, 0.01, "Specifies the importance of the index build time raported to the nearest-neighbor search time. In some applications it’s acceptable for the index build step to take a long time if the subsequent searches in the index can be performed very fast. In other applications it’s required that the index be build as fast as possible even if that leads to slightly longer search times.");
|
||||
PARAMETER(NearestNeighbor, Autotuned_memory_weight, double, 0, "Is used to specify the tradeoff between time (index build time and search time) and memory used by the index. A value less than 1 gives more importance to the time spent and a value greater than 1 gives more importance to the memory usage.");
|
||||
PARAMETER(NearestNeighbor, Autotuned_sample_fraction, double, 0.1, "Is a number between 0 and 1 indicating what fraction of the dataset to use in the automatic parameter configuration algorithm. Running the algorithm on the full dataset gives the most accurate results, but for very large datasets can take longer than desired. In such case using just a fraction of the data helps speeding up this algorithm while still giving good approximations of the optimum parameters.");
|
||||
|
||||
PARAMETER(NearestNeighbor, KMeans_branching, int, 32, "The branching factor to use for the hierarchical k-means tree.");
|
||||
PARAMETER(NearestNeighbor, KMeans_iterations, int, 11, "The maximum number of iterations to use in the k-means clustering stage when building the k-means tree. A value of -1 used here means that the k-means clustering should be iterated until convergence.");
|
||||
PARAMETER(NearestNeighbor, KMeans_centers_init, QString, "0:RANDOM;GONZALES;KMEANSPP", "The algorithm to use for selecting the initial centers when performing a k-means clustering step. The possible values are CENTERS_RANDOM (picks the initial cluster centers randomly), CENTERS_GONZALES (picks the initial centers using Gonzales’ algorithm) and CENTERS_KMEANSPP (picks the initial centers using the algorithm suggested in arthur_kmeanspp_2007 ).");
|
||||
PARAMETER(NearestNeighbor, KMeans_cb_index, double, 0.2, "This parameter (cluster boundary index) influences the way exploration is performed in the hierarchical kmeans tree. When cb_index is zero the next kmeans domain to be explored is chosen to be the one with the closest center. A value greater then zero also takes into account the size of the domain.");
|
||||
|
||||
PARAMETER(NearestNeighbor, Lsh_table_number, int, 12, "The number of hash tables to use (between 10 and 30 usually).");
|
||||
PARAMETER(NearestNeighbor, Lsh_key_size, int, 20, "The size of the hash key in bits (between 10 and 20 usually).");
|
||||
PARAMETER(NearestNeighbor, Lsh_multi_probe_level, int, 2, "The number of bits to shift to check for neighboring buckets (0 is regular LSH, 2 is recommended).");
|
||||
|
||||
PARAMETER(General, autoStartCamera, bool, false, "Automatically start the camera when the application is opened.");
|
||||
PARAMETER(General, autoUpdateObjects, bool, true, "Automatically update objects on every parameter changes, otherwise you would need to press \"Update objects\" on the objects panel.");
|
||||
PARAMETER(General, nextObjID, uint, 1, "Next object ID to use.");
|
||||
PARAMETER(General, imageFormats, QString, "*.png *.jpg *.bmp *.tiff *.ppm", "Image formats supported.");
|
||||
PARAMETER(General, videoFormats, QString, "*.avi *.m4v *.mp4", "Video formats supported.");
|
||||
PARAMETER(General, mirrorView, bool, true, "Flip the camera image horizontally (like all webcam applications).");
|
||||
PARAMETER(General, invertedSearch, bool, true, "Instead of matching descriptors from the objects to those in a vocabulary created with descriptors extracted from the scene, we create a vocabulary from all the objects' descriptors and we match scene's descriptors to this vocabulary. It is the inverted search mode.");
|
||||
PARAMETER(General, controlsShown, bool, false, "Show play/image seek controls (useful with video file and directory of images modes).");
|
||||
PARAMETER(General, threads, int, 1, "Number of threads used for objects matching and homography computation. 0 means as many threads as objects. On InvertedSearch mode, multi-threading has only effect on homography computation.");
|
||||
PARAMETER(General, multiDetection, bool, false, "Multiple detection of the same object.");
|
||||
PARAMETER(General, multiDetectionRadius, int, 30, "Ignore detection of the same object in X pixels radius of the previous detections.");
|
||||
PARAMETER(General, port, int, 0, "Port on objects detected are published. If port=0, a port is chosen automatically.")
|
||||
PARAMETER(General, autoScroll, bool, true, "Auto scroll to detected object in Objects panel.");
|
||||
PARAMETER(General, vocabularyIncremental, bool, false, "The vocabulary is created incrementally. When new objects are added, their descriptors are compared to those already in vocabulary to find if the visual word already exist or not. \"NearestNeighbor/nndrRatio\" is used to compare descriptors.");
|
||||
PARAMETER(General, vocabularyUpdateMinWords, int, 2000, "When the vocabulary is incremental (see \"General/vocabularyIncremental\"), after X words added to vocabulary, the internal index is updated with new words. This parameter lets avoiding to reconstruct the whole nearest neighbor index after each time descriptors of an object are added to vocabulary. 0 means no incremental update.");
|
||||
PARAMETER(General, sendNoObjDetectedEvents, bool, false, "When there are no objects detected, send an empty object detection event.");
|
||||
|
||||
PARAMETER(Homography, homographyComputed, bool, true, "Compute homography? On ROS, this is required to publish objects detected.");
|
||||
PARAMETER(Homography, method, QString, "1:LMEDS;RANSAC", "Type of the robust estimation algorithm: least-median algorithm or RANSAC algorithm.");
|
||||
PARAMETER(Homography, ransacReprojThr, double, 1.0, "Maximum allowed reprojection error to treat a point pair as an inlier (used in the RANSAC method only). It usually makes sense to set this parameter somewhere in the range of 1 to 10.");
|
||||
PARAMETER(Homography, minimumInliers, int, 10, "Minimum inliers to accept the homography. Value must be >= 4.");
|
||||
PARAMETER(Homography, ignoreWhenAllInliers, bool, false, "Ignore homography when all features are inliers (sometimes when the homography doesn't converge, it returns the best homography with all features as inliers).");
|
||||
PARAMETER(Homography, rectBorderWidth, int, 4, "Homography rectangle border width.");
|
||||
|
||||
public:
|
||||
virtual ~Settings(){}
|
||||
|
||||
static QString workingDirectory();
|
||||
static QString iniDefaultPath();
|
||||
static QString iniDefaultFileName() {return "config.ini";}
|
||||
static QString iniPath();
|
||||
|
||||
static void init(const QString & fileName = QString());
|
||||
|
||||
static void loadSettings(const QString & fileName = QString());
|
||||
static void loadWindowSettings(QByteArray & windowGeometry, QByteArray & windowState, const QString & fileName = QString());
|
||||
static void saveSettings(const QString & fileName = QString());
|
||||
static void saveWindowSettings(const QByteArray & windowGeometry, const QByteArray & windowState, const QString & fileName = QString());
|
||||
|
||||
static const ParametersMap & getDefaultParameters() {return defaultParameters_;}
|
||||
static const ParametersMap & getParameters() {return parameters_;}
|
||||
static const ParametersType & getParametersType() {return parametersType_;}
|
||||
static const DescriptionsMap & getDescriptions() {return descriptions_;}
|
||||
static void setParameter(const QString & key, const QVariant & value) {if(parameters_.contains(key))parameters_[key] = value;}
|
||||
static void resetParameter(const QString & key) {if(defaultParameters_.contains(key)) parameters_.insert(key, defaultParameters_.value(key));}
|
||||
static QVariant getParameter(const QString & key) {return parameters_.value(key, QVariant());}
|
||||
|
||||
static KeypointDetector * createKeypointDetector();
|
||||
static DescriptorExtractor * createDescriptorExtractor();
|
||||
|
||||
static QString currentDescriptorType();
|
||||
static QString currentDetectorType();
|
||||
static QString currentNearestNeighborType();
|
||||
|
||||
static cv::flann::IndexParams * createFlannIndexParams();
|
||||
static cvflann::flann_distance_t getFlannDistanceType();
|
||||
static cv::flann::SearchParams getFlannSearchParams();
|
||||
|
||||
static int getHomographyMethod();
|
||||
|
||||
private:
|
||||
Settings(){}
|
||||
|
||||
private:
|
||||
static ParametersMap defaultParameters_;
|
||||
static ParametersMap parameters_;
|
||||
static ParametersType parametersType_;
|
||||
static DescriptionsMap descriptions_;
|
||||
static Settings dummyInit_;
|
||||
static QString iniPath_;
|
||||
};
|
||||
|
||||
class KeypointDetector
|
||||
{
|
||||
public:
|
||||
KeypointDetector(cv::FeatureDetector * featureDetector);
|
||||
KeypointDetector(GPUFeature2D * gpuFeature2D);
|
||||
|
||||
void detect(const cv::Mat & image, std::vector<cv::KeyPoint> & keypoints);
|
||||
|
||||
private:
|
||||
cv::FeatureDetector * featureDetector_;
|
||||
GPUFeature2D * gpuFeature2D_;
|
||||
};
|
||||
|
||||
class DescriptorExtractor
|
||||
{
|
||||
public:
|
||||
DescriptorExtractor(cv::DescriptorExtractor * descriptorExtractor);
|
||||
DescriptorExtractor(GPUFeature2D * gpuFeature2D);
|
||||
|
||||
void compute(const cv::Mat & image,
|
||||
std::vector<cv::KeyPoint> & keypoints,
|
||||
cv::Mat & descriptors);
|
||||
|
||||
private:
|
||||
cv::DescriptorExtractor * descriptorExtractor_;
|
||||
GPUFeature2D * gpuFeature2D_;
|
||||
};
|
||||
|
||||
#endif /* SETTINGS_H_ */
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* TCPServer.h
|
||||
*
|
||||
* Created on: 2014-05-05
|
||||
* Author: mathieu
|
||||
*/
|
||||
|
||||
#ifndef TCPSERVER_H_
|
||||
#define TCPSERVER_H_
|
||||
|
||||
#include "find_object/FindObjectExp.h" // DLL export/import defines
|
||||
|
||||
#include <QtNetwork/QTcpServer>
|
||||
|
||||
class QNetworkSession;
|
||||
|
||||
class FINDOBJECT_EXP TcpServer : public QTcpServer
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TcpServer(quint16 port = 0, QObject * parent = 0);
|
||||
|
||||
QHostAddress getHostAddress() const;
|
||||
quint16 getPort() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
void publishObjects(const QMultiMap<int, QPair<QRect, QTransform> > & objects);
|
||||
|
||||
private Q_SLOTS:
|
||||
void addClient();
|
||||
};
|
||||
|
||||
#endif /* TCPSERVER_H_ */
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* utilite is a cross-platform library with
|
||||
* useful utilities for fast and small developing.
|
||||
* Copyright (C) 2010 Mathieu Labbe
|
||||
*
|
||||
* utilite is free library: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* utilite is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef UDESTROYER_H
|
||||
#define UDESTROYER_H
|
||||
|
||||
//#include "utilite/UtiLiteExp.h" // DLL export/import defines
|
||||
|
||||
/**
|
||||
* This class is used to delete a dynamically created
|
||||
* objects. It was mainly designed to remove dynamically created Singleton.
|
||||
* Created on the stack of a Singleton, when the
|
||||
* application is finished, his destructor make sure that the
|
||||
* Singleton is deleted.
|
||||
*
|
||||
*/
|
||||
template <class T>
|
||||
class UDestroyer
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* The constructor. Set the doomed object (take ownership of the object). The object is deleted
|
||||
* when this object is deleted.
|
||||
*/
|
||||
UDestroyer(T* doomed = 0) : doomed_(doomed) {}
|
||||
|
||||
~UDestroyer()
|
||||
{
|
||||
if(doomed_)
|
||||
{
|
||||
delete doomed_;
|
||||
doomed_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the doomed object. If a doomed object is already set, the function returns false.
|
||||
* @param doomed the doomed object
|
||||
* @return false if an object is already set and the new object is not null, otherwise true
|
||||
*/
|
||||
bool setDoomed(T* doomed)
|
||||
{
|
||||
if(doomed_ && doomed)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
doomed_ = doomed;
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
// Prevent users from making copies of a
|
||||
// Destroyer to avoid double deletion:
|
||||
UDestroyer(const UDestroyer<T>&);
|
||||
void operator=(const UDestroyer<T>&);
|
||||
|
||||
private:
|
||||
T* doomed_;
|
||||
};
|
||||
|
||||
#endif // UDESTROYER_H
|
||||
@@ -0,0 +1,531 @@
|
||||
/*
|
||||
* utilite is a cross-platform library with
|
||||
* useful utilities for fast and small developing.
|
||||
* Copyright (C) 2010 Mathieu Labbe
|
||||
*
|
||||
* utilite is free library: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* utilite is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef ULOGGER_H
|
||||
#define ULOGGER_H
|
||||
|
||||
#include "find_object/FindObjectExp.h" // DLL export/import defines
|
||||
|
||||
#include "find_object/utilite/UMutex.h"
|
||||
#include "find_object/utilite/UDestroyer.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
/**
|
||||
* \file ULogger.h
|
||||
* \brief ULogger class and convenient macros
|
||||
*
|
||||
* This contains macros useful for logging a message anywhere in the
|
||||
* application. Once the ULogger is set, use these macros like a printf to
|
||||
* print debug messages.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Convenient macros for logging...
|
||||
*/
|
||||
#define ULOGGER_LOG(level, ...) ULogger::write(level, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)
|
||||
|
||||
#define ULOGGER_DEBUG(...) ULOGGER_LOG(ULogger::kDebug, __VA_ARGS__)
|
||||
#define ULOGGER_INFO(...) ULOGGER_LOG(ULogger::kInfo, __VA_ARGS__)
|
||||
#define ULOGGER_WARN(...) ULOGGER_LOG(ULogger::kWarning, __VA_ARGS__)
|
||||
#define ULOGGER_ERROR(...) ULOGGER_LOG(ULogger::kError, __VA_ARGS__)
|
||||
#define ULOGGER_FATAL(...) ULOGGER_LOG(ULogger::kFatal, __VA_ARGS__)
|
||||
|
||||
#define UDEBUG(...) ULOGGER_DEBUG(__VA_ARGS__)
|
||||
#define UINFO(...) ULOGGER_INFO(__VA_ARGS__)
|
||||
#define UWARN(...) ULOGGER_WARN(__VA_ARGS__)
|
||||
#define UERROR(...) ULOGGER_ERROR(__VA_ARGS__)
|
||||
#define UFATAL(...) ULOGGER_FATAL(__VA_ARGS__)
|
||||
|
||||
#define UASSERT(condition) if(!(condition)) ULogger::write(ULogger::kFatal, __FILE__, __LINE__, __FUNCTION__, "Condition (%s) not met!", #condition)
|
||||
#define UASSERT_MSG(condition, msg_str) if(!(condition)) ULogger::write(ULogger::kFatal, __FILE__, __LINE__, __FUNCTION__, "Condition (%s) not met! [%s]", #condition, msg_str)
|
||||
|
||||
/**
|
||||
* \def UDEBUG(...)
|
||||
* Print a debug level message in the logger. Format is the same as a printf:
|
||||
* @code
|
||||
* UDEBUG("This is a debug message with the number %d", 42);
|
||||
* @endcode
|
||||
*/
|
||||
/**
|
||||
* \def UINFO(...)
|
||||
* Print a information level message in the logger. Format is the same as a printf:
|
||||
* @code
|
||||
* UINFO("This is a information message with the number %d", 42);
|
||||
* @endcode
|
||||
*/
|
||||
/**
|
||||
* \def UWARN(...)
|
||||
* Print a warning level message in the logger. Format is the same as a printf:
|
||||
* @code
|
||||
* UWARN("This is a warning message with the number %d", 42);
|
||||
* @endcode
|
||||
*/
|
||||
/**
|
||||
* \def UERROR(...)
|
||||
* Print an error level message in the logger. Format is the same as a printf:
|
||||
* @code
|
||||
* UERROR("This is an error message with the number %d", 42);
|
||||
* @endcode
|
||||
*/
|
||||
/**
|
||||
* \def UFATAL(...)
|
||||
* Print a fatal error level message in the logger. The application will exit on
|
||||
* fatal error. Format is the same as a printf:
|
||||
* @code
|
||||
* UFATAL("This is a fatal error message with the number %d", 42);
|
||||
* @endcode
|
||||
*/
|
||||
/**
|
||||
* \def UASSERT(condition, ...)
|
||||
* Print a fatal error level message in the logger if condition is not met. The application will exit on
|
||||
* fatal error. Format is the same as a printf:
|
||||
* @code
|
||||
* UASSERT(a!=42, "This is a fatal error message with the number %d", 42);
|
||||
* @endcode
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* This class is used to log messages with time on a console, in a file
|
||||
* and/or with an event. At the start of the application, call
|
||||
* ULogger::setType() with the type of the logger you want (see ULogger::Type, the type of the output
|
||||
* can be changed at the run-time.). To use it,
|
||||
* simply call the convenient macros UDEBUG(), UINFO(), UWARN(), UERROR(), UFATAL() depending of
|
||||
* the severity of the message. You can disable some messages by setting the logger
|
||||
* level ULogger::setLevel() to severity you want, defined by ULogger::Level. A fatal message
|
||||
* will make the application to exit, printing the message on console (whatever the logger type) and
|
||||
* posting a ULogEvent (synchronously... see UEventsManager::post()) before exiting.
|
||||
*
|
||||
* The display of the logged messages can be modified:
|
||||
* - If you don't want the level label, set ULogger::setPrintLevel() to false.
|
||||
* - If you don't want the time label, set ULogger::setPrintTime() to false.
|
||||
* - If you don't want the end of line added, set ULogger::setPrintEndline() to false.
|
||||
* - If you don't the full path of the message, set ULogger::setPrintWhereFullPath() to false.
|
||||
* - If you don't the path of the message, set ULogger::setPrintWhere() to false.
|
||||
*
|
||||
* When using a file logger (kTypeLogger), it can be useful in some
|
||||
* application to buffer messages before writing them to hard drive (avoiding
|
||||
* hard drive latencies). You can set ULogger::setBuffered() to true to do that. When the
|
||||
* buffered messages will be written to file on appllciation exit (ULogger destructor) or when
|
||||
* ULogger::flush() is called.
|
||||
*
|
||||
* If you want the application to exit on a lower severity level than kFatal,
|
||||
* you can set ULogger::setExitLevel() to any ULogger::Type you want.
|
||||
*
|
||||
* Example:
|
||||
* @code
|
||||
* #include <utilite/ULogger.h>
|
||||
* int main(int argc, char * argv[])
|
||||
* {
|
||||
* // Set the logger type. The choices are kTypeConsole,
|
||||
* // kTypeFile or kTypeNoLog (nothing is logged).
|
||||
* ULogger::setType(ULogger::kTypeConsole);
|
||||
*
|
||||
* // Set the logger severity level (kDebug, kInfo, kWarning, kError, kFatal).
|
||||
* // All log entries under the severity level are not logged. Here,
|
||||
* // only debug messages are not logged.
|
||||
* ULogger::setLevel(ULogger::kInfo);
|
||||
*
|
||||
* // Use a predefined Macro to easy logging. It can be
|
||||
* // called anywhere in the application as the logger is
|
||||
* // a Singleton.
|
||||
* UDEBUG("This message won't be logged because the "
|
||||
* "severity level of the logger is set to kInfo.");
|
||||
*
|
||||
* UINFO("This message is logged.");
|
||||
*
|
||||
* UWARN("A warning message...");
|
||||
*
|
||||
* UERROR("An error message with code %d.", 42);
|
||||
*
|
||||
* return 0;
|
||||
* }
|
||||
* @endcode
|
||||
* Output:
|
||||
* @code
|
||||
* [ INFO] (2010-09-25 18:08:20) main.cpp:18::main() This message is logged.
|
||||
* [ WARN] (2010-09-25 18:08:20) main.cpp:20::main() A warning message...
|
||||
* [ERROR] (2010-09-25 18:08:20) main.cpp:22::main() An error message with code 42.
|
||||
* @endcode
|
||||
*
|
||||
* Another useful form of the ULogger is to use it with the UTimer class. Here an example:
|
||||
* @code
|
||||
* #include <utilite/ULogger.h>
|
||||
* #include <utilite/UTimer.h>
|
||||
* ...
|
||||
* UTimer timer; // automatically starts
|
||||
* // do some works for part A
|
||||
* UINFO("Time for part A = %f s", timer.ticks());
|
||||
* // do some works for part B
|
||||
* UINFO("Time for part B = %f s", timer.ticks());
|
||||
* // do some works for part C
|
||||
* UINFO("Time for part C = %f s", timer.ticks());
|
||||
* ...
|
||||
* @endcode
|
||||
*
|
||||
* @see setType()
|
||||
* @see setLevel()
|
||||
* @see UDEBUG(), UINFO(), UWARN(), UERROR(), UFATAL()
|
||||
*
|
||||
*/
|
||||
class FINDOBJECT_EXP ULogger
|
||||
{
|
||||
|
||||
public:
|
||||
/**
|
||||
* The default log file name.
|
||||
*/
|
||||
static const std::string kDefaultLogFileName;
|
||||
|
||||
/**
|
||||
* Loggers available:
|
||||
* @code
|
||||
* kTypeNoLog, kTypeConsole, kTypeFile
|
||||
* @endcode
|
||||
*/
|
||||
enum Type{kTypeNoLog, kTypeConsole, kTypeFile};
|
||||
|
||||
/**
|
||||
* Logger levels, from lowest severity to highest:
|
||||
* @code
|
||||
* kDebug, kInfo, kWarning, kError, kFatal
|
||||
* @endcode
|
||||
*/
|
||||
enum Level{kDebug, kInfo, kWarning, kError, kFatal};
|
||||
|
||||
/**
|
||||
* Set the type of the logger. When using kTypeFile, the parameter "fileName" would be
|
||||
* changed (default is "./ULog.txt"), and optionally "append" if we want the
|
||||
* logger to append messages to file or to overwrite the file.
|
||||
* @param type the ULogger::Type of the logger.
|
||||
* @param fileName file name used with a file logger type.
|
||||
* @param append if true, the file isn't overwritten, otherwise it is.
|
||||
*
|
||||
* TODO : Can it be useful to have 2 or more types at the same time ? Print
|
||||
* in console and file at the same time.
|
||||
*/
|
||||
static void setType(Type type, const std::string &fileName = kDefaultLogFileName, bool append = true);
|
||||
static Type type() {return type_;}
|
||||
|
||||
// Setters
|
||||
/**
|
||||
* Print time: default true.
|
||||
* @param printTime true to print time, otherwise set to false.
|
||||
*/
|
||||
static void setPrintTime(bool printTime) {printTime_ = printTime;}
|
||||
static bool isPrintTime() {return printTime_;}
|
||||
|
||||
/**
|
||||
* Print level: default true.
|
||||
* @param printLevel true to print level, otherwise set to false.
|
||||
*/
|
||||
static void setPrintLevel(bool printLevel) {printLevel_ = printLevel;}
|
||||
static bool isPrintLevel() {return printLevel_;}
|
||||
|
||||
/**
|
||||
* Print end of line: default true.
|
||||
* @param printLevel true to print end of line, otherwise set to false.
|
||||
*/
|
||||
static void setPrintEndline(bool printEndline) {printEndline_ = printEndline;}
|
||||
static bool isPrintEndLine() {return printEndline_;}
|
||||
|
||||
/**
|
||||
* Print text with color: default true.
|
||||
* Dark green for Debug, white for Info, yellow for Warning, red for Error and Fatal.
|
||||
* @param printColored true to print text with color, otherwise set to false.
|
||||
*/
|
||||
static void setPrintColored(bool printColored) {printColored_ = printColored;}
|
||||
static bool isPrintColored() {return printColored_;}
|
||||
|
||||
/**
|
||||
* Print where is this message in source code: default true.
|
||||
* @param printWhere true to print where, otherwise set to false.
|
||||
*/
|
||||
static void setPrintWhere(bool printWhere) {printWhere_ = printWhere;}
|
||||
static bool isPrintWhere() {return printWhere_;}
|
||||
|
||||
/**
|
||||
* Print the full path: default true. ULogger::setPrintWhere() must be true to have path printed.
|
||||
* @param printWhereFullPath true to print the full path, otherwise set to false.
|
||||
*/
|
||||
static void setPrintWhereFullPath(bool printWhereFullPath) {printWhereFullPath_ = printWhereFullPath;}
|
||||
static bool isPrintWhereFullPath() {return printWhereFullPath_;}
|
||||
|
||||
/**
|
||||
* Set is the logger buffers messages, default false. When true, the messages are
|
||||
* buffered until the application is closed or ULogger::flush() is called.
|
||||
* @see ULogger::flush()
|
||||
* @param buffered true to buffer messages, otherwise set to false.
|
||||
*/
|
||||
static void setBuffered(bool buffered);
|
||||
static bool isBuffered() {return buffered_;}
|
||||
|
||||
/**
|
||||
* Set logger level: default kInfo. All messages over the severity set
|
||||
* are printed, other are ignored. The severity is from the lowest to
|
||||
* highest:
|
||||
* - kDebug
|
||||
* - kInfo
|
||||
* - kWarning
|
||||
* - kError
|
||||
* - kFatal
|
||||
* @param level the minimum level of the messages printed.
|
||||
*/
|
||||
static void setLevel(ULogger::Level level) {level_ = level;}
|
||||
static ULogger::Level level() {return level_;}
|
||||
|
||||
/**
|
||||
* Make application to exit when a log with level is written (useful for debugging). The message is printed to
|
||||
* console (whatever the logger type) and an ULogEvent is sent (synchronously... see UEventsManager::post()) before exiting.
|
||||
*
|
||||
* Note : A kFatal level will always exit whatever the level specified here.
|
||||
*/
|
||||
static void setExitLevel(ULogger::Level exitLevel) {exitLevel_ = exitLevel;}
|
||||
static ULogger::Level exitLevel() {return exitLevel_;}
|
||||
|
||||
/**
|
||||
* An ULogEvent is sent on each message logged at the specified level.
|
||||
* Note : On message with level >= exitLevel, the event is sent synchronously (see UEventsManager::post()).
|
||||
* @see ULogEvent
|
||||
* @see setExitLevel()
|
||||
*/
|
||||
static void setEventLevel(ULogger::Level eventSentLevel) {eventLevel_ = eventSentLevel;}
|
||||
static ULogger::Level eventLevel() {return eventLevel_;}
|
||||
|
||||
/**
|
||||
* Reset to default parameters.
|
||||
*/
|
||||
static void reset();
|
||||
|
||||
/**
|
||||
* Flush buffered messages.
|
||||
* @see setBuffered()
|
||||
*/
|
||||
static void flush();
|
||||
|
||||
/**
|
||||
* Write a message directly to logger without level handling.
|
||||
* @param msg the message to write.
|
||||
* @param ... the variable arguments
|
||||
* @deprecated use UDEBUG(), UINFO(), UWARN(), UERROR() or UFATAL()
|
||||
*/
|
||||
static void write(const char* msg, ...);
|
||||
|
||||
/*
|
||||
* Write a message to logger: use UDEBUG(), UINFO(), UWARN(), UERROR() or UFATAL() instead.
|
||||
* @param level the log level of this message
|
||||
* @param file the file path
|
||||
* @param line the line in the file
|
||||
* @param function the function name in which the message is logged
|
||||
* @param msg the message to write
|
||||
* @param ... the variable arguments
|
||||
*/
|
||||
static void write(ULogger::Level level,
|
||||
const char * file,
|
||||
int line,
|
||||
const char *function,
|
||||
const char* msg,
|
||||
...);
|
||||
|
||||
/**
|
||||
* Get the time in the format "2008-7-13 12:23:44".
|
||||
* @param timeStr string were the time will be copied.
|
||||
* @return the number of characters written, or 0 if an error occurred.
|
||||
*/
|
||||
static int getTime(std::string &timeStr);
|
||||
|
||||
protected:
|
||||
/*
|
||||
* This method is used to have a reference on the
|
||||
* Logger. When no Logger exists, one is
|
||||
* created. There is only one instance in the application.
|
||||
* Must be protected by loggerMutex_.
|
||||
* See the Singleton pattern for further explanation.
|
||||
*
|
||||
* @return the reference on the Logger
|
||||
*/
|
||||
static ULogger* getInstance();
|
||||
|
||||
/*
|
||||
* Called only once in getInstance(). It can't be instanciated
|
||||
* by the user.
|
||||
*
|
||||
* @see getInstance()
|
||||
*/
|
||||
ULogger() {}
|
||||
|
||||
/*
|
||||
* Only called by a Destroyer.
|
||||
* @see Destroyer
|
||||
*/
|
||||
virtual ~ULogger();
|
||||
|
||||
/*
|
||||
* Flush buffered messages
|
||||
*/
|
||||
void _flush();
|
||||
|
||||
/*
|
||||
* A Destroyer is used to remove a dynamicaly created
|
||||
* Singleton. It is friend here to have access to the
|
||||
* destructor.
|
||||
*
|
||||
* @see Destroyer
|
||||
*/
|
||||
friend class UDestroyer<ULogger>;
|
||||
|
||||
/*
|
||||
* The log file name.
|
||||
*/
|
||||
static std::string logFileName_;
|
||||
|
||||
/*
|
||||
* Default true, it doesn't overwrite the file.
|
||||
*/
|
||||
static bool append_;
|
||||
|
||||
private:
|
||||
/*
|
||||
* Create an instance according to type. See the Abstract factory
|
||||
* pattern for further explanation.
|
||||
* @see type_
|
||||
* @return the reference on the new logger
|
||||
*/
|
||||
static ULogger* createInstance();
|
||||
|
||||
/*
|
||||
* Write a message on the output with the format :
|
||||
* "A message". Inherited class
|
||||
* must override this method to output the message. It
|
||||
* does nothing by default.
|
||||
* @param msg the message to write.
|
||||
* @param arg the variable arguments
|
||||
*/
|
||||
virtual void _write(const char* msg, va_list arg) {} // Do nothing by default
|
||||
virtual void _writeStr(const char* msg) {} // Do nothing by default
|
||||
|
||||
private:
|
||||
/*
|
||||
* The Logger instance pointer.
|
||||
*/
|
||||
static ULogger* instance_;
|
||||
|
||||
/*
|
||||
* The Logger's destroyer
|
||||
*/
|
||||
static UDestroyer<ULogger> destroyer_;
|
||||
|
||||
/*
|
||||
* If the logger prints the time for each message.
|
||||
* Default is true.
|
||||
*/
|
||||
static bool printTime_;
|
||||
|
||||
/*
|
||||
* If the logger prints the level for each message.
|
||||
* Default is true.
|
||||
*/
|
||||
static bool printLevel_;
|
||||
|
||||
/*
|
||||
* If the logger prints the end line for each message.
|
||||
* Default is true.
|
||||
*/
|
||||
static bool printEndline_;
|
||||
|
||||
/*
|
||||
* If the logger prints text with color.
|
||||
* Default is true.
|
||||
*/
|
||||
static bool printColored_;
|
||||
|
||||
/*
|
||||
* If the logger prints where the message is logged (fileName::function():line).
|
||||
* Default is true.
|
||||
*/
|
||||
static bool printWhere_;
|
||||
|
||||
/*
|
||||
* If the logger prints the full path of the source file
|
||||
* where the message is written. Only works when
|
||||
* "printWhere_" is true.
|
||||
* Default is false.
|
||||
*/
|
||||
static bool printWhereFullPath_;
|
||||
|
||||
/*
|
||||
* If the logger limit the size of the "where" path to
|
||||
* characters. If the path is over 8 characters, a "~"
|
||||
* is added. Only works when "printWhereFullPath_" is false.
|
||||
* Default is false.
|
||||
*/
|
||||
static bool limitWhereLength_;
|
||||
|
||||
/*
|
||||
* The type of the logger.
|
||||
*/
|
||||
static Type type_;
|
||||
|
||||
/*
|
||||
* The severity of the log.
|
||||
*/
|
||||
static Level level_;
|
||||
|
||||
/*
|
||||
* The severity at which the application exits.
|
||||
* Note : A FATAL level will always exit whatever the level specified here.
|
||||
*/
|
||||
static Level exitLevel_;
|
||||
|
||||
/*
|
||||
* The severity at which the message is also sent in a ULogEvent.
|
||||
*/
|
||||
static Level eventLevel_;
|
||||
|
||||
static const char * levelName_[5];
|
||||
|
||||
/*
|
||||
* Mutex used when accessing public functions.
|
||||
*/
|
||||
static UMutex loggerMutex_;
|
||||
|
||||
/*
|
||||
* If the logger prints messages only when ULogger::flush() is called.
|
||||
* Default is false.
|
||||
*/
|
||||
static bool buffered_;
|
||||
|
||||
static std::string bufferedMsgs_;
|
||||
|
||||
/*
|
||||
* State attribute. This state happens when an exit level
|
||||
* message is received.
|
||||
* Messages received during this state are not logged.
|
||||
* @see exitLevel_
|
||||
*/
|
||||
static bool exitingState_;
|
||||
};
|
||||
|
||||
#endif // ULOGGER_H
|
||||
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* utilite is a cross-platform library with
|
||||
* useful utilities for fast and small developing.
|
||||
* Copyright (C) 2010 Mathieu Labbe
|
||||
*
|
||||
* utilite is free library: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* utilite is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef UMUTEX_H
|
||||
#define UMUTEX_H
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include "find_object/utilite/UWin32.h"
|
||||
#else
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* A mutex class.
|
||||
*
|
||||
* On a lock() call, the calling thread is blocked if the
|
||||
* UMutex was previously locked by another thread. It is unblocked when unlock() is called.
|
||||
*
|
||||
* On Unix (not yet tested on Windows), UMutex is recursive: the same thread can
|
||||
* call multiple times lock() without being blocked.
|
||||
*
|
||||
* Example:
|
||||
* @code
|
||||
* UMutex m; // Mutex shared with another thread(s).
|
||||
* ...
|
||||
* m.lock();
|
||||
* // Data is protected here from the second thread
|
||||
* //(assuming the second one protects also with the same mutex the same data).
|
||||
* m.unlock();
|
||||
*
|
||||
* @endcode
|
||||
*
|
||||
* @see USemaphore
|
||||
*/
|
||||
class UMutex
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* The constructor.
|
||||
*/
|
||||
UMutex()
|
||||
{
|
||||
#ifdef WIN32
|
||||
InitializeCriticalSection(&C);
|
||||
#else
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
|
||||
pthread_mutex_init(&M,&attr);
|
||||
pthread_mutexattr_destroy(&attr);
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual ~UMutex()
|
||||
{
|
||||
#ifdef WIN32
|
||||
DeleteCriticalSection(&C);
|
||||
#else
|
||||
pthread_mutex_unlock(&M); pthread_mutex_destroy(&M);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Lock the mutex.
|
||||
*/
|
||||
int lock() const
|
||||
{
|
||||
#ifdef WIN32
|
||||
EnterCriticalSection(&C); return 0;
|
||||
#else
|
||||
return pthread_mutex_lock(&M);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
#if(_WIN32_WINNT >= 0x0400)
|
||||
int lockTry() const
|
||||
{
|
||||
return (TryEnterCriticalSection(&C)?0:EBUSY);
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
int lockTry() const
|
||||
{
|
||||
return pthread_mutex_trylock(&M);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Unlock the mutex.
|
||||
*/
|
||||
int unlock() const
|
||||
{
|
||||
#ifdef WIN32
|
||||
LeaveCriticalSection(&C); return 0;
|
||||
#else
|
||||
return pthread_mutex_unlock(&M);
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
#ifdef WIN32
|
||||
mutable CRITICAL_SECTION C;
|
||||
#else
|
||||
mutable pthread_mutex_t M;
|
||||
#endif
|
||||
void operator=(UMutex &M) {}
|
||||
UMutex( const UMutex &M ) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Automatically lock the referenced mutex on constructor and unlock mutex on destructor.
|
||||
*
|
||||
* Example:
|
||||
* @code
|
||||
* UMutex m; // Mutex shared with another thread(s).
|
||||
* ...
|
||||
* int myMethod()
|
||||
* {
|
||||
* UScopeMutex sm(m); // automatically lock the mutex m
|
||||
* if(cond1)
|
||||
* {
|
||||
* return 1; // automatically unlock the mutex m
|
||||
* }
|
||||
* else if(cond2)
|
||||
* {
|
||||
* return 2; // automatically unlock the mutex m
|
||||
* }
|
||||
* return 0; // automatically unlock the mutex m
|
||||
* }
|
||||
*
|
||||
* @endcode
|
||||
*
|
||||
* @see UMutex
|
||||
*/
|
||||
class UScopeMutex
|
||||
{
|
||||
public:
|
||||
UScopeMutex(const UMutex & mutex) :
|
||||
mutex_(mutex)
|
||||
{
|
||||
mutex_.lock();
|
||||
}
|
||||
// backward compatibility
|
||||
UScopeMutex(UMutex * mutex) :
|
||||
mutex_(*mutex)
|
||||
{
|
||||
mutex_.lock();
|
||||
}
|
||||
~UScopeMutex()
|
||||
{
|
||||
mutex_.unlock();
|
||||
}
|
||||
private:
|
||||
const UMutex & mutex_;
|
||||
};
|
||||
|
||||
#endif // UMUTEX_H
|
||||
@@ -0,0 +1,62 @@
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Written by Phillip Sitbon
|
||||
// Copyright 2003
|
||||
//
|
||||
// Win32.h
|
||||
// - Windows includes
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
#ifndef _U_Win32_
|
||||
#define _U_Win32_
|
||||
|
||||
#if !defined(_WINDOWS_)
|
||||
// WIN32 Excludes
|
||||
#ifdef WIN32_LEAN_AND_MEAN
|
||||
# define VC_EXTRALEAN
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# define _PRSHT_H_
|
||||
# define NOGDICAPMASKS // CC_*, LC_*, PC_*, CP_*, TC_*, RC_
|
||||
# define NOVIRTUALKEYCODES // VK_*
|
||||
# define NOWINMESSAGES // WM_*, EM_*, LB_*, CB_*
|
||||
# define NOWINSTYLES // WS_*, CS_*, ES_*, LBS_*, SBS_*, CBS_*
|
||||
# define NOSYSMETRICS // SM_*
|
||||
# define NOMENUS // MF_*
|
||||
# define NOICONS // IDI_*
|
||||
# define NOKEYSTATES // MK_*
|
||||
# define NOSYSCOMMANDS // SC_*
|
||||
# define NORASTEROPS // Binary and Tertiary raster ops
|
||||
# define NOSHOWWINDOW // SW_*
|
||||
# define OEMRESOURCE // OEM Resource values
|
||||
# define NOATOM // Atom Manager routines
|
||||
# define NOCLIPBOARD // Clipboard routines
|
||||
# define NOCOLOR // Screen colors
|
||||
# define NOCTLMGR // Control and Dialog routines
|
||||
# define NODRAWTEXT // DrawText() and DT_*
|
||||
# define NOGDI // All GDI defines and routines
|
||||
# define NOKERNEL // All KERNEL defines and routines
|
||||
# define NOUSER // All USER defines and routines
|
||||
# define NONLS // All NLS defines and routines
|
||||
# define NOMB // MB_* and MessageBox()
|
||||
# define NOMEMMGR // GMEM_*, LMEM_*, GHND, LHND, associated routines
|
||||
# define NOMETAFILE // typedef METAFILEPICT
|
||||
# define NOMINMAX // Macros min(a,b) and max(a,b)
|
||||
# define NOMSG // typedef MSG and associated routines
|
||||
# define NOOPENFILE // OpenFile(), OemToAnsi, AnsiToOem, and OF_*
|
||||
# define NOSCROLL // SB_* and scrolling routines
|
||||
# define NOSERVICE // All Service Controller routines, SERVICE_ equates, etc.
|
||||
# define NOSOUND // Sound driver routines
|
||||
# define NOTEXTMETRIC // typedef TEXTMETRIC and associated routines
|
||||
# define NOWH // SetWindowsHook and WH_*
|
||||
# define NOWINOFFSETS // GWL_*, GCL_*, associated routines
|
||||
# define NOCOMM // COMM driver routines
|
||||
# define NOKANJI // Kanji support stuff.
|
||||
# define NOHELP // Help engine interface.
|
||||
# define NOPROFILER // Profiler interface.
|
||||
# define NODEFERWINDOWPOS // DeferWindowPos routines
|
||||
# define NOMCX // Modem Configuration Extensions
|
||||
#endif // WIN32_LEAN_AND_MEAN
|
||||
//
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
#endif // !_U_Win32_
|
||||
Reference in New Issue
Block a user