reverted eclipse project name to find_object

git-svn-id: http://find-object.googlecode.com/svn/trunk/find_object@11 620bd6b2-0a58-f614-fd9a-1bd335dccda9
This commit is contained in:
matlabbe 2011-10-25 15:48:19 +00:00
commit e78b7ca029
27 changed files with 3366 additions and 0 deletions

94
.cproject Normal file
View File

@ -0,0 +1,94 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?fileVersion 4.0.0?>
<cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
<storageModule moduleId="org.eclipse.cdt.core.settings">
<cconfiguration id="cdt.managedbuild.toolchain.gnu.base.1122816744">
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.base.1122816744" moduleId="org.eclipse.cdt.core.settings" name="Default">
<externalSettings/>
<extensions>
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration artifactName="${ProjName}" buildProperties="" description="" id="cdt.managedbuild.toolchain.gnu.base.1122816744" name="Default" parent="org.eclipse.cdt.build.core.emptycfg">
<folderInfo id="cdt.managedbuild.toolchain.gnu.base.1122816744.306079558" name="/" resourcePath="">
<toolChain id="cdt.managedbuild.toolchain.gnu.base.1536867206" name="cdt.managedbuild.toolchain.gnu.base" superClass="cdt.managedbuild.toolchain.gnu.base">
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.target.gnu.platform.base.1135530120" name="Debug Platform" osList="linux,hpux,aix,qnx" superClass="cdt.managedbuild.target.gnu.platform.base"/>
<builder arguments="-C ${ProjDirPath}/build VERBOSE=true" command="make" id="cdt.managedbuild.target.gnu.builder.base.673178816" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="cdt.managedbuild.target.gnu.builder.base"/>
<tool id="cdt.managedbuild.tool.gnu.archiver.base.881773237" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/>
<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.base.2094327183" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.base">
<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.424205109" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
</tool>
<tool id="cdt.managedbuild.tool.gnu.c.compiler.base.86959710" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.base">
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1730465962" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
</tool>
<tool id="cdt.managedbuild.tool.gnu.c.linker.base.467751471" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.base"/>
<tool id="cdt.managedbuild.tool.gnu.cpp.linker.base.921357809" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.base">
<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.2123576755" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
</inputType>
</tool>
<tool id="cdt.managedbuild.tool.gnu.assembler.base.961100725" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.base">
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.652879249" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
</tool>
</toolChain>
</folderInfo>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
<storageModule moduleId="org.eclipse.cdt.core.language.mapping"/>
</cconfiguration>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<project id="find_object.null.1999159200" name="find_object"/>
</storageModule>
<storageModule moduleId="scannerConfiguration">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets">
<buildTargets>
<target name="CMake-MinGW-Debug" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>cmake</buildCommand>
<buildArguments>-E chdir build/ cmake -G "MinGW Makefiles" -D CMAKE_BUILD_TYPE=Debug ../</buildArguments>
<buildTarget/>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="CMake-MinGW-Release" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>cmake</buildCommand>
<buildArguments>-E chdir build/ cmake -G "MinGW Makefiles" -D CMAKE_BUILD_TYPE=Release ../</buildArguments>
<buildTarget/>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="CMake-Unix-Debug" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>cmake</buildCommand>
<buildArguments>-E chdir build/ cmake -G "Unix Makefiles" -D CMAKE_BUILD_TYPE=Debug ../</buildArguments>
<buildTarget/>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="CMake-Unix-Release" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>cmake</buildCommand>
<buildArguments>-E chdir build/ cmake -G "Unix Makefiles" -D CMAKE_BUILD_TYPE=Release ../</buildArguments>
<buildTarget/>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
</buildTargets>
</storageModule>
<storageModule moduleId="refreshScope" versionNumber="1">
<resource resourceType="PROJECT" workspacePath="/find_object"/>
</storageModule>
</cproject>

79
.project Normal file
View File

@ -0,0 +1,79 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>find_object</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
<triggers>clean,full,incremental,</triggers>
<arguments>
<dictionary>
<key>?name?</key>
<value></value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.append_environment</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.autoBuildTarget</key>
<value>all</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.buildArguments</key>
<value>-C ${ProjDirPath}/build VERBOSE=true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.buildCommand</key>
<value>make</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.cleanBuildTarget</key>
<value>clean</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.contents</key>
<value>org.eclipse.cdt.make.core.activeConfigSettings</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.enableAutoBuild</key>
<value>false</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.enableCleanBuild</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.enableFullBuild</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.fullBuildTarget</key>
<value>all</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.stopOnError</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.useDefaultBuildCmd</key>
<value>false</value>
</dictionary>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.cdt.core.cnature</nature>
<nature>org.eclipse.cdt.core.ccnature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
</natures>
</projectDescription>

17
CMakeLists.txt Normal file
View File

@ -0,0 +1,17 @@
# Top-Level CmakeLists.txt
cmake_minimum_required(VERSION 2.8.2)
PROJECT( FindObject )
ADD_DEFINITIONS(-DPROJECT_NAME="${PROJECT_NAME}")
####### OUTPUT DIR #######
SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin)
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin)
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/lib)
####### DEPENDENCIES #######
FIND_PACKAGE(OpenCV REQUIRED) # tested on 2.3.1
FIND_PACKAGE(Qt4 COMPONENTS QtCore QtGui) # tested on Qt4.7
####### SOURCES (Projects) #######
ADD_SUBDIRECTORY( src )

13
README Normal file
View File

@ -0,0 +1,13 @@
Requirements :
-Cmake (tested on 2.8.2)
-Qt4 (tested on 4.7)
-OpenCV (tested on 2.3.1)
Build from source:
$ cd find_object/build
$ cmake ..
$ make
$ cd ../bin
$ ./find_object
(enjoy!)

BIN
doc/Add_object.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 651 KiB

BIN
doc/Find_object.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 886 KiB

BIN
doc/Parameters.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 670 KiB

276
src/AddObjectDialog.cpp Normal file
View File

@ -0,0 +1,276 @@
#include "AddObjectDialog.h"
#include "ui_addObjectDialog.h"
#include "Object.h"
#include "KeypointItem.h"
#include "Camera.h"
#include "qtipl.h"
#include <stdio.h>
#include <QtGui/QGraphicsScene>
#include <QtGui/QGraphicsPixmapItem>
#include <QtGui/QMessageBox>
#include <opencv2/imgproc/imgproc_c.h>
#include <opencv2/highgui/highgui_c.h>
AddObjectDialog::AddObjectDialog(QList<Object*> * objects, QWidget * parent, Qt::WindowFlags f) :
QDialog(parent, f),
camera_(0),
objects_(objects),
cvImage_(0)
{
ui_ = new Ui_addObjectDialog();
ui_->setupUi(this);
camera_ = Settings::createCamera();
connect(&cameraTimer_, SIGNAL(timeout()), this, SLOT(update()));
connect(ui_->pushButton_cancel, SIGNAL(clicked()), this, SLOT(cancel()));
connect(ui_->pushButton_back, SIGNAL(clicked()), this, SLOT(back()));
connect(ui_->pushButton_next, SIGNAL(clicked()), this, SLOT(next()));
connect(ui_->pushButton_takePicture, SIGNAL(clicked()), this, SLOT(takePicture()));
connect(ui_->cameraView->scene(), SIGNAL(selectionChanged()), this, SLOT(updateNextButton()));
this->setState(kTakePicture);
}
AddObjectDialog::~AddObjectDialog()
{
if(cvImage_)
{
cvReleaseImage(&cvImage_);
}
if(camera_)
{
delete camera_;
}
delete ui_;
}
void AddObjectDialog::closeEvent(QCloseEvent* event)
{
QDialog::closeEvent(event);
}
void AddObjectDialog::next()
{
setState(state_+1);
}
void AddObjectDialog::back()
{
setState(state_-1);
}
void AddObjectDialog::cancel()
{
this->reject();
}
void AddObjectDialog::takePicture()
{
next();
}
void AddObjectDialog::updateNextButton()
{
if(state_ == kSelectFeatures)
{
if(ui_->cameraView->scene()->selectedItems().size() > 0)
{
ui_->pushButton_next->setEnabled(true);
}
else
{
ui_->pushButton_next->setEnabled(false);
}
}
}
void AddObjectDialog::setState(int state)
{
state_ = state;
if(state == kTakePicture)
{
ui_->pushButton_cancel->setEnabled(true);
ui_->pushButton_back->setEnabled(false);
ui_->pushButton_next->setEnabled(false);
ui_->pushButton_takePicture->setEnabled(true);
ui_->label_instruction->setText(tr("Place the object in front of the camera and click \"Take picture\"."));
ui_->pushButton_next->setText(tr("Next"));
ui_->cameraView->setVisible(true);
ui_->objectView->setVisible(false);
ui_->cameraView->setGraphicsViewMode(false);
if(!camera_->init())
{
QMessageBox::critical(this, tr("Camera error"), tr("Camera initialization failed! (with device %1)").arg(Settings::getCamera_deviceId().toInt()));
ui_->pushButton_takePicture->setEnabled(false);
}
else
{
cameraTimer_.start(1000/Settings::getCamera_imageRate().toInt());
}
}
else if(state == kSelectFeatures)
{
cameraTimer_.stop();
camera_->close();
ui_->pushButton_cancel->setEnabled(true);
ui_->pushButton_back->setEnabled(true);
ui_->pushButton_next->setEnabled(false);
ui_->pushButton_takePicture->setEnabled(false);
ui_->label_instruction->setText(tr("Select features representing the object."));
ui_->pushButton_next->setText(tr("Next"));
ui_->cameraView->setVisible(true);
ui_->objectView->setVisible(false);
ui_->cameraView->setGraphicsViewMode(true);
}
else if(state == kVerifySelection)
{
cameraTimer_.stop();
camera_->close();
ui_->pushButton_cancel->setEnabled(true);
ui_->pushButton_back->setEnabled(true);
ui_->pushButton_takePicture->setEnabled(false);
ui_->pushButton_next->setText(tr("End"));
ui_->cameraView->setVisible(true);
ui_->objectView->setVisible(true);
ui_->cameraView->setGraphicsViewMode(true);
std::vector<cv::KeyPoint> selectedKeypoints = ui_->cameraView->selectedKeypoints();
// Select keypoints
if(selectedKeypoints.size() && cvImage_)
{
CvRect roi = computeROI(selectedKeypoints);
cvSetImageROI(cvImage_, roi);
if(roi.x != 0 || roi.y != 0)
{
for(unsigned int i=0; i<selectedKeypoints.size(); ++i)
{
selectedKeypoints.at(i).pt.x -= roi.x;
selectedKeypoints.at(i).pt.y -= roi.y;
}
}
ui_->objectView->setData(selectedKeypoints, cv::Mat(), cvImage_);
cvResetImageROI(cvImage_);
ui_->pushButton_next->setEnabled(true);
}
else
{
printf("Please select items\n");
ui_->pushButton_next->setEnabled(false);
}
ui_->label_instruction->setText(tr("Selection : %1 features").arg(selectedKeypoints.size()));
}
else if(state == kClosing)
{
std::vector<cv::KeyPoint> selectedKeypoints = ui_->cameraView->selectedKeypoints();
if(selectedKeypoints.size())
{
// Extract descriptors
cv::Mat descriptors;
cv::DescriptorExtractor * extractor = Settings::createDescriptorsExtractor();
extractor->compute(cvImage_, selectedKeypoints, descriptors);
delete extractor;
if(selectedKeypoints.size() != descriptors.rows)
{
printf("ERROR : keypoints=%lu != descriptors=%d\n", selectedKeypoints.size(), descriptors.rows);
}
CvRect roi = computeROI(selectedKeypoints);
cvSetImageROI(cvImage_, roi);
if(roi.x != 0 || roi.y != 0)
{
for(unsigned int i=0; i<selectedKeypoints.size(); ++i)
{
selectedKeypoints.at(i).pt.x -= roi.x;
selectedKeypoints.at(i).pt.y -= roi.y;
}
}
objects_->append(new Object(0, selectedKeypoints, descriptors, cvImage_, Settings::currentDetectorType(), Settings::currentDescriptorType()));
cvResetImageROI(cvImage_);
this->accept();
}
}
}
void AddObjectDialog::update()
{
if(cvImage_)
{
cvReleaseImage(&cvImage_);
cvImage_ = 0;
}
cvImage_ = camera_->takeImage();
if(cvImage_)
{
// convert to grayscale
if(cvImage_->nChannels != 1 || cvImage_->depth != IPL_DEPTH_8U)
{
IplImage * imageGrayScale = cvCreateImage(cvSize(cvImage_->width, cvImage_->height), IPL_DEPTH_8U, 1);
cvCvtColor(cvImage_, imageGrayScale, CV_BGR2GRAY);
cvReleaseImage(&cvImage_);
cvImage_ = imageGrayScale;
}
// Extract keypoints
cv::FeatureDetector * detector = Settings::createFeaturesDetector();
cv::vector<cv::KeyPoint> keypoints;
detector->detect(cvImage_, keypoints);
delete detector;
ui_->cameraView->setData(keypoints, cv::Mat(), cvImage_);
ui_->cameraView->update();
}
}
CvRect AddObjectDialog::computeROI(const std::vector<cv::KeyPoint> & kpts)
{
CvRect roi;
int x1,x2,h1,h2;
for(unsigned int i=0; i<kpts.size(); ++i)
{
float radius = kpts.at(i).size / 2;
if(i==0)
{
x1 = int(kpts.at(i).pt.x - radius);
x2 = int(kpts.at(i).pt.x + radius);
h1 = int(kpts.at(i).pt.y - radius);
h2 = int(kpts.at(i).pt.y + radius);
}
else
{
if(x1 > int(kpts.at(i).pt.x - radius))
{
x1 = int(kpts.at(i).pt.x - radius);
}
else if(x2 < int(kpts.at(i).pt.x + radius))
{
x2 = int(kpts.at(i).pt.x + radius);
}
if(h1 > int(kpts.at(i).pt.y - radius))
{
h1 = int(kpts.at(i).pt.y - radius);
}
else if(h2 < int(kpts.at(i).pt.y + radius))
{
h2 = int(kpts.at(i).pt.y + radius);
}
}
roi.x = x1;
roi.y = h1;
roi.width = x2-x1;
roi.height = h2-h1;
printf("ptx=%d, pty=%d\n", (int)kpts.at(i).pt.x, (int)kpts.at(i).pt.y);
printf("x=%d, y=%d, w=%d, h=%d\n", roi.x, roi.y, roi.width, roi.height);
}
return roi;
}

47
src/AddObjectDialog.h Normal file
View File

@ -0,0 +1,47 @@
#ifndef ADDOBJECTDIALOG_H_
#define ADDOBJECTDIALOG_H_
#include <QtGui/QDialog>
#include <QtCore/QTimer>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/core/core_c.h>
class Ui_addObjectDialog;
class Object;
class Camera;
class KeypointItem;
class AddObjectDialog : public QDialog {
Q_OBJECT
public:
AddObjectDialog(QList<Object*> * objects, QWidget * parent = 0, Qt::WindowFlags f = 0);
virtual ~AddObjectDialog();
private slots:
void update();
void next();
void back();
void cancel();
void takePicture();
void updateNextButton();
protected:
virtual void closeEvent(QCloseEvent* event);
private:
void setState(int state);
CvRect computeROI(const std::vector<cv::KeyPoint> & kpts);
private:
Ui_addObjectDialog * ui_;
Camera * camera_;
QTimer cameraTimer_;
QList<Object*> * objects_;
IplImage * cvImage_;
enum State{kTakePicture, kSelectFeatures, kVerifySelection, kClosing};
int state_;
};
#endif /* ADDOBJECTDIALOG_H_ */

69
src/CMakeLists.txt Normal file
View File

@ -0,0 +1,69 @@
### Qt Gui stuff ###
SET(headers_ui
./MainWindow.h
./AddObjectDialog.h
./Object.h
./Camera.h
./ParametersToolBox.h
)
SET(uis
./ui/mainWindow.ui
./ui/addObjectDialog.ui
)
#SET(qrc
# ./GuiLib.qrc
#)
# generate rules for building source files from the resources
#QT4_ADD_RESOURCES(srcs_qrc ${qrc})
#Generate .h files from the .ui files
QT4_WRAP_UI(moc_uis ${uis})
#This will generate moc_* for Qt
QT4_WRAP_CPP(moc_srcs ${headers_ui})
### Qt Gui stuff end###
SET(SRC_FILES
./MainWindow.cpp
./AddObjectDialog.cpp
./KeypointItem.cpp
./qtipl.cpp
./main.cpp
./Camera.cpp
./ParametersToolBox.cpp
./Settings.cpp
./Object.cpp
${moc_srcs}
${moc_uis}
#${srcs_qrc}
)
SET(INCLUDE_DIRS
${CMAKE_CURRENT_SOURCE_DIR}
${OpenCV_INCLUDE_DIRS}
${CMAKE_CURRENT_BINARY_DIR} # for qt ui generated in binary dir
)
INCLUDE(${QT_USE_FILE})
SET(LIBRARIES
${QT_LIBRARIES}
${OpenCV_LIBS}
)
#include files
INCLUDE_DIRECTORIES(${INCLUDE_DIRS})
# create an executable file
ADD_EXECUTABLE(find_object ${SRC_FILES})
# Linking with Qt libraries
TARGET_LINK_LIBRARIES(find_object ${LIBRARIES})

95
src/Camera.cpp Normal file
View File

@ -0,0 +1,95 @@
/*
* Camera.cpp
*
* Created on: 2011-10-21
* Author: matlab
*/
#include "Camera.h"
#include <stdio.h>
#include <opencv2/imgproc/imgproc_c.h>
Camera::Camera(int deviceId,
int imageWidth,
int imageHeight,
QObject * parent) :
QObject(parent),
capture_(0),
deviceId_(deviceId),
imageWidth_(imageWidth),
imageHeight_(imageHeight)
{
}
Camera::~Camera()
{
this->close();
}
bool Camera::init()
{
if(!capture_)
{
capture_ = cvCaptureFromCAM(deviceId_);
if(capture_)
{
cvSetCaptureProperty(capture_, CV_CAP_PROP_FRAME_WIDTH, double(imageWidth_));
cvSetCaptureProperty(capture_, CV_CAP_PROP_FRAME_HEIGHT, double(imageHeight_));
}
}
if(!capture_)
{
printf("Failed to create a capture object!\n");
return false;
}
return true;
}
void Camera::close()
{
if(capture_)
{
cvReleaseCapture(&capture_);
capture_ = 0;
}
}
IplImage * Camera::takeImage()
{
IplImage * img = 0;
if(capture_)
{
if(cvGrabFrame(capture_)) // capture a frame
{
img = cvRetrieveFrame(capture_); // retrieve the captured frame
}
else
{
printf("CameraVideo: Could not grab a frame, the end of the feed may be reached...\n");
}
}
//resize
if(img &&
imageWidth_ &&
imageHeight_ &&
imageWidth_ != (unsigned int)img->width &&
imageHeight_ != (unsigned int)img->height)
{
// declare a destination IplImage object with correct size, depth and channels
IplImage * resampledImg = cvCreateImage( cvSize(imageWidth_, imageHeight_),
img->depth,
img->nChannels );
//use cvResize to resize source to a destination image (linear interpolation)
cvResize(img, resampledImg);
img = resampledImg;
}
else if(img)
{
img = cvCloneImage(img);
}
return img;
}

47
src/Camera.h Normal file
View File

@ -0,0 +1,47 @@
/*
* Camera.h
*
* Created on: 2011-10-21
* Author: matlab
*/
#ifndef CAMERA_H_
#define CAMERA_H_
#include <opencv2/highgui/highgui.hpp>
#include <QtCore/QObject>
#include "Settings.h"
class Camera : public QObject {
Q_OBJECT
public:
Camera(int deviceId = Settings::defaultCamera_deviceId(),
int width = Settings::defaultCamera_imageWidth(),
int height = Settings::defaultCamera_imageHeight(),
QObject * parent = 0);
virtual ~Camera();
void setDeviceId(int deviceId) {deviceId_=deviceId;}
void setImageWidth(int imageWidth) {imageWidth_=imageWidth;}
void setImageHeight(int imageHeight) {imageHeight_=imageHeight;}
int getDeviceId() const {return deviceId_;}
int getImageWidth() const {return imageWidth_;}
int getImageHeight() const {return imageHeight_;}
signals:
void ready();
public:
bool init();
void close();
IplImage * takeImage();
private:
CvCapture * capture_;
int deviceId_;
int imageWidth_;
int imageHeight_;
};
#endif /* CAMERA_H_ */

109
src/KeypointItem.cpp Normal file
View File

@ -0,0 +1,109 @@
#include "KeypointItem.h"
#include <QtGui/QPen>
#include <QtGui/QBrush>
#include <QtGui/QGraphicsScene>
KeypointItem::KeypointItem(int id, qreal x, qreal y, int r, const QString & info, const QColor & color, QGraphicsItem * parent) :
QGraphicsEllipseItem(x, y, r, r, parent),
_info(info),
_placeHolder(0),
_id(id)
{
this->setPen(QPen(color));
this->setBrush(QBrush(color));
this->setAcceptsHoverEvents(true);
this->setFlag(QGraphicsItem::ItemIsFocusable, true);
this->setFlag(QGraphicsItem::ItemIsSelectable, true);
_width = pen().width();
}
KeypointItem::~KeypointItem()
{
/*if(_placeHolder)
{
delete _placeHolder;
}*/
}
void KeypointItem::setColor(const QColor & color)
{
this->setPen(QPen(color));
this->setBrush(QBrush(color));
if(_placeHolder)
{
QList<QGraphicsItem *> items = _placeHolder->children();
if(items.size())
{
((QGraphicsTextItem *)items.front())->setDefaultTextColor(this->pen().color().rgb());
}
}
}
void KeypointItem::showDescription()
{
if(!_placeHolder)
{
_placeHolder = new QGraphicsRectItem();
_placeHolder->setVisible(false);
this->scene()->addItem(_placeHolder);
_placeHolder->setBrush(QBrush(QColor ( 0, 0, 0, 170 ))); // Black transparent background
QGraphicsTextItem * text = new QGraphicsTextItem(_placeHolder);
text->setDefaultTextColor(this->pen().color().rgb());
text->setPlainText(_info);
_placeHolder->setRect(text->boundingRect());
}
QPen pen = this->pen();
this->setPen(QPen(pen.color(), _width+2));
_placeHolder->setZValue(this->zValue()+1);
_placeHolder->setPos(this->mapToScene(0,0));
_placeHolder->setVisible(true);
}
void KeypointItem::hideDescription()
{
if(_placeHolder)
{
_placeHolder->setVisible(false);
}
this->setPen(QPen(pen().color(), _width));
}
void KeypointItem::hoverEnterEvent ( QGraphicsSceneHoverEvent * event )
{
QGraphicsScene * scene = this->scene();
if(scene && scene->focusItem() == 0)
{
this->showDescription();
}
else
{
this->setPen(QPen(pen().color(), _width+2));
}
QGraphicsEllipseItem::hoverEnterEvent(event);
}
void KeypointItem::hoverLeaveEvent ( QGraphicsSceneHoverEvent * event )
{
if(!this->hasFocus())
{
this->hideDescription();
}
QGraphicsEllipseItem::hoverEnterEvent(event);
}
void KeypointItem::focusInEvent ( QFocusEvent * event )
{
this->showDescription();
QGraphicsEllipseItem::focusInEvent(event);
}
void KeypointItem::focusOutEvent ( QFocusEvent * event )
{
this->hideDescription();
QGraphicsEllipseItem::focusOutEvent(event);
}

37
src/KeypointItem.h Normal file
View File

@ -0,0 +1,37 @@
#ifndef KEYPOINTITEM_H_
#define KEYPOINTITEM_H_
#include <QtGui/QGraphicsEllipseItem>
#include <QtGui/QGraphicsTextItem>
#include <QtGui/QPen>
#include <QtGui/QBrush>
class KeypointItem : public QGraphicsEllipseItem
{
public:
KeypointItem(int id, qreal x, qreal y, int r, const QString & info, const QColor & color = Qt::green, QGraphicsItem * parent = 0);
virtual ~KeypointItem();
void setColor(const QColor & color);
int id() const {return _id;}
protected:
virtual void hoverEnterEvent ( QGraphicsSceneHoverEvent * event );
virtual void hoverLeaveEvent ( QGraphicsSceneHoverEvent * event );
virtual void focusInEvent ( QFocusEvent * event );
virtual void focusOutEvent ( QFocusEvent * event );
private:
void showDescription();
void hideDescription();
private:
QString _info;
QGraphicsRectItem * _placeHolder;
int _width;
int _id;
};
#endif /* KEYPOINTITEM_H_ */

476
src/MainWindow.cpp Normal file
View File

@ -0,0 +1,476 @@
#include "MainWindow.h"
#include "AddObjectDialog.h"
#include "ui_mainWindow.h"
#include "qtipl.h"
#include "KeypointItem.h"
#include "Object.h"
#include "Camera.h"
#include "Settings.h"
#include "ParametersToolBox.h"
#include <iostream>
#include <stdio.h>
#include "opencv2/calib3d/calib3d.hpp"
#include <QtCore/QTextStream>
#include <QtCore/QFile>
#include <QtGui/QFileDialog>
#include <QtGui/QMessageBox>
#include <QtGui/QGraphicsScene>
MainWindow::MainWindow(QWidget * parent) :
QMainWindow(parent),
camera_(0)
{
ui_ = new Ui_mainWindow();
ui_->setupUi(this);
connect(&cameraTimer_, SIGNAL(timeout()), this, SLOT(update()));
QByteArray geometry;
Settings::loadSettings(Settings::iniDefaultFileName, &geometry);
this->restoreGeometry(geometry);
ui_->toolBox->setupUi();
ui_->dockWidget_parameters->hide();
ui_->menuView->addAction(ui_->dockWidget_parameters->toggleViewAction());
ui_->menuView->addAction(ui_->dockWidget_objects->toggleViewAction());
ui_->imageView_source->setGraphicsViewMode(false);
//reset button
connect(ui_->pushButton_restoreDefaults, SIGNAL(clicked()), ui_->toolBox, SLOT(resetCurrentPage()));
ui_->actionStop_camera->setEnabled(false);
ui_->actionSave_objects->setEnabled(false);
// Actions
connect(ui_->actionAdd_object, SIGNAL(triggered()), this, SLOT(addObject()));
connect(ui_->actionStart_camera, SIGNAL(triggered()), this, SLOT(startCamera()));
connect(ui_->actionStop_camera, SIGNAL(triggered()), this, SLOT(stopCamera()));
connect(ui_->actionExit, SIGNAL(triggered()), this, SLOT(close()));
connect(ui_->actionSave_objects, SIGNAL(triggered()), this, SLOT(saveObjects()));
connect(ui_->actionLoad_objects, SIGNAL(triggered()), this, SLOT(loadObjects()));
}
MainWindow::~MainWindow()
{
this->stopCamera();
if(camera_)
{
delete camera_;
camera_ = 0;
}
dataTree_ = cv::Mat();
qDeleteAll(objects_.begin(), objects_.end());
objects_.clear();
delete ui_;
}
void MainWindow::closeEvent(QCloseEvent * event)
{
Settings::saveSettings(Settings::iniDefaultFileName, this->saveGeometry());
QMainWindow::closeEvent(event);
}
void MainWindow::loadObjects()
{
QString fileName = QFileDialog::getOpenFileName(this, tr("Load objects..."), "", "*.obj");
if(!fileName.isEmpty())
{
QFile file(fileName);
file.open(QIODevice::ReadOnly);
QDataStream in(&file);
while(!in.atEnd())
{
Object * obj = new Object();
obj->load(in);
bool alreadyLoaded = false;
for(int i=0; i<objects_.size(); ++i)
{
if(objects_.at(i)->id() == obj->id())
{
alreadyLoaded = true;
break;
}
}
if(!alreadyLoaded)
{
objects_.append(obj);
showObject(obj);
}
else
{
delete obj;
}
}
file.close();
}
}
void MainWindow::saveObjects()
{
QString fileName = QFileDialog::getSaveFileName(this, tr("Save objects..."), Settings::currentDetectorType()+Settings::currentDescriptorType()+QString("%1.obj").arg(objects_.size()), "*.obj");
if(!fileName.isEmpty())
{
if(!fileName.endsWith(".obj"))
{
fileName.append(".obj");//default
}
QFile file(fileName);
file.open(QIODevice::WriteOnly);
QDataStream out(&file);
for(int i=0; i<objects_.size(); ++i)
{
objects_.at(i)->save(out);
}
file.close();
}
}
void MainWindow::removeObject(Object * object)
{
if(object)
{
objects_.removeOne(object);
object->deleteLater();
this->updateData();
}
}
void MainWindow::addObject()
{
this->stopCamera();
AddObjectDialog dialog(&objects_, this);
if(dialog.exec() == QDialog::Accepted)
{
showObject(objects_.last());
}
}
void MainWindow::showObject(Object * obj)
{
if(obj)
{
obj->setGraphicsViewMode(false);
QList<Object*> objs = ui_->objects_area->findChildren<Object*>();
QVBoxLayout * vLayout = new QVBoxLayout();
int id = Settings::getGeneral_nextObjID().toInt();
if(obj->id() == 0)
{
obj->setId(id++);
Settings::setGeneral_nextObjID(id);
}
else if(obj->id() > id)
{
id = obj->id()+1;
Settings::setGeneral_nextObjID(id);
}
QLabel * title = new QLabel(QString("%1 (%2)").arg(obj->id()).arg(QString::number(obj->keypoints().size())), this);
QLabel * detectedLabel = new QLabel(this);
QLabel * detectorDescriptorType = new QLabel(QString("%1/%2").arg(obj->detectorType()).arg(obj->descriptorType()), this);
detectedLabel->setObjectName(QString("%1detection").arg(obj->id()));
QHBoxLayout * hLayout = new QHBoxLayout();
hLayout->addWidget(title);
hLayout->addWidget(detectorDescriptorType);
hLayout->addWidget(detectedLabel);
hLayout->addStretch(1);
vLayout->addLayout(hLayout);
vLayout->addWidget(obj);
objects_.last()->setDeletable(true);
connect(obj, SIGNAL(removalTriggered(Object*)), this, SLOT(removeObject(Object*)));
connect(obj, SIGNAL(destroyed(QObject *)), title, SLOT(deleteLater()));
connect(obj, SIGNAL(destroyed(QObject *)), detectedLabel, SLOT(deleteLater()));
connect(obj, SIGNAL(destroyed(QObject *)), detectorDescriptorType, SLOT(deleteLater()));
connect(obj, SIGNAL(destroyed(QObject *)), vLayout, SLOT(deleteLater()));
ui_->verticalLayout_objects->insertLayout(ui_->verticalLayout_objects->count()-1, vLayout);
this->updateData();
}
}
void MainWindow::updateData()
{
if(objects_.size())
{
ui_->actionSave_objects->setEnabled(true);
}
else
{
ui_->actionSave_objects->setEnabled(false);
}
dataTree_ = cv::Mat();
dataRange_.clear();
int count = 0;
int dim = -1;
int type = -1;
// Get the total size and verify descriptors
for(int i=0; i<objects_.size(); ++i)
{
if(dim >= 0 && objects_.at(i)->descriptors().cols != dim)
{
QMessageBox::critical(this, tr("Error"), tr("Descriptors of the objects are not all the same size!\nObjects opened must have all the same size (and from the same descriptor extractor)."));
return;
}
dim = objects_.at(i)->descriptors().cols;
if(type >= 0 && objects_.at(i)->descriptors().type() != type)
{
QMessageBox::critical(this, tr("Error"), tr("Descriptors of the objects are not all the same type!\nObjects opened must have been processed by the same descriptor extractor."));
return;
}
type = objects_.at(i)->descriptors().type();
count += objects_.at(i)->descriptors().rows;
}
// Copy data
if(count)
{
cv::Mat data(count, dim, type);
printf("Total descriptors=%d, dim=%d, type=%d\n",count, dim, type);
int row = 0;
for(int i=0; i<objects_.size(); ++i)
{
cv::Mat dest(data, cv::Range(row, row+objects_.at(i)->descriptors().rows));
objects_.at(i)->descriptors().copyTo(dest);
row += objects_.at(i)->descriptors().rows;
dataRange_.append(row);
}
data.convertTo(dataTree_, CV_32F);
}
}
void MainWindow::startCamera()
{
if(camera_)
{
camera_->close();
delete camera_;
}
camera_ = Settings::createCamera();
connect(camera_, SIGNAL(ready()), this, SLOT(update()));
if(camera_->init())
{
cameraTimer_.start(1000/Settings::getCamera_imageRate().toInt());
ui_->actionStop_camera->setEnabled(true);
ui_->actionStart_camera->setEnabled(false);
}
else
{
QMessageBox::critical(this, tr("Camera error"), tr("Camera initialization failed! (with device %1)").arg(Settings::getCamera_deviceId().toInt()));
}
}
void MainWindow::stopCamera()
{
if(camera_)
{
cameraTimer_.stop();
camera_->close();
delete camera_;
camera_ = 0;
}
ui_->actionStop_camera->setEnabled(false);
ui_->actionStart_camera->setEnabled(true);
}
void MainWindow::update()
{
// reset objects color
for(int i=0; i<objects_.size(); ++i)
{
objects_[i]->resetKptsColor();
}
if(camera_)
{
IplImage * cvImage = camera_->takeImage();
if(cvImage)
{
QTime time;
//Convert to grayscale
IplImage * imageGrayScale = 0;
if(cvImage->nChannels != 1 || cvImage->depth != IPL_DEPTH_8U)
{
imageGrayScale = cvCreateImage(cvSize(cvImage->width,cvImage->height), IPL_DEPTH_8U, 1);
cvCvtColor(cvImage, imageGrayScale, CV_BGR2GRAY);
}
cv::Mat img;
if(imageGrayScale)
{
img = cv::Mat(imageGrayScale);
}
else
{
img = cv::Mat(cvImage);
}
// EXTRACT KEYPOINTS
time.start();
cv::FeatureDetector * detector = Settings::createFeaturesDetector();
std::vector<cv::KeyPoint> keypoints;
detector->detect(img, keypoints);
delete detector;
ui_->label_timeDetection->setText(QString::number(time.elapsed()));
// EXTRACT DESCRIPTORS
time.start();
cv::Mat descriptors;
cv::DescriptorExtractor * extractor = Settings::createDescriptorsExtractor();
extractor->compute(img, keypoints, descriptors);
delete extractor;
if(keypoints.size() != descriptors.rows)
{
printf("ERROR : kpt=%lu != descriptors=%d\n", keypoints.size(), descriptors.rows);
}
if(imageGrayScale)
{
cvReleaseImage(&imageGrayScale);
}
ui_->label_timeExtraction->setText(QString::number(time.elapsed()));
// COMPARE
int alpha = 20*255/100;
if(!dataTree_.empty())
{
// CREATE INDEX
time.start();
cv::Mat environment(descriptors.rows, descriptors.cols, CV_32F);
descriptors.convertTo(environment, CV_32F);
cv::flann::Index treeFlannIndex(environment, cv::flann::KDTreeIndexParams());
ui_->label_timeIndexing->setText(QString::number(time.elapsed()));
// DO NEAREST NEIGHBOR
time.start();
int k = 2;
int emax = 64;
cv::Mat results(dataTree_.rows, k, CV_32SC1); // results index
cv::Mat dists(dataTree_.rows, k, CV_32FC1); // Distance results are CV_32FC1
treeFlannIndex.knnSearch(dataTree_, results, dists, k, cv::flann::SearchParams(emax) ); // maximum number of leafs checked
ui_->label_timeMatching->setText(QString::number(time.elapsed()));
// PROCESS RESULTS
time.start();
ui_->imageView_source->setData(keypoints, cv::Mat(), cvImage);
int j=0;
std::vector<cv::Point2f> mpts_1, mpts_2;
std::vector<int> indexes_1, indexes_2;
std::vector<uchar> outlier_mask;
for(unsigned int i=0; i<dataTree_.rows; ++i)
{
// Check if this descriptor matches with those of the objects
// Apply NNDR
if(dists.at<float>(i,0) <= Settings::getNN_nndrRatio().toFloat() * dists.at<float>(i,1))
{
if(j>0)
{
mpts_1.push_back(objects_.at(j)->keypoints().at(i-dataRange_.at(j-1)).pt);
indexes_1.push_back(i-dataRange_.at(j-1));
}
else
{
mpts_1.push_back(objects_.at(j)->keypoints().at(i).pt);
indexes_1.push_back(i);
}
mpts_2.push_back(ui_->imageView_source->keypoints().at(results.at<int>(i,0)).pt);
indexes_2.push_back(results.at<int>(i,0));
}
if(i+1 >= dataRange_.at(j))
{
QLabel * label = ui_->dockWidget_objects->findChild<QLabel*>(QString("%1detection").arg(objects_.at(j)->id()));
if(mpts_1.size() >= Settings::getHomography_minimumInliers().toInt())
{
cv::Mat H = findHomography(mpts_1,
mpts_2,
cv::RANSAC,
Settings::getHomography_ransacReprojThr().toDouble(),
outlier_mask);
int inliers=0, outliers=0;
QColor color((Qt::GlobalColor)(j % 12 + 7 ));
color.setAlpha(alpha);
for(int k=0; k<mpts_1.size();++k)
{
if(outlier_mask.at(k))
{
++inliers;
}
else
{
++outliers;
}
}
// COLORIZE
if(inliers >= Settings::getHomography_minimumInliers().toInt())
{
for(int k=0; k<mpts_1.size();++k)
{
if(outlier_mask.at(k))
{
objects_.at(j)->setKptColor(indexes_1.at(k), color);
ui_->imageView_source->setKptColor(indexes_2.at(k), color);
}
else
{
objects_.at(j)->setKptColor(indexes_1.at(k), QColor(0,0,0,alpha));
}
}
label->setText(QString("%1 in %2 out").arg(inliers).arg(outliers));
QTransform hTransform(
H.at<double>(0,0), H.at<double>(1,0), H.at<double>(2,0),
H.at<double>(0,1), H.at<double>(1,1), H.at<double>(2,1),
H.at<double>(0,2), H.at<double>(1,2), H.at<double>(2,2));
QPen rectPen(color);
rectPen.setWidth(4);
QGraphicsRectItem * rectItem = ui_->imageView_source->scene()->addRect(objects_.at(j)->image().rect(), rectPen);
rectItem->setTransform(hTransform);
}
else
{
label->setText(QString("Too low inliers (%1)").arg(inliers));
}
}
else
{
label->setText(QString("Too low matches (%1)").arg(mpts_1.size()));
}
mpts_1.clear();
mpts_2.clear();
indexes_1.clear();
indexes_2.clear();
outlier_mask.clear();
++j;
}
}
}
else
{
ui_->imageView_source->setData(keypoints, cv::Mat(), cvImage);
}
//Update object pictures
for(int i=0; i<objects_.size(); ++i)
{
objects_[i]->update();
}
ui_->label_nfeatures->setText(QString::number(keypoints.size()));
ui_->imageView_source->update();
ui_->label_timeGui->setText(QString::number(time.elapsed()));
cvReleaseImage(&cvImage);
}
}
ui_->label_detectorDescriptorType->setText(QString("%1/%2").arg(Settings::currentDetectorType()).arg(Settings::currentDescriptorType()));
ui_->label_timeRefreshRate->setText(QString("(%1 Hz - %2 Hz)").arg(QString::number(1000/cameraTimer_.interval())).arg(QString::number(int(1000.0f/(float)(updateRate_.elapsed())))));
//printf("GUI refresh rate %f Hz\n", 1000.0f/(float)(updateRate_.elapsed()));
updateRate_.start();
}

56
src/MainWindow.h Normal file
View File

@ -0,0 +1,56 @@
#ifndef MAINWINDOW_H_
#define MAINWINDOW_H_
#include <QtGui/QMainWindow>
#include <QtCore/QSet>
#include <QtCore/QTimer>
#include <QtCore/QTime>
#include <opencv2/core/core.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/imgproc/imgproc_c.h>
class Ui_mainWindow;
class Object;
class Camera;
class ParametersToolBox;
class QLabel;
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget * parent = 0);
virtual ~MainWindow();
protected:
virtual void closeEvent(QCloseEvent * event);
private slots:
void addObject();
void startCamera();
void stopCamera();
void loadObjects();
void saveObjects();
void update();
void updateData();
void removeObject(Object * object);
private:
void showObject(Object * obj);
private:
Ui_mainWindow * ui_;
Camera * camera_;
QList<Object*> objects_;
QTimer cameraTimer_;
cv::Mat dataTree_;
QList<int> dataRange_;
QTime updateRate_;
};
#endif /* MainWindow_H_ */

517
src/Object.cpp Normal file
View File

@ -0,0 +1,517 @@
/*
* Object.cpp
*
* Created on: 2011-10-23
* Author: matlab
*/
/*
* VisualObject.h
*
* Created on: 2011-10-21
* Author: matlab
*/
#include "Object.h"
#include "KeypointItem.h"
#include "qtipl.h"
#include <opencv2/highgui/highgui.hpp>
#include <QtGui/QWidget>
#include <QtGui/QContextMenuEvent>
#include <QtGui/QMenu>
#include <QtGui/QMenu>
#include <QtGui/QFileDialog>
#include <QtGui/QAction>
#include <QtGui/QGraphicsView>
#include <QtGui/QGraphicsScene>
#include <QtGui/QVBoxLayout>
#include <QtCore/QDir>
#include <stdio.h>
Object::Object(QWidget * parent) :
QWidget(parent),
iplImage_(0),
graphicsView_(0),
id_(0),
graphicsViewMode_(true),
detectorType_("NA"),
descriptorType_("NA")
{
setupUi();
}
Object::Object(int id,
const std::vector<cv::KeyPoint> & keypoints,
const cv::Mat & descriptors,
const IplImage * iplImage,
const QString & detectorType,
const QString & descriptorType,
QWidget * parent) :
QWidget(parent),
iplImage_(0),
graphicsView_(0),
id_(id),
graphicsViewMode_(true),
detectorType_(detectorType),
descriptorType_(descriptorType)
{
setupUi();
this->setData(keypoints, descriptors, iplImage);
}
Object::~Object()
{
if(iplImage_)
{
cvReleaseImage(&iplImage_);
}
}
void Object::setupUi()
{
graphicsView_ = new QGraphicsView(this);
graphicsView_->setVisible(true);
graphicsView_->setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
graphicsView_->setScene(new QGraphicsScene(graphicsView_));
this->setLayout(new QVBoxLayout(graphicsView_));
this->layout()->addWidget(graphicsView_);
this->layout()->setContentsMargins(0,0,0,0);
_menu = new QMenu(tr(""), this);
_showImage = _menu->addAction(tr("Show image"));
_showImage->setCheckable(true);
_showImage->setChecked(true);
_showFeatures = _menu->addAction(tr("Show features"));
_showFeatures->setCheckable(true);
_showFeatures->setChecked(true);
_mirrorView = _menu->addAction(tr("Mirror view"));
_mirrorView->setCheckable(true);
_mirrorView->setChecked(false);
_plainView = _menu->addAction(tr("Plain view"));
_plainView->setCheckable(true);
_plainView->setChecked(!graphicsViewMode_);
_menu->addSeparator();
_saveImage = _menu->addAction(tr("Save picture..."));
_menu->addSeparator();
_delete = _menu->addAction(tr("Delete"));
_delete->setEnabled(false);
this->setId(id_);
graphicsView_->setRubberBandSelectionMode(Qt::ContainsItemShape);
graphicsView_->setDragMode(QGraphicsView::RubberBandDrag);
}
void Object::setId(int id)
{
id_=id;
if(id_)
{
_savedFileName = QString("object_%1.png").arg(id_);
}
}
void Object::setGraphicsViewMode(bool on)
{
graphicsViewMode_ = on;
graphicsView_->setVisible(on);
//update items' color
if(on)
{
if(keypointItems_.size() == 0)
{
this->setupGraphicsView();
}
else
{
for(int i=0; i<keypointItems_.size(); ++i)
{
keypointItems_[i]->setColor(kptColors_.at(i));
}
}
}
graphicsView_->fitInView(graphicsView_->sceneRect(), Qt::KeepAspectRatio);
_plainView->setChecked(!on);
this->update();
}
// ownership transferred
void Object::setData(const std::vector<cv::KeyPoint> & keypoints, const cv::Mat & descriptors, const IplImage * image)
{
keypoints_ = keypoints;
descriptors_ = descriptors;
kptColors_ = QVector<QColor>(keypoints.size(), defaultColor());
keypointItems_.clear();
if(iplImage_)
{
cvReleaseImage(&iplImage_);
iplImage_ = 0;
}
if(image)
{
/* create destination image
Note that cvGetSize will return the width and the height of ROI */
iplImage_ = cvCreateImage(cvGetSize(image),
image->depth,
image->nChannels);
/* copy subimage */
cvCopy(image, iplImage_, NULL);
image_ = QPixmap::fromImage(Ipl2QImage(iplImage_));
this->setMinimumSize(image_.size());
}
if(graphicsViewMode_)
{
this->setupGraphicsView();
}
}
void Object::resetKptsColor()
{
for(int i=0; i<kptColors_.size(); ++i)
{
kptColors_[i] = defaultColor();
if(graphicsViewMode_)
{
keypointItems_[i]->setColor(this->defaultColor());
}
}
}
void Object::setKptColor(unsigned int index, const QColor & color)
{
if(index < kptColors_.size())
{
kptColors_[index] = color;
}
if(graphicsViewMode_)
{
if(index < keypointItems_.size())
{
keypointItems_.at(index)->setColor(color);
}
}
}
bool Object::isImageShown() const
{
return _showImage->isChecked();
}
bool Object::isFeaturesShown() const
{
return _showFeatures->isChecked();
}
bool Object::isMirrorView() const
{
return _mirrorView->isChecked();
}
QGraphicsScene * Object::scene() const
{
return graphicsView_->scene();
}
void Object::setDeletable(bool deletable)
{
_delete->setEnabled(deletable);
}
void Object::save(QDataStream & streamPtr) const
{
streamPtr << id_ << detectorType_ << descriptorType_;
streamPtr << (int)keypoints_.size();
for(int j=0; j<keypoints_.size(); ++j)
{
streamPtr << keypoints_.at(j).angle <<
keypoints_.at(j).class_id <<
keypoints_.at(j).octave <<
keypoints_.at(j).pt.x <<
keypoints_.at(j).pt.y <<
keypoints_.at(j).response <<
keypoints_.at(j).size;
}
qint64 dataSize = descriptors_.elemSize()*descriptors_.cols*descriptors_.rows;
streamPtr << descriptors_.rows <<
descriptors_.cols <<
descriptors_.type() <<
dataSize;
streamPtr << QByteArray((char*)descriptors_.data, dataSize);
streamPtr << image_;
}
void Object::load(QDataStream & streamPtr)
{
std::vector<cv::KeyPoint> kpts;
cv::Mat descriptors;
int nKpts;
streamPtr >> id_ >> detectorType_ >> descriptorType_ >> nKpts;
for(int i=0;i<nKpts;++i)
{
cv::KeyPoint kpt;
streamPtr >>
kpt.angle >>
kpt.class_id >>
kpt.octave >>
kpt.pt.x >>
kpt.pt.y >>
kpt.response >>
kpt.size;
kpts.push_back(kpt);
}
int rows,cols,type;
qint64 dataSize;
streamPtr >> rows >> cols >> type >> dataSize;
QByteArray data;
streamPtr >> data;
descriptors = cv::Mat(rows, cols, type, data.data()).clone();
streamPtr >> image_;
this->setData(kpts, descriptors, 0);
this->setMinimumSize(image_.size());
}
void Object::paintEvent(QPaintEvent *event)
{
if(graphicsViewMode_)
{
QWidget::paintEvent(event);
}
else
{
if(!image_.isNull())
{
//Scale
float w = image_.width();
float h = image_.height();
float widthRatio = this->rect().width() / w;
float heightRatio = this->rect().height() / h;
float ratio = 1.0f;
//printf("w=%f, h=%f, wR=%f, hR=%f, sW=%f, sH=%f\n", w, h, widthRatio, heightRatio, sceneRect.width(), sceneRect.height());
if(widthRatio < heightRatio)
{
ratio = widthRatio;
}
else
{
ratio = heightRatio;
}
//printf("ratio=%f\n",ratio);
w *= ratio;
h *= ratio;
float offsetX = 0.0f;
float offsetY = 0.0f;
if(w < this->rect().width())
{
offsetX = (this->rect().width() - w)/2.0f;
}
if(h < this->rect().height())
{
offsetY = (this->rect().height() - h)/2.0f;
}
QPainter painter(this);
if(_mirrorView->isChecked())
{
painter.translate(offsetX+w, offsetY);
painter.scale(-ratio, ratio);
}
else
{
painter.translate(offsetX, offsetY);
painter.scale(ratio, ratio);
}
if(_showImage->isChecked())
{
painter.drawPixmap(QPoint(0,0), image_);
}
if(_showFeatures->isChecked())
{
drawKeypoints(&painter);
}
}
}
}
void Object::resizeEvent(QResizeEvent* event)
{
if(graphicsViewMode_)
{
graphicsView_->fitInView(graphicsView_->sceneRect(), Qt::KeepAspectRatio);
}
QWidget::resizeEvent(event);
}
void Object::contextMenuEvent(QContextMenuEvent * event)
{
QAction * action = _menu->exec(event->globalPos());
if(action == _saveImage)
{
QString text;
text = QFileDialog::getSaveFileName(this, tr("Save figure to ..."), _savedFileName, "*.png *.xpm *.jpg *.pdf");
if(!text.isEmpty())
{
if(!text.endsWith(".png") && !text.endsWith(".png") && !text.endsWith(".png") && !text.endsWith(".png"))
{
text.append(".png");//default
}
_savedFileName = text;
getSceneAsPixmap().save(text);
}
}
else if(action == _showFeatures || action == _showImage)
{
if(graphicsViewMode_)
{
this->updateItemsShown();
}
else
{
this->update();
}
}
else if(action == _mirrorView)
{
graphicsView_->setTransform(QTransform().scale(this->isMirrorView()?-1.0:1.0, 1.0));
if(graphicsViewMode_)
{
graphicsView_->fitInView(graphicsView_->sceneRect(), Qt::KeepAspectRatio);
}
else
{
this->update();
}
}
else if(action == _delete)
{
emit removalTriggered(this);
}
else if(action == _plainView)
{
this->setGraphicsViewMode(!_plainView->isChecked());
}
QWidget::contextMenuEvent(event);
}
QPixmap Object::getSceneAsPixmap()
{
if(graphicsViewMode_)
{
QPixmap img(graphicsView_->sceneRect().width(), graphicsView_->sceneRect().height());
QPainter p(&img);
graphicsView_->scene()->render(&p, graphicsView_->sceneRect(), graphicsView_->sceneRect());
return img;
}
else
{
return QPixmap::grabWidget(this);
}
}
void Object::updateItemsShown()
{
QList<QGraphicsItem*> items = graphicsView_->scene()->items();
for(int i=0; i<items.size(); ++i)
{
if(qgraphicsitem_cast<KeypointItem*>(items.at(i)))
{
items.at(i)->setVisible(_showFeatures->isChecked());
}
else if(qgraphicsitem_cast<QGraphicsPixmapItem*>(items.at(i)))
{
items.at(i)->setVisible(_showImage->isChecked());
}
}
}
void Object::drawKeypoints(QPainter * painter)
{
QList<KeypointItem *> items;
KeypointItem * item = 0;
int i = 0;
for(std::vector<cv::KeyPoint>::const_iterator iter = keypoints_.begin(); iter != keypoints_.end(); ++iter, ++i )
{
const cv::KeyPoint & r = *iter;
float radius = 14*1.2/9.*2;//r.size*1.2/9.*2;
if(graphicsViewMode_)
{
QString info = QString( "ID = %1\n"
"Response = %2\n"
"Angle = %3\n"
"X = %4\n"
"Y = %5\n"
"Size = %6").arg(i+1).arg(r.response).arg(r.angle).arg(r.pt.x).arg(r.pt.y).arg(r.size);
// YELLOW = NEW and multiple times
item = new KeypointItem(i+1, r.pt.x-radius, r.pt.y-radius, radius*2, info, kptColors_.at(i));
item->setVisible(this->isFeaturesShown());
item->setZValue(1);
graphicsView_->scene()->addItem(item);
keypointItems_.append(item);
}
if(painter)
{
painter->save();
painter->setPen(kptColors_.at(i));
painter->setBrush(kptColors_.at(i));
painter->drawEllipse(r.pt.x-radius, r.pt.y-radius, radius*2, radius*2);
painter->restore();
}
}
}
QColor Object::defaultColor() const
{
int alpha = 20*255/100;
return QColor(255, 255, 0, alpha);
}
std::vector<cv::KeyPoint> Object::selectedKeypoints() const
{
std::vector<cv::KeyPoint> selected;
if(graphicsViewMode_)
{
QList<QGraphicsItem*> items = graphicsView_->scene()->selectedItems();
for(int i=0; i<items.size(); ++i)
{
if(qgraphicsitem_cast<KeypointItem*>(items.at(i)))
{
selected.push_back(keypoints_.at(((KeypointItem*)items.at(i))->id()-1)); // ids start at 1
}
}
}
return selected;
}
void Object::setupGraphicsView()
{
graphicsView_->scene()->clear();
graphicsView_->scene()->setSceneRect(image_.rect());
QList<KeypointItem*> items;
if(image_.width() > 0 && image_.height() > 0)
{
QRectF sceneRect = graphicsView_->sceneRect();
QGraphicsPixmapItem * pixmapItem = graphicsView_->scene()->addPixmap(image_);
pixmapItem->setVisible(this->isImageShown());
this->drawKeypoints();
graphicsView_->fitInView(sceneRect, Qt::KeepAspectRatio);
}
}

103
src/Object.h Normal file
View File

@ -0,0 +1,103 @@
/*
* VisualObject.h
*
* Created on: 2011-10-21
* Author: matlab
*/
#ifndef OBJECT_H_
#define OBJECT_H_
#include <opencv2/features2d/features2d.hpp>
#include <QtGui/QWidget>
class KeypointItem;
class ImageKptsView;
class QAction;
class QMenu;
class QGraphicsView;
class QGraphicsScene;
class Object : public QWidget
{
Q_OBJECT
public:
Object(QWidget * parent = 0);
Object(int id,
const std::vector<cv::KeyPoint> & keypoints,
const cv::Mat & descriptors,
const IplImage * image,
const QString & detectorType = "NA",
const QString & descriptorType = "NA",
QWidget * parent = 0);
virtual ~Object();
void setId(int id);
void setData(const std::vector<cv::KeyPoint> & keypoints,
const cv::Mat & descriptors,
const IplImage * image);
void resetKptsColor();
void setKptColor(unsigned int index, const QColor & color);
void setGraphicsViewMode(bool on);
void setDeletable(bool deletable);
const std::vector<cv::KeyPoint> & keypoints() const {return keypoints_;}
const cv::Mat & descriptors() const {return descriptors_;}
const QPixmap & image() const {return image_;}
const IplImage * iplImage() const {return iplImage_;}
int id() const {return id_;}
QColor defaultColor() const;
bool isImageShown() const;
bool isFeaturesShown() const;
bool isMirrorView() const;
QGraphicsScene * scene() const;
std::vector<cv::KeyPoint> selectedKeypoints() const;
const QString & detectorType() const {return detectorType_;}
const QString & descriptorType() const {return descriptorType_;}
QPixmap getSceneAsPixmap();
void save(QDataStream & streamPtr) const;
void load(QDataStream & streamPtr);
protected:
virtual void paintEvent(QPaintEvent *event);
virtual void contextMenuEvent(QContextMenuEvent * event);
virtual void resizeEvent(QResizeEvent* event);
signals:
void removalTriggered(Object *);
private:
void setupGraphicsView();
void drawKeypoints(QPainter * painter = 0);
void setupUi();
void updateItemsShown();
private:
std::vector<cv::KeyPoint> keypoints_;
cv::Mat descriptors_;
QPixmap image_;
IplImage * iplImage_;
QList<KeypointItem*> keypointItems_;
QGraphicsView * graphicsView_;
int id_;
bool graphicsViewMode_;
QVector<QColor> kptColors_;
QString detectorType_;
QString descriptorType_;
// menu stuff
QString _savedFileName;
QMenu * _menu;
QAction * _showImage;
QAction * _showFeatures;
QAction * _saveImage;
QAction * _mirrorView;
QAction * _delete;
QAction * _plainView;
};
#endif /* OBJECT_H_ */

256
src/ParametersToolBox.cpp Normal file
View File

@ -0,0 +1,256 @@
/*
* ParametersToolbox.cpp
*
* Created on: 2011-10-22
* Author: matlab
*/
#include "ParametersToolBox.h"
#include "Settings.h"
#include <QtGui/QComboBox>
#include <QtGui/QDoubleSpinBox>
#include <QtGui/QLineEdit>
#include <QtGui/QLabel>
#include <QtGui/QGroupBox>
#include <QtGui/QCheckBox>
#include <QtGui/QVBoxLayout>
#include <stdio.h>
ParametersToolBox::ParametersToolBox(QWidget *parent) :
QToolBox(parent)
{
}
ParametersToolBox::~ParametersToolBox()
{
}
void ParametersToolBox::resetCurrentPage()
{
const QObjectList & children = this->widget(this->currentIndex())->children();
for(int j=0; j<children.size();++j)
{
QString key = children.at(j)->objectName();
QVariant value = Settings::getDefaultParameters().value(key, QVariant());
if(value.isValid())
{
if(qobject_cast<QComboBox*>(children.at(j)))
{
((QComboBox*)children.at(j))->setCurrentIndex(value.toString().split(':').first().toInt());
}
else if(qobject_cast<QSpinBox*>(children.at(j)))
{
((QSpinBox*)children.at(j))->setValue(value.toInt());
}
else if(qobject_cast<QDoubleSpinBox*>(children.at(j)))
{
((QDoubleSpinBox*)children.at(j))->setValue(value.toDouble());
}
else if(qobject_cast<QCheckBox*>(children.at(j)))
{
((QCheckBox*)children.at(j))->setChecked(value.toBool());
}
Settings::setParameter(key, value);
}
}
}
void ParametersToolBox::setupUi()
{
QWidget * currentItem = 0;
const ParametersMap & parameters = Settings::getParameters();
for(ParametersMap::const_iterator iter=parameters.constBegin();
iter!=parameters.constEnd();
++iter)
{
QStringList splitted = iter.key().split('/');
QString group = splitted.first();
QString name = splitted.last();
if(currentItem == 0 || currentItem->objectName().compare(group) != 0)
{
currentItem = new QWidget(this);
int index = this->addItem(currentItem, group);
currentItem->setObjectName(group);
QVBoxLayout * layout = new QVBoxLayout(currentItem);
currentItem->setLayout(layout);
layout->addSpacerItem(new QSpacerItem(0,0, QSizePolicy::Minimum, QSizePolicy::Expanding));
addParameter(layout, iter.key(), iter.value());
}
else
{
addParameter((QVBoxLayout*)currentItem->layout(), iter.key(), iter.value());
}
}
}
void ParametersToolBox::addParameter(QVBoxLayout * layout,
const QString & key,
const QVariant & value)
{
QString type = Settings::getParametersType().value(key);
if(type.compare("QString") == 0)
{
addParameter(layout, key, value.toString());
}
else if(type.compare("int") == 0)
{
addParameter(layout, key, value.toInt());
}
else if(type.compare("unsigned int") == 0)
{
addParameter(layout, key, value.toInt());
}
else if(type.compare("double") == 0)
{
addParameter(layout, key, value.toDouble());
}
else if(type.compare("float") == 0)
{
addParameter(layout, key, value.toDouble());
}
else if(type.compare("bool") == 0)
{
addParameter(layout, key, value.toBool());
}
}
void ParametersToolBox::addParameter(QVBoxLayout * layout,
const QString & key,
const QString & value)
{
if(value.contains(';'))
{
QComboBox * widget = new QComboBox(this);
widget->setObjectName(key);
QStringList splitted = value.split(':');
widget->addItems(splitted.last().split(';'));
widget->setCurrentIndex(splitted.first().toInt());
connect(widget, SIGNAL(currentIndexChanged(int)), this, SLOT(changeParameter(int)));
addParameter(layout, key.split('/').last(), widget);
}
else
{
QLineEdit * widget = new QLineEdit(value, this);
widget->setObjectName(key);
connect(widget, SIGNAL(textChanged(const QString &)), this, SLOT(changeParameter(const QString &)));
addParameter(layout, key.split('/').last(), widget);
}
}
void ParametersToolBox::addParameter(QVBoxLayout * layout,
const QString & key,
const double & value)
{
QDoubleSpinBox * widget = new QDoubleSpinBox(this);
double def = Settings::getDefaultParameters().value(key).toDouble();
if(def<0.001)
{
widget->setDecimals(4);
}
else if(def<0.01)
{
widget->setDecimals(3);
}
if(def>0.0)
{
widget->setMaximum(def*10.0);
}
else if(def<0.0)
{
widget->setMinimum(def*10.0);
widget->setMaximum(0.0);
}
widget->setValue(value);
widget->setObjectName(key);
connect(widget, SIGNAL(editingFinished()), this, SLOT(changeParameter()));
addParameter(layout, key.split('/').last(), widget);
}
void ParametersToolBox::addParameter(QVBoxLayout * layout,
const QString & key,
const int & value)
{
QSpinBox * widget = new QSpinBox(this);
int def = Settings::getDefaultParameters().value(key).toInt();
if(def>0)
{
widget->setMaximum(def*10);
}
else if(def<0)
{
widget->setMinimum(def*10);
widget->setMaximum(0);
}
widget->setValue(value);
widget->setObjectName(key);
connect(widget, SIGNAL(editingFinished()), this, SLOT(changeParameter()));
addParameter(layout, key.split('/').last(), widget);
}
void ParametersToolBox::addParameter(QVBoxLayout * layout,
const QString & key,
const bool & value)
{
QCheckBox * widget = new QCheckBox(this);
widget->setChecked(value);
widget->setObjectName(key);
connect(widget, SIGNAL(stateChanged(int)), this, SLOT(changeParameter(int)));
addParameter(layout, key.split('/').last(), widget);
}
void ParametersToolBox::addParameter(QVBoxLayout * layout, const QString & name, QWidget * widget)
{
QHBoxLayout * hLayout = new QHBoxLayout();
layout->insertLayout(layout->count()-1, hLayout);
hLayout->addWidget(new QLabel(name, this));
hLayout->addWidget(widget);
}
void ParametersToolBox::changeParameter(const QString & value)
{
if(sender())
{
Settings::setParameter(sender()->objectName(), value);
}
}
void ParametersToolBox::changeParameter()
{
if(sender())
{
QDoubleSpinBox * doubleSpinBox = qobject_cast<QDoubleSpinBox*>(sender());
QSpinBox * spinBox = qobject_cast<QSpinBox*>(sender());
if(doubleSpinBox)
{
Settings::setParameter(sender()->objectName(), doubleSpinBox->value());
}
else if(spinBox)
{
Settings::setParameter(sender()->objectName(), spinBox->value());
}
}
}
void ParametersToolBox::changeParameter(const int & value)
{
if(sender())
{
QComboBox * comboBox = qobject_cast<QComboBox*>(sender());
QCheckBox * checkBox = qobject_cast<QCheckBox*>(sender());
if(comboBox)
{
QStringList items;
for(int i=0; i<comboBox->count(); ++i)
{
items.append(comboBox->itemText(i));
}
QString merged = QString::number(value) + QString(":") + items.join(";");
Settings::setParameter(sender()->objectName(), merged);
}
else if(checkBox)
{
Settings::setParameter(sender()->objectName(), value==Qt::Checked?true:false);
}
}
}

42
src/ParametersToolBox.h Normal file
View File

@ -0,0 +1,42 @@
/*
* ParametersToolbox.h
*
* Created on: 2011-10-22
* Author: matlab
*/
#ifndef PARAMETERSTOOLBOX_H_
#define PARAMETERSTOOLBOX_H_
#include <QtGui/QToolBox>
class QVBoxLayout;
class QAbstractButton;
class ParametersToolBox: public QToolBox
{
Q_OBJECT
public:
ParametersToolBox(QWidget *parent = 0);
virtual ~ParametersToolBox();
void setupUi();
private:
void addParameter(QVBoxLayout * layout, const QString & key, const QVariant & value);
void addParameter(QVBoxLayout * layout, const QString & key, const QString & value);
void addParameter(QVBoxLayout * layout, const QString & key, const int & value);
void addParameter(QVBoxLayout * layout, const QString & key, const double & value);
void addParameter(QVBoxLayout * layout, const QString & key, const bool & value);
void addParameter(QVBoxLayout * layout, const QString & name, QWidget * widget);
private slots:
void changeParameter();
void changeParameter(const QString & value);
void changeParameter(const int & value);
void resetCurrentPage();
};
#endif /* PARAMETERSTOOLBOX_H_ */

285
src/Settings.cpp Normal file
View File

@ -0,0 +1,285 @@
/*
* Settings.cpp
*
* Created on: 2011-10-22
* Author: matlab
*/
#include "Settings.h"
#include "Camera.h"
#include <QtCore/QSettings>
#include <QtCore/QStringList>
#include <stdio.h>
ParametersMap Settings::defaultParameters_;
ParametersMap Settings::parameters_;
ParametersType Settings::parametersType_;
Settings Settings::dummyInit_;
const char * Settings::iniDefaultFileName = "./" PROJECT_NAME ".ini";
void Settings::loadSettings(const QString & fileName, QByteArray * windowGeometry)
{
QSettings ini(fileName, QSettings::IniFormat);
for(ParametersMap::const_iterator iter = defaultParameters_.begin(); iter!=defaultParameters_.end(); ++iter)
{
const QString & key = iter.key();
QVariant value = ini.value(key, QVariant());
if(value.isValid())
{
setParameter(key, value);
}
}
if(windowGeometry)
{
QVariant value = ini.value("windowGeometry", QVariant());
if(value.isValid())
{
*windowGeometry = value.toByteArray();
}
}
printf("Settings loaded from %s\n", fileName.toStdString().c_str());
}
void Settings::saveSettings(const QString & fileName, const QByteArray & windowGeometry)
{
QSettings ini(fileName, QSettings::IniFormat);
for(ParametersMap::const_iterator iter = parameters_.begin(); iter!=parameters_.end(); ++iter)
{
QString type = Settings::getParametersType().value(iter.key());
if(type.compare("float") == 0)
{
ini.setValue(iter.key(), QString::number(iter.value().toFloat(),'g',6));
}
else
{
ini.setValue(iter.key(), iter.value());
}
}
if(!windowGeometry.isEmpty())
{
ini.setValue("windowGeometry", windowGeometry);
}
printf("Settings saved to %s\n", fileName.toStdString().c_str());
}
cv::FeatureDetector * Settings::createFeaturesDetector()
{
cv::FeatureDetector * detector = 0;
QString str = getDetector_Type().toString();
QStringList split = str.split(':');
if(split.size()==2)
{
bool ok = false;
int index = split.first().toInt(&ok);
if(ok)
{
QStringList strategies = split.last().split(';');
if(strategies.size() == 8 && index>=0 && index<8)
{
switch(index)
{
case 0:
if(strategies.at(index).compare("Dense") == 0)
{
cv::DenseFeatureDetector::Params params;
params.initFeatureScale = getDense_initFeatureScale().toFloat();
params.featureScaleLevels = getDense_featureScaleLevels().toInt();
params.featureScaleMul = getDense_featureScaleMul().toFloat();
params.initXyStep = getDense_initXyStep().toInt();
params.initImgBound = getDense_initImgBound().toInt();
params.varyXyStepWithScale = getDense_varyXyStepWithScale().toBool();
params.varyImgBoundWithScale = getDense_varyImgBoundWithScale().toBool();
detector = new cv::DenseFeatureDetector(params);
}
break;
case 1:
if(strategies.at(index).compare("Fast") == 0)
{
detector = new cv::FastFeatureDetector(
getFast_threshold().toInt(),
getFast_nonmaxSuppression().toBool());
}
break;
case 2:
if(strategies.at(index).compare("GoodFeaturesToTrack") == 0)
{
cv::GoodFeaturesToTrackDetector::Params params;
params.maxCorners = getGoodFeaturesToTrack_maxCorners().toInt();
params.qualityLevel = getGoodFeaturesToTrack_qualityLevel().toDouble();
params.minDistance = getGoodFeaturesToTrack_minDistance().toDouble();
params.blockSize = getGoodFeaturesToTrack_blockSize().toInt();
params.useHarrisDetector = getGoodFeaturesToTrack_useHarrisDetector().toBool();
params.k = getGoodFeaturesToTrack_k().toDouble();
detector = new cv::GoodFeaturesToTrackDetector(params);
}
break;
case 3:
if(strategies.at(index).compare("Mser") == 0)
{
CvMSERParams params = cvMSERParams();
params.delta = getMser_delta().toInt();
params.maxArea = getMser_maxArea().toInt();
params.minArea = getMser_minArea().toInt();
params.maxVariation = getMser_maxVariation().toFloat();
params.minDiversity = getMser_minDiversity().toFloat();
params.maxEvolution = getMser_maxEvolution().toInt();
params.areaThreshold = getMser_areaThreshold().toDouble();
params.minMargin = getMser_minMargin().toDouble();
params.edgeBlurSize = getMser_edgeBlurSize().toInt();
detector = new cv::MserFeatureDetector(params);
}
break;
case 4:
if(strategies.at(index).compare("Orb") == 0)
{
cv::ORB::CommonParams params;
params.scale_factor_ = getOrb_scaleFactor().toFloat();
params.n_levels_ = getOrb_nLevels().toUInt();
params.first_level_ = getOrb_firstLevel().toUInt();
params.edge_threshold_ = getOrb_edgeThreshold().toInt();
detector = new cv::OrbFeatureDetector(
getOrb_nFeatures().toUInt(),
params);
}
break;
case 5:
if(strategies.at(index).compare("Sift") == 0)
{
cv::SIFT::DetectorParams detectorParams;
detectorParams.edgeThreshold = getSift_edgeThreshold().toDouble();
detectorParams.threshold = getSift_threshold().toDouble();
cv::SIFT::CommonParams commonParams;
commonParams.angleMode = getSift_angleMode().toInt();
commonParams.firstOctave = getSift_firstOctave().toInt();
commonParams.nOctaveLayers = getSift_nOctaveLayers().toInt();
commonParams.nOctaves = getSift_nOctaves().toInt();
detector = new cv::SiftFeatureDetector(
detectorParams,
commonParams);
}
break;
case 6:
if(strategies.at(index).compare("Star") == 0)
{
CvStarDetectorParams params = cvStarDetectorParams();
params.lineThresholdBinarized = getStar_lineThresholdBinarized().toInt();
params.lineThresholdProjected = getStar_lineThresholdProjected().toInt();
params.maxSize = getStar_maxSize().toInt();
params.responseThreshold = getStar_responseThreshold().toInt();
params.suppressNonmaxSize = getStar_suppressNonmaxSize().toInt();
detector = new cv::StarFeatureDetector(params);
}
break;
case 7:
if(strategies.at(index).compare("Surf") == 0)
{
detector = new cv::SurfFeatureDetector(
getSurf_hessianThreshold().toDouble(),
getSurf_octaves().toInt(),
getSurf_octaveLayers().toInt(),
getSurf_upright().toBool());
}
break;
default:
break;
}
}
}
}
return detector;
}
cv::DescriptorExtractor * Settings::createDescriptorsExtractor()
{
cv::DescriptorExtractor * extractor = 0;
QString str = getDescriptor_Type().toString();
QStringList split = str.split(':');
if(split.size()==2)
{
bool ok = false;
int index = split.first().toInt(&ok);
if(ok)
{
QStringList strategies = split.last().split(';');
if(strategies.size() == 4 && index>=0 && index<4)
{
switch(index)
{
case 0:
if(strategies.at(index).compare("Brief") == 0)
{
extractor = new cv::BriefDescriptorExtractor(
getBrief_bytes().toInt());
}
break;
case 1:
if(strategies.at(index).compare("Orb") == 0)
{
cv::ORB::CommonParams params;
params.scale_factor_ = getOrb_scaleFactor().toFloat();
params.n_levels_ = getOrb_nLevels().toUInt();
params.first_level_ = getOrb_firstLevel().toUInt();
params.edge_threshold_ = getOrb_edgeThreshold().toInt();
extractor = new cv::OrbDescriptorExtractor(params);
}
break;
case 2:
if(strategies.at(index).compare("Sift") == 0)
{
cv::SIFT::DescriptorParams descriptorParams;
descriptorParams.isNormalize = getSift_isNormalize().toBool();
descriptorParams.magnification = getSift_magnification().toDouble();
descriptorParams.recalculateAngles = getSift_recalculateAngles().toBool();
cv::SIFT::CommonParams commonParams;
commonParams.angleMode = getSift_angleMode().toInt();
commonParams.firstOctave = getSift_firstOctave().toInt();
commonParams.nOctaveLayers = getSift_nOctaveLayers().toInt();
commonParams.nOctaves = getSift_nOctaves().toInt();
extractor = new cv::SiftDescriptorExtractor(
descriptorParams,
commonParams);
}
break;
case 3:
if(strategies.at(index).compare("Surf") == 0)
{
extractor = new cv::SurfDescriptorExtractor(
getSurf_octaves().toInt(),
getSurf_octaveLayers().toInt(),
getSurf_extended().toBool(),
getSurf_upright().toBool());
}
break;
default:
break;
}
}
}
}
return extractor;
}
Camera * Settings::createCamera()
{
return new Camera(
getCamera_deviceId().toInt(),
getCamera_imageWidth().toInt(),
getCamera_imageHeight().toInt());
}
QString Settings::currentDetectorType()
{
int index = Settings::getDetector_Type().toString().split(':').first().toInt();
return getDetector_Type().toString().split(':').last().split(';').at(index);
}
QString Settings::currentDescriptorType()
{
int index = Settings::getDescriptor_Type().toString().split(':').first().toInt();
return getDescriptor_Type().toString().split(':').last().split(';').at(index);
}

150
src/Settings.h Normal file
View File

@ -0,0 +1,150 @@
/*
* Settings.h
*
* Created on: 2011-10-22
* Author: matlab
*/
#ifndef SETTINGS_H_
#define SETTINGS_H_
#include <QtCore/QMap>
#include <QtCore/QVariant>
#include <QtCore/QByteArray>
#include <opencv2/features2d/features2d.hpp>
class Camera;
typedef QMap<QString, QVariant> ParametersMap; // Key, value
typedef QMap<QString, QString> ParametersType; // Key, type
// MACRO BEGIN
#define PARAMETER(PREFIX, NAME, TYPE, DEFAULT_VALUE) \
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 QVariant get##PREFIX##_##NAME() {return parameters_.value(#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);} \
}; \
Dummy##PREFIX##_##NAME dummy##PREFIX##_##NAME;
// MACRO END
class Settings
{
PARAMETER(Camera, deviceId, int, 0);
PARAMETER(Camera, imageWidth, int, 640);
PARAMETER(Camera, imageHeight, int, 480);
PARAMETER(Camera, imageRate, int, 5); // Hz
//List format : [Index:item0;item1;item3;...]
PARAMETER(Detector, Type, QString, "1:Dense;Fast;GoodFeaturesToTrack;Mser;Orb;Sift;Star;Surf");
PARAMETER(Descriptor, Type, QString, "0:Brief;Orb;Sift;Surf");
PARAMETER(Brief, bytes, int, 32);
PARAMETER(Dense, initFeatureScale, float, cv::DenseFeatureDetector::Params().initFeatureScale);
PARAMETER(Dense, featureScaleLevels, int, cv::DenseFeatureDetector::Params().featureScaleLevels);
PARAMETER(Dense, featureScaleMul, float, cv::DenseFeatureDetector::Params().featureScaleMul);
PARAMETER(Dense, initXyStep, int, cv::DenseFeatureDetector::Params().initXyStep);
PARAMETER(Dense, initImgBound, int, cv::DenseFeatureDetector::Params().initImgBound);
PARAMETER(Dense, varyXyStepWithScale, bool, cv::DenseFeatureDetector::Params().varyXyStepWithScale);
PARAMETER(Dense, varyImgBoundWithScale, bool, cv::DenseFeatureDetector::Params().varyImgBoundWithScale);
PARAMETER(Fast, threshold, int, 20);
PARAMETER(Fast, nonmaxSuppression, bool, true);
PARAMETER(GoodFeaturesToTrack, maxCorners, int, cv::GoodFeaturesToTrackDetector::Params().maxCorners);
PARAMETER(GoodFeaturesToTrack, qualityLevel, double, cv::GoodFeaturesToTrackDetector::Params().qualityLevel);
PARAMETER(GoodFeaturesToTrack, minDistance, double, cv::GoodFeaturesToTrackDetector::Params().minDistance);
PARAMETER(GoodFeaturesToTrack, blockSize, int, cv::GoodFeaturesToTrackDetector::Params().blockSize);
PARAMETER(GoodFeaturesToTrack, useHarrisDetector, bool, cv::GoodFeaturesToTrackDetector::Params().useHarrisDetector);
PARAMETER(GoodFeaturesToTrack, k, double, cv::GoodFeaturesToTrackDetector::Params().k);
PARAMETER(Orb, nFeatures, unsigned int, 700);
PARAMETER(Orb, scaleFactor, float, cv::ORB::CommonParams().scale_factor_);
PARAMETER(Orb, nLevels, unsigned int, cv::ORB::CommonParams().n_levels_);
PARAMETER(Orb, firstLevel, unsigned int, cv::ORB::CommonParams().first_level_);
PARAMETER(Orb, edgeThreshold, int, cv::ORB::CommonParams().edge_threshold_);
PARAMETER(Mser, delta, int, cvMSERParams().delta);
PARAMETER(Mser, minArea, int, cvMSERParams().minArea);
PARAMETER(Mser, maxArea, int, cvMSERParams().maxArea);
PARAMETER(Mser, maxVariation, float, cvMSERParams().maxVariation);
PARAMETER(Mser, minDiversity, float, cvMSERParams().minDiversity);
PARAMETER(Mser, maxEvolution, int, cvMSERParams().maxEvolution);
PARAMETER(Mser, areaThreshold, double, cvMSERParams().areaThreshold);
PARAMETER(Mser, minMargin, double, cvMSERParams().minMargin);
PARAMETER(Mser, edgeBlurSize, int, cvMSERParams().edgeBlurSize);
PARAMETER(Sift, threshold, double, cv::SIFT::DetectorParams::GET_DEFAULT_THRESHOLD());
PARAMETER(Sift, edgeThreshold, double, cv::SIFT::DetectorParams::GET_DEFAULT_EDGE_THRESHOLD());
PARAMETER(Sift, nOctaves, int, cv::SIFT::CommonParams::DEFAULT_NOCTAVES);
PARAMETER(Sift, nOctaveLayers, int, cv::SIFT::CommonParams::DEFAULT_NOCTAVE_LAYERS);
PARAMETER(Sift, firstOctave, int, cv::SIFT::CommonParams::DEFAULT_FIRST_OCTAVE);
PARAMETER(Sift, angleMode, int, cv::SIFT::CommonParams::FIRST_ANGLE);
PARAMETER(Sift, magnification, double, cv::SIFT::DescriptorParams::GET_DEFAULT_MAGNIFICATION());
PARAMETER(Sift, isNormalize, bool, cv::SIFT::DescriptorParams::DEFAULT_IS_NORMALIZE);
PARAMETER(Sift, recalculateAngles, bool, true);
PARAMETER(Star, maxSize, int, cvStarDetectorParams().maxSize);
PARAMETER(Star, responseThreshold, int, cvStarDetectorParams().responseThreshold);
PARAMETER(Star, lineThresholdProjected, int, cvStarDetectorParams().lineThresholdProjected);
PARAMETER(Star, lineThresholdBinarized, int, cvStarDetectorParams().lineThresholdBinarized);
PARAMETER(Star, suppressNonmaxSize, int, cvStarDetectorParams().suppressNonmaxSize);
PARAMETER(Surf, hessianThreshold, double, 400.0);
PARAMETER(Surf, octaves, int, 3);
PARAMETER(Surf, octaveLayers, int, 4);
PARAMETER(Surf, upright, bool, false);
PARAMETER(Surf, extended, bool, false);
PARAMETER(NN, nndrRatio, float, 0.8f); // NNDR RATIO
PARAMETER(General, nextObjID, unsigned int, 1);
PARAMETER(Homography, ransacReprojThr, double, 1.0);
PARAMETER(Homography, minimumInliers, int, 10);
public:
virtual ~Settings(){}
static const char * iniDefaultFileName; // "./" PROJECT_NAME ".ini"
static void loadSettings(const QString & fileName = iniDefaultFileName, QByteArray * windowGeometry = 0);
static void saveSettings(const QString & fileName = iniDefaultFileName, const QByteArray & windowGeometry = QByteArray());
static const ParametersMap & getDefaultParameters() {return defaultParameters_;}
static const ParametersMap & getParameters() {return parameters_;}
static const ParametersType & getParametersType() {return parametersType_;}
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 cv::FeatureDetector * createFeaturesDetector();
static cv::DescriptorExtractor * createDescriptorsExtractor();
static QString currentDescriptorType();
static QString currentDetectorType();
static Camera * createCamera();
private:
Settings(){}
private:
static ParametersMap defaultParameters_;
static ParametersMap parameters_;
static ParametersType parametersType_;
static Settings dummyInit_;
};
#endif /* SETTINGS_H_ */

18
src/main.cpp Normal file
View File

@ -0,0 +1,18 @@
#include <QtGui/QApplication>
#include "MainWindow.h"
int main(int argc, char* argv[])
{
/* Create tasks */
QApplication app(argc, argv);
MainWindow mainWindow;
mainWindow.showNormal();
// Now wait for application to finish
app.connect( &app, SIGNAL( lastWindowClosed() ),
&app, SLOT( quit() ) );
app.exec();// MUST be called by the Main Thread
return 0;
}

30
src/qtipl.cpp Normal file
View File

@ -0,0 +1,30 @@
#include "qtipl.h"
#include <opencv2/core/core_c.h>
// TODO : support only from gray 8bits ?
QImage Ipl2QImage(const IplImage *newImage)
{
QImage qtemp;
if (newImage && newImage->depth == IPL_DEPTH_8U && cvGetSize(newImage).width>0)
{
int x;
int y;
char* data = newImage->imageData;
qtemp= QImage(newImage->width, newImage->height,QImage::Format_RGB32 );
for( y = 0; y < newImage->height; y++, data +=newImage->widthStep )
{
for( x = 0; x < newImage->width; x++)
{
uint *p = (uint*)qtemp.scanLine (y) + x;
*p = qRgb(data[x * newImage->nChannels+2], data[x * newImage->nChannels+1],data[x * newImage->nChannels]);
}
}
}
else
{
//Wrong IplImage format
}
return qtemp;
}

9
src/qtipl.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef QTIPL_H
#define QTIPL_H
#include <QtGui/QImage>
#include <opencv2/core/core.hpp>
QImage Ipl2QImage(const IplImage *newImage);
#endif

91
src/ui/addObjectDialog.ui Normal file
View File

@ -0,0 +1,91 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>addObjectDialog</class>
<widget class="QDialog" name="addObjectDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>527</width>
<height>420</height>
</rect>
</property>
<property name="windowTitle">
<string>Add object</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,1,0">
<item>
<widget class="QLabel" name="label_instruction">
<property name="text">
<string>(Instructions)</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="Object" name="cameraView" native="true"/>
</item>
<item>
<widget class="Object" name="objectView" native="true"/>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="pushButton_cancel">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="pushButton_back">
<property name="text">
<string>Back</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_takePicture">
<property name="text">
<string>Take picture</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_next">
<property name="text">
<string>End</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>Object</class>
<extends>QWidget</extends>
<header>Object.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

450
src/ui/mainWindow.ui Normal file
View File

@ -0,0 +1,450 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>mainWindow</class>
<widget class="QMainWindow" name="mainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>864</width>
<height>533</height>
</rect>
</property>
<property name="windowTitle">
<string>Find object</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QHBoxLayout" name="horizontalLayout" stretch="2">
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<number>0</number>
</property>
<item>
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,1">
<property name="spacing">
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch="0,0,0,0,0,0,0">
<item>
<widget class="QLabel" name="label_5">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Camera</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_timeRefreshRate">
<property name="text">
<string> (0 Hz - 0 Hz)</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_detectorDescriptorType">
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_nfeatures">
<property name="text">
<string>0</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_15">
<property name="text">
<string> features</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="Object" name="imageView_source" native="true"/>
</item>
</layout>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>864</width>
<height>25</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
<property name="title">
<string>File</string>
</property>
<addaction name="actionLoad_objects"/>
<addaction name="actionSave_objects"/>
<addaction name="separator"/>
<addaction name="actionExit"/>
</widget>
<widget class="QMenu" name="menuEdit">
<property name="title">
<string>Edit</string>
</property>
<addaction name="actionAdd_object"/>
<addaction name="actionStart_camera"/>
<addaction name="actionStop_camera"/>
</widget>
<widget class="QMenu" name="menuView">
<property name="title">
<string>View</string>
</property>
</widget>
<addaction name="menuFile"/>
<addaction name="menuEdit"/>
<addaction name="menuView"/>
</widget>
<widget class="QDockWidget" name="dockWidget_parameters">
<property name="minimumSize">
<size>
<width>300</width>
<height>180</height>
</size>
</property>
<property name="floating">
<bool>false</bool>
</property>
<property name="windowTitle">
<string>Parameters</string>
</property>
<attribute name="dockWidgetArea">
<number>2</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents">
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="ParametersToolBox" name="toolBox">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="page_1">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>282</width>
<height>401</height>
</rect>
</property>
<attribute name="label">
<string>Timings</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<layout class="QGridLayout" name="gridLayout" columnstretch="0,0,0">
<property name="horizontalSpacing">
<number>6</number>
</property>
<property name="verticalSpacing">
<number>0</number>
</property>
<property name="margin">
<number>0</number>
</property>
<item row="0" column="2">
<widget class="QLabel" name="label_3">
<property name="text">
<string>ms</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_timeExtraction">
<property name="text">
<string>000</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLabel" name="label_4">
<property name="text">
<string>ms</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Descriptors extraction</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Features detection</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_timeDetection">
<property name="text">
<string>000</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Descriptors matching</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Descriptors indexing</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="label_timeIndexing">
<property name="text">
<string>000</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="label_timeMatching">
<property name="text">
<string>000</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLabel" name="label_9">
<property name="text">
<string>ms</string>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QLabel" name="label_10">
<property name="text">
<string>ms</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_11">
<property name="text">
<string>Detect outliers and GUI</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLabel" name="label_timeGui">
<property name="text">
<string>000</string>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QLabel" name="label_12">
<property name="text">
<string>ms</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>174</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_restoreDefaults">
<property name="text">
<string>Restore defaults</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="QDockWidget" name="dockWidget_objects">
<property name="minimumSize">
<size>
<width>300</width>
<height>121</height>
</size>
</property>
<property name="windowTitle">
<string>Objects</string>
</property>
<attribute name="dockWidgetArea">
<number>1</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents_2">
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<widget class="QScrollArea" name="objects_area">
<property name="minimumSize">
<size>
<width>150</width>
<height>0</height>
</size>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>280</width>
<height>463</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_objects">
<property name="margin">
<number>0</number>
</property>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>230</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
</widget>
<action name="actionExit">
<property name="text">
<string>Exit</string>
</property>
</action>
<action name="actionAdd_object">
<property name="text">
<string>Add object...</string>
</property>
</action>
<action name="actionStart_camera">
<property name="text">
<string>Start camera</string>
</property>
</action>
<action name="actionStop_camera">
<property name="text">
<string>Stop camera</string>
</property>
</action>
<action name="actionSave_objects">
<property name="text">
<string>Save objects...</string>
</property>
</action>
<action name="actionLoad_objects">
<property name="text">
<string>Load objects...</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>
<class>Object</class>
<extends>QWidget</extends>
<header>Object.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>ParametersToolBox</class>
<extends>QToolBox</extends>
<header>ParametersToolBox.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>