Added some new features ("update objects" button and region selection) described in issue 2.

git-svn-id: http://find-object.googlecode.com/svn/trunk/find_object@74 620bd6b2-0a58-f614-fd9a-1bd335dccda9
This commit is contained in:
matlabbe 2012-01-28 01:00:23 +00:00
parent a1c6ec7509
commit 27652b4f8f
11 changed files with 364 additions and 99 deletions

View File

@ -118,8 +118,8 @@ int main(int argc, char * argv[])
// PROCESS NEAREST NEIGHBOR RESULTS // PROCESS NEAREST NEIGHBOR RESULTS
//////////////////////////// ////////////////////////////
// Set gui data // Set gui data
objWidget.setData(objectKeypoints, objectDescriptors, objectImg); objWidget.setData(objectKeypoints, objectDescriptors, objectImg, "SURF", "SURF");
sceneWidget.setData(sceneKeypoints, sceneDescriptors, sceneImg); sceneWidget.setData(sceneKeypoints, sceneDescriptors, sceneImg, "SURF", "SURF");
// Find correspondences by NNDR (Nearest Neighbor Distance Ratio) // Find correspondences by NNDR (Nearest Neighbor Distance Ratio)
float nndrRatio = 0.6; float nndrRatio = 0.6;

View File

@ -19,7 +19,7 @@
#include <opencv2/imgproc/imgproc_c.h> #include <opencv2/imgproc/imgproc_c.h>
#include <opencv2/highgui/highgui_c.h> #include <opencv2/highgui/highgui_c.h>
AddObjectDialog::AddObjectDialog(Camera * camera, QList<ObjWidget*> * objects, QWidget * parent, Qt::WindowFlags f) : AddObjectDialog::AddObjectDialog(Camera * camera, QList<ObjWidget*> * objects, bool mirrorView, QWidget * parent, Qt::WindowFlags f) :
QDialog(parent, f), QDialog(parent, f),
camera_(camera), camera_(camera),
objects_(objects), objects_(objects),
@ -32,8 +32,11 @@ AddObjectDialog::AddObjectDialog(Camera * camera, QList<ObjWidget*> * objects, Q
connect(ui_->pushButton_back, SIGNAL(clicked()), this, SLOT(back())); connect(ui_->pushButton_back, SIGNAL(clicked()), this, SLOT(back()));
connect(ui_->pushButton_next, SIGNAL(clicked()), this, SLOT(next())); connect(ui_->pushButton_next, SIGNAL(clicked()), this, SLOT(next()));
connect(ui_->pushButton_takePicture, SIGNAL(clicked()), this, SLOT(takePicture())); connect(ui_->pushButton_takePicture, SIGNAL(clicked()), this, SLOT(takePicture()));
connect(ui_->comboBox_selection, SIGNAL(currentIndexChanged(int)), this, SLOT(changeSelectionMode()));
connect(ui_->cameraView, SIGNAL(selectionChanged()), this, SLOT(updateNextButton())); connect(ui_->cameraView, SIGNAL(selectionChanged()), this, SLOT(updateNextButton()));
connect(ui_->cameraView, SIGNAL(roiChanged(const QRect &)), this, SLOT(updateNextButton(const QRect &)));
ui_->cameraView->setMirrorView(mirrorView);
this->setState(kTakePicture); this->setState(kTakePicture);
} }
@ -72,7 +75,15 @@ void AddObjectDialog::takePicture()
void AddObjectDialog::updateNextButton() void AddObjectDialog::updateNextButton()
{ {
updateNextButton(QRect());
}
void AddObjectDialog::updateNextButton(const QRect & rect)
{
roi_ = rect;
if(state_ == kSelectFeatures) if(state_ == kSelectFeatures)
{
if(ui_->comboBox_selection->currentIndex() == 1)
{ {
if(ui_->cameraView->selectedItems().size() > 0) if(ui_->cameraView->selectedItems().size() > 0)
{ {
@ -83,6 +94,23 @@ void AddObjectDialog::updateNextButton()
ui_->pushButton_next->setEnabled(false); ui_->pushButton_next->setEnabled(false);
} }
} }
else
{
if(roi_.isNull())
{
ui_->pushButton_next->setEnabled(false);
}
else
{
ui_->pushButton_next->setEnabled(true);
}
}
}
}
void AddObjectDialog::changeSelectionMode()
{
this->setState(kSelectFeatures);
} }
void AddObjectDialog::setState(int state) void AddObjectDialog::setState(int state)
@ -97,8 +125,10 @@ void AddObjectDialog::setState(int state)
ui_->label_instruction->setText(tr("Place the object in front of the camera and click \"Take picture\".")); ui_->label_instruction->setText(tr("Place the object in front of the camera and click \"Take picture\"."));
ui_->pushButton_next->setText(tr("Next")); ui_->pushButton_next->setText(tr("Next"));
ui_->cameraView->setVisible(true); ui_->cameraView->setVisible(true);
ui_->cameraView->clearRoiSelection();
ui_->objectView->setVisible(false); ui_->objectView->setVisible(false);
ui_->cameraView->setGraphicsViewMode(false); ui_->cameraView->setGraphicsViewMode(false);
ui_->comboBox_selection->setVisible(false);
if(!camera_ || !camera_->start()) if(!camera_ || !camera_->start())
{ {
QMessageBox::critical(this, tr("Camera error"), tr("Camera is not started!")); QMessageBox::critical(this, tr("Camera error"), tr("Camera is not started!"));
@ -118,12 +148,23 @@ void AddObjectDialog::setState(int state)
ui_->pushButton_back->setEnabled(true); ui_->pushButton_back->setEnabled(true);
ui_->pushButton_next->setEnabled(false); ui_->pushButton_next->setEnabled(false);
ui_->pushButton_takePicture->setEnabled(false); ui_->pushButton_takePicture->setEnabled(false);
ui_->label_instruction->setText(tr("Select features representing the object."));
ui_->pushButton_next->setText(tr("Next")); ui_->pushButton_next->setText(tr("Next"));
ui_->cameraView->setVisible(true); ui_->cameraView->setVisible(true);
ui_->cameraView->clearRoiSelection();
ui_->objectView->setVisible(false); ui_->objectView->setVisible(false);
ui_->comboBox_selection->setVisible(true);
if(ui_->comboBox_selection->currentIndex() == 1)
{
ui_->label_instruction->setText(tr("Select features representing the object."));
ui_->cameraView->setGraphicsViewMode(true); ui_->cameraView->setGraphicsViewMode(true);
updateNextButton(); }
else
{
ui_->label_instruction->setText(tr("Select region representing the object."));
ui_->cameraView->setGraphicsViewMode(false);
}
updateNextButton(QRect());
} }
else if(state == kVerifySelection) else if(state == kVerifySelection)
{ {
@ -136,15 +177,41 @@ void AddObjectDialog::setState(int state)
ui_->pushButton_next->setText(tr("End")); ui_->pushButton_next->setText(tr("End"));
ui_->cameraView->setVisible(true); ui_->cameraView->setVisible(true);
ui_->objectView->setVisible(true); ui_->objectView->setVisible(true);
ui_->objectView->setMirrorView(ui_->cameraView->isMirrorView());
ui_->objectView->setSizedFeatures(ui_->cameraView->isSizedFeatures());
ui_->comboBox_selection->setVisible(false);
if(ui_->comboBox_selection->currentIndex() == 1)
{
ui_->cameraView->setGraphicsViewMode(true); ui_->cameraView->setGraphicsViewMode(true);
}
else
{
ui_->cameraView->setGraphicsViewMode(false);
}
std::vector<cv::KeyPoint> selectedKeypoints = ui_->cameraView->selectedKeypoints(); std::vector<cv::KeyPoint> selectedKeypoints = ui_->cameraView->selectedKeypoints();
// Select keypoints // Select keypoints
if(selectedKeypoints.size() && cvImage_) if(cvImage_ &&
((ui_->comboBox_selection->currentIndex() == 1 && selectedKeypoints.size()) ||
(ui_->comboBox_selection->currentIndex() == 0 && !roi_.isNull())))
{ {
CvRect roi = computeROI(selectedKeypoints); CvRect roi;
if(ui_->comboBox_selection->currentIndex() == 1)
{
roi = computeROI(selectedKeypoints);
}
else
{
roi.x = roi_.x();
roi.y = roi_.y();
roi.width = roi_.width();
roi.height = roi_.height();
}
cvSetImageROI(cvImage_, roi); cvSetImageROI(cvImage_, roi);
if(ui_->comboBox_selection->currentIndex() == 1)
{
if(roi.x != 0 || roi.y != 0) if(roi.x != 0 || roi.y != 0)
{ {
for(unsigned int i=0; i<selectedKeypoints.size(); ++i) for(unsigned int i=0; i<selectedKeypoints.size(); ++i)
@ -153,7 +220,16 @@ void AddObjectDialog::setState(int state)
selectedKeypoints.at(i).pt.y -= roi.y; selectedKeypoints.at(i).pt.y -= roi.y;
} }
} }
ui_->objectView->setData(selectedKeypoints, cv::Mat(), cvImage_); }
else
{
// Extract keypoints
selectedKeypoints.clear();
cv::FeatureDetector * detector = Settings::createFeaturesDetector();
detector->detect(cvImage_, selectedKeypoints);
delete detector;
}
ui_->objectView->setData(selectedKeypoints, cv::Mat(), cvImage_, Settings::currentDetectorType(), "");
ui_->objectView->setMinimumSize(roi.width, roi.height); ui_->objectView->setMinimumSize(roi.width, roi.height);
ui_->objectView->update(); ui_->objectView->update();
cvResetImageROI(cvImage_); cvResetImageROI(cvImage_);
@ -168,33 +244,25 @@ void AddObjectDialog::setState(int state)
} }
else if(state == kClosing) else if(state == kClosing)
{ {
std::vector<cv::KeyPoint> selectedKeypoints = ui_->cameraView->selectedKeypoints(); std::vector<cv::KeyPoint> keypoints = ui_->objectView->keypoints();
if(selectedKeypoints.size()) if((ui_->comboBox_selection->currentIndex() == 1 && keypoints.size()) ||
(ui_->comboBox_selection->currentIndex() == 0 && !roi_.isNull()))
{
cv::Mat descriptors;
if(keypoints.size())
{ {
// Extract descriptors // Extract descriptors
cv::Mat descriptors;
cv::DescriptorExtractor * extractor = Settings::createDescriptorsExtractor(); cv::DescriptorExtractor * extractor = Settings::createDescriptorsExtractor();
extractor->compute(cvImage_, selectedKeypoints, descriptors); extractor->compute(ui_->objectView->iplImage(), keypoints, descriptors);
delete extractor; delete extractor;
if(selectedKeypoints.size() != (unsigned int)descriptors.rows)
{
printf("ERROR : keypoints=%d != descriptors=%d\n", (int)selectedKeypoints.size(), descriptors.rows);
}
CvRect roi = computeROI(selectedKeypoints); if(keypoints.size() != (unsigned int)descriptors.rows)
cvSetImageROI(cvImage_, roi);
if(roi.x != 0 || roi.y != 0)
{ {
for(unsigned int i=0; i<selectedKeypoints.size(); ++i) printf("ERROR : keypoints=%d != descriptors=%d\n", (int)keypoints.size(), descriptors.rows);
{
selectedKeypoints.at(i).pt.x -= roi.x;
selectedKeypoints.at(i).pt.y -= roi.y;
} }
} }
objects_->append(new ObjWidget(0, selectedKeypoints, descriptors, cvImage_, Settings::currentDetectorType(), Settings::currentDescriptorType()));
cvResetImageROI(cvImage_);
objects_->append(new ObjWidget(0, keypoints, descriptors, ui_->objectView->iplImage(), Settings::currentDetectorType(), Settings::currentDescriptorType()));
this->accept(); this->accept();
} }
@ -227,7 +295,7 @@ void AddObjectDialog::update(const cv::Mat & image)
detector->detect(cvImage_, keypoints); detector->detect(cvImage_, keypoints);
delete detector; delete detector;
ui_->cameraView->setData(keypoints, cv::Mat(), cvImage_); ui_->cameraView->setData(keypoints, cv::Mat(), cvImage_, Settings::currentDetectorType(), "");
ui_->cameraView->update(); ui_->cameraView->update();
} }
} }

View File

@ -20,7 +20,7 @@ class AddObjectDialog : public QDialog {
Q_OBJECT Q_OBJECT
public: public:
AddObjectDialog(Camera * camera, QList<ObjWidget*> * objects, QWidget * parent = 0, Qt::WindowFlags f = 0); AddObjectDialog(Camera * camera, QList<ObjWidget*> * objects, bool mirrorView, QWidget * parent = 0, Qt::WindowFlags f = 0);
virtual ~AddObjectDialog(); virtual ~AddObjectDialog();
private slots: private slots:
@ -30,6 +30,8 @@ private slots:
void cancel(); void cancel();
void takePicture(); void takePicture();
void updateNextButton(); void updateNextButton();
void updateNextButton(const QRect &);
void changeSelectionMode();
protected: protected:
virtual void closeEvent(QCloseEvent* event); virtual void closeEvent(QCloseEvent* event);
@ -45,6 +47,7 @@ private:
enum State{kTakePicture, kSelectFeatures, kVerifySelection, kClosing}; enum State{kTakePicture, kSelectFeatures, kVerifySelection, kClosing};
int state_; int state_;
QRect roi_;
}; };
#endif /* ADDOBJECTDIALOG_H_ */ #endif /* ADDOBJECTDIALOG_H_ */

View File

@ -61,11 +61,14 @@ MainWindow::MainWindow(Camera * camera, QWidget * parent) :
ui_->dockWidget_parameters->hide(); ui_->dockWidget_parameters->hide();
ui_->menuView->addAction(ui_->dockWidget_parameters->toggleViewAction()); ui_->menuView->addAction(ui_->dockWidget_parameters->toggleViewAction());
ui_->menuView->addAction(ui_->dockWidget_objects->toggleViewAction()); ui_->menuView->addAction(ui_->dockWidget_objects->toggleViewAction());
connect(ui_->toolBox, SIGNAL(parametersChanged()), this, SLOT(notifyParametersChanged()));
ui_->imageView_source->setGraphicsViewMode(false); ui_->imageView_source->setGraphicsViewMode(false);
//reset button //reset button
connect(ui_->pushButton_restoreDefaults, SIGNAL(clicked()), ui_->toolBox, SLOT(resetCurrentPage())); connect(ui_->pushButton_restoreDefaults, SIGNAL(clicked()), ui_->toolBox, SLOT(resetCurrentPage()));
// udpate objects button
connect(ui_->pushButton_updateObjects, SIGNAL(clicked()), this, SLOT(updateObjects()));
ui_->actionStop_camera->setEnabled(false); ui_->actionStop_camera->setEnabled(false);
ui_->actionSave_objects->setEnabled(false); ui_->actionSave_objects->setEnabled(false);
@ -185,7 +188,7 @@ void MainWindow::removeObject(ObjWidget * object)
void MainWindow::addObject() void MainWindow::addObject()
{ {
disconnect(camera_, SIGNAL(imageReceived(const cv::Mat &)), this, SLOT(update(const cv::Mat &))); disconnect(camera_, SIGNAL(imageReceived(const cv::Mat &)), this, SLOT(update(const cv::Mat &)));
AddObjectDialog dialog(camera_, &objects_, this); AddObjectDialog dialog(camera_, &objects_, ui_->imageView_source->isMirrorView(), this);
if(dialog.exec() == QDialog::Accepted) if(dialog.exec() == QDialog::Accepted)
{ {
showObject(objects_.last()); showObject(objects_.last());
@ -198,6 +201,7 @@ void MainWindow::showObject(ObjWidget * obj)
if(obj) if(obj)
{ {
obj->setGraphicsViewMode(false); obj->setGraphicsViewMode(false);
obj->setMirrorView(ui_->imageView_source->isMirrorView());
QList<ObjWidget*> objs = ui_->objects_area->findChildren<ObjWidget*>(); QList<ObjWidget*> objs = ui_->objects_area->findChildren<ObjWidget*>();
QVBoxLayout * vLayout = new QVBoxLayout(); QVBoxLayout * vLayout = new QVBoxLayout();
obj->setMinimumSize(obj->image().width(), obj->image().height()); obj->setMinimumSize(obj->image().width(), obj->image().height());
@ -214,8 +218,10 @@ void MainWindow::showObject(ObjWidget * obj)
} }
QLabel * title = new QLabel(QString("%1 (%2)").arg(obj->id()).arg(QString::number(obj->keypoints().size())), this); 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); QLabel * detectorDescriptorType = new QLabel(QString("%1/%2").arg(obj->detectorType()).arg(obj->descriptorType()), this);
QLabel * detectedLabel = new QLabel(this);
title->setObjectName(QString("%1title").arg(obj->id()));
detectorDescriptorType->setObjectName(QString("%1type").arg(obj->id()));
detectedLabel->setObjectName(QString("%1detection").arg(obj->id())); detectedLabel->setObjectName(QString("%1detection").arg(obj->id()));
QHBoxLayout * hLayout = new QHBoxLayout(); QHBoxLayout * hLayout = new QHBoxLayout();
hLayout->addWidget(title); hLayout->addWidget(title);
@ -236,6 +242,46 @@ void MainWindow::showObject(ObjWidget * obj)
} }
} }
void MainWindow::updateObjects()
{
if(objects_.size())
{
for(int i=0; i<objects_.size(); ++i)
{
IplImage * img = cvCloneImage(objects_.at(i)->iplImage());
cv::FeatureDetector * detector = Settings::createFeaturesDetector();
std::vector<cv::KeyPoint> keypoints;
detector->detect(img, keypoints);
delete detector;
cv::Mat descriptors;
if(keypoints.size())
{
cv::DescriptorExtractor * extractor = Settings::createDescriptorsExtractor();
extractor->compute(img, keypoints, descriptors);
delete extractor;
if((int)keypoints.size() != descriptors.rows)
{
printf("ERROR : kpt=%d != descriptors=%d\n", (int)keypoints.size(), descriptors.rows);
}
}
else
{
printf("WARNING: no features detected in object %d !?!\n", objects_.at(i)->id());
}
objects_.at(i)->setData(keypoints, descriptors, img, Settings::currentDetectorType(), Settings::currentDescriptorType());
//update object labels
QLabel * title = qFindChild<QLabel*>(this, QString("%1title").arg(objects_.at(i)->id()));
title->setText(QString("%1 (%2)").arg(objects_.at(i)->id()).arg(QString::number(objects_.at(i)->keypoints().size())));
QLabel * detectorDescriptorType = qFindChild<QLabel*>(this, QString("%1type").arg(objects_.at(i)->id()));
detectorDescriptorType->setText(QString("%1/%2").arg(objects_.at(i)->detectorType()).arg(objects_.at(i)->descriptorType()));
}
updateData();
}
this->statusBar()->clearMessage();
}
void MainWindow::updateData() void MainWindow::updateData()
{ {
if(objects_.size()) if(objects_.size())
@ -401,7 +447,7 @@ void MainWindow::update(const cv::Mat & image)
// PROCESS RESULTS // PROCESS RESULTS
if(this->isVisible()) if(this->isVisible())
{ {
ui_->imageView_source->setData(keypoints, cv::Mat(), &iplImage); ui_->imageView_source->setData(keypoints, cv::Mat(), &iplImage, Settings::currentDetectorType(), Settings::currentDescriptorType());
} }
int j=0; int j=0;
std::vector<cv::Point2f> mpts_1, mpts_2; std::vector<cv::Point2f> mpts_1, mpts_2;
@ -564,7 +610,7 @@ void MainWindow::update(const cv::Mat & image)
} }
else if(this->isVisible()) else if(this->isVisible())
{ {
ui_->imageView_source->setData(keypoints, cv::Mat(), &iplImage); ui_->imageView_source->setData(keypoints, cv::Mat(), &iplImage, Settings::currentDetectorType(), Settings::currentDescriptorType());
} }
if(this->isVisible()) if(this->isVisible())
@ -602,3 +648,11 @@ void MainWindow::update(const cv::Mat & image)
refreshStartTime_.start(); refreshStartTime_.start();
} }
} }
void MainWindow::notifyParametersChanged()
{
if(objects_.size())
{
this->statusBar()->showMessage(tr("A parameter has changed... \"Update objects\" may be required."));
}
}

View File

@ -47,6 +47,8 @@ private slots:
void addObject(); void addObject();
void removeObject(ObjWidget * object); void removeObject(ObjWidget * object);
void update(const cv::Mat & image); void update(const cv::Mat & image);
void updateObjects();
void notifyParametersChanged();
signals: signals:
void objectsFound(const QMap<int, QPair<QRect, QTransform> > &); void objectsFound(const QMap<int, QPair<QRect, QTransform> > &);

View File

@ -49,13 +49,13 @@ ObjWidget::ObjWidget(int id,
iplImage_(0), iplImage_(0),
graphicsView_(0), graphicsView_(0),
id_(id), id_(id),
detectorType_(detectorType), detectorType_("NA"),
descriptorType_(descriptorType), descriptorType_("NA"),
graphicsViewInitialized_(false), graphicsViewInitialized_(false),
alpha_(50) alpha_(50)
{ {
setupUi(); setupUi();
this->setData(keypoints, descriptors, iplImage); this->setData(keypoints, descriptors, iplImage, detectorType, descriptorType);
} }
ObjWidget::~ObjWidget() ObjWidget::~ObjWidget()
{ {
@ -189,6 +189,20 @@ void ObjWidget::setSizedFeatures(bool on)
} }
} }
void ObjWidget::setMirrorView(bool on)
{
_mirrorView->setChecked(on);
graphicsView_->setTransform(QTransform().scale(this->isMirrorView()?-1.0:1.0, 1.0));
if(_graphicsViewMode->isChecked() && _autoScale->isChecked())
{
graphicsView_->fitInView(graphicsView_->sceneRect(), Qt::KeepAspectRatio);
}
else if(!_graphicsViewMode->isChecked())
{
this->update();
}
}
void ObjWidget::setAlpha(int alpha) void ObjWidget::setAlpha(int alpha)
{ {
if(alpha>=0 && alpha<=255) if(alpha>=0 && alpha<=255)
@ -218,7 +232,11 @@ void ObjWidget::setAlpha(int alpha)
} }
} }
void ObjWidget::setData(const std::vector<cv::KeyPoint> & keypoints, const cv::Mat & descriptors, const IplImage * image) void ObjWidget::setData(const std::vector<cv::KeyPoint> & keypoints,
const cv::Mat & descriptors,
const IplImage * image,
const QString & detectorType,
const QString & descriptorType)
{ {
keypoints_ = keypoints; keypoints_ = keypoints;
descriptors_ = descriptors; descriptors_ = descriptors;
@ -227,6 +245,8 @@ void ObjWidget::setData(const std::vector<cv::KeyPoint> & keypoints, const cv::M
rectItems_.clear(); rectItems_.clear();
graphicsView_->scene()->clear(); graphicsView_->scene()->clear();
graphicsViewInitialized_ = false; graphicsViewInitialized_ = false;
detectorType_ = detectorType;
descriptorType_ = descriptorType;
if(iplImage_) if(iplImage_)
{ {
cvReleaseImage(&iplImage_); cvReleaseImage(&iplImage_);
@ -314,6 +334,11 @@ bool ObjWidget::isFeaturesShown() const
return _showFeatures->isChecked(); return _showFeatures->isChecked();
} }
bool ObjWidget::isSizedFeatures() const
{
return _sizedFeatures->isChecked();
}
bool ObjWidget::isMirrorView() const bool ObjWidget::isMirrorView() const
{ {
return _mirrorView->isChecked(); return _mirrorView->isChecked();
@ -354,7 +379,8 @@ void ObjWidget::load(QDataStream & streamPtr)
cv::Mat descriptors; cv::Mat descriptors;
int nKpts; int nKpts;
streamPtr >> id_ >> detectorType_ >> descriptorType_ >> nKpts; QString detectorType, descriptorType;
streamPtr >> id_ >> detectorType >> descriptorType >> nKpts;
for(int i=0;i<nKpts;++i) for(int i=0;i<nKpts;++i)
{ {
cv::KeyPoint kpt; cv::KeyPoint kpt;
@ -376,10 +402,50 @@ void ObjWidget::load(QDataStream & streamPtr)
streamPtr >> data; streamPtr >> data;
descriptors = cv::Mat(rows, cols, type, data.data()).clone(); descriptors = cv::Mat(rows, cols, type, data.data()).clone();
streamPtr >> image_; streamPtr >> image_;
this->setData(kpts, descriptors, 0); this->setData(kpts, descriptors, 0, detectorType, descriptorType);
//this->setMinimumSize(image_.size()); //this->setMinimumSize(image_.size());
} }
void ObjWidget::computeScaleOffsets(float & scale, float & offsetX, float & offsetY)
{
scale = 1.0f;
offsetX = 0.0f;
offsetY = 0.0f;
if(!image_.isNull())
{
float w = image_.width();
float h = image_.height();
float widthRatio = float(this->rect().width()) / w;
float heightRatio = float(this->rect().height()) / h;
//printf("w=%f, h=%f, wR=%f, hR=%f, sW=%d, sH=%d\n", w, h, widthRatio, heightRatio, this->rect().width(), this->rect().height());
if(widthRatio < heightRatio)
{
scale = widthRatio;
}
else
{
scale = heightRatio;
}
//printf("ratio=%f\n",ratio);
w *= scale;
h *= scale;
if(w < this->rect().width())
{
offsetX = (this->rect().width() - w)/2.0f;
}
if(h < this->rect().height())
{
offsetY = (this->rect().height() - h)/2.0f;
}
//printf("offsetX=%f, offsetY=%f\n",offsetX, offsetY);
}
}
void ObjWidget::paintEvent(QPaintEvent *event) void ObjWidget::paintEvent(QPaintEvent *event)
{ {
if(_graphicsViewMode->isChecked()) if(_graphicsViewMode->isChecked())
@ -391,42 +457,13 @@ void ObjWidget::paintEvent(QPaintEvent *event)
if(!image_.isNull()) if(!image_.isNull())
{ {
//Scale //Scale
float w = image_.width(); float ratio, offsetX, offsetY;
float h = image_.height(); this->computeScaleOffsets(ratio, offsetX, offsetY);
float widthRatio = float(this->rect().width()) / w;
float heightRatio = float(this->rect().height()) / h;
float ratio = 1.0f;
//printf("w=%f, h=%f, wR=%f, hR=%f, sW=%d, sH=%d\n", w, h, widthRatio, heightRatio, this->rect().width(), this->rect().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); QPainter painter(this);
if(_mirrorView->isChecked()) if(_mirrorView->isChecked())
{ {
painter.translate(offsetX+w, offsetY); painter.translate(offsetX+image_.width()*ratio, offsetY);
painter.scale(-ratio, ratio); painter.scale(-ratio, ratio);
} }
else else
@ -445,7 +482,6 @@ void ObjWidget::paintEvent(QPaintEvent *event)
drawKeypoints(&painter); drawKeypoints(&painter);
} }
for(int i=0; i<rectItems_.size(); ++i) for(int i=0; i<rectItems_.size(); ++i)
{ {
painter.save(); painter.save();
@ -455,6 +491,28 @@ void ObjWidget::paintEvent(QPaintEvent *event)
painter.restore(); painter.restore();
} }
if(mouseCurrentPos_ != mousePressedPos_)
{
painter.save();
int left, top, right, bottom;
left = mousePressedPos_.x() < mouseCurrentPos_.x() ? mousePressedPos_.x():mouseCurrentPos_.x();
top = mousePressedPos_.y() < mouseCurrentPos_.y() ? mousePressedPos_.y():mouseCurrentPos_.y();
right = mousePressedPos_.x() > mouseCurrentPos_.x() ? mousePressedPos_.x():mouseCurrentPos_.x();
bottom = mousePressedPos_.y() > mouseCurrentPos_.y() ? mousePressedPos_.y():mouseCurrentPos_.y();
if(_mirrorView->isChecked())
{
int l = left;
left = qAbs(right - image_.width());
right = qAbs(l - image_.width());
}
painter.setPen(Qt::NoPen);
painter.setBrush(QBrush(QColor(0,0,0,100)));
painter.drawRect(0, 0, image_.width(), top-1);
painter.drawRect(0, top, left, bottom-top);
painter.drawRect(right, top, image_.width()-right, bottom-top);
painter.drawRect(0, bottom, image_.width(), image_.height()-bottom);
painter.restore();
}
} }
} }
} }
@ -468,6 +526,50 @@ void ObjWidget::resizeEvent(QResizeEvent* event)
} }
} }
void ObjWidget::mousePressEvent(QMouseEvent * event)
{
float scale, offsetX, offsetY;
this->computeScaleOffsets(scale, offsetX, offsetY);
mousePressedPos_.setX((event->pos().x()-offsetX)/scale);
mousePressedPos_.setY((event->pos().y()-offsetY)/scale);
mouseCurrentPos_ = mousePressedPos_;
this->update();
QWidget::mousePressEvent(event);
}
void ObjWidget::mouseMoveEvent(QMouseEvent * event)
{
float scale, offsetX, offsetY;
this->computeScaleOffsets(scale, offsetX, offsetY);
mouseCurrentPos_.setX((event->pos().x()-offsetX)/scale);
mouseCurrentPos_.setY((event->pos().y()-offsetY)/scale);
this->update();
QWidget::mouseMoveEvent(event);
}
void ObjWidget::mouseReleaseEvent(QMouseEvent * event)
{
if(!image_.isNull())
{
int left,top,bottom,right;
left = mousePressedPos_.x() < mouseCurrentPos_.x() ? mousePressedPos_.x():mouseCurrentPos_.x();
top = mousePressedPos_.y() < mouseCurrentPos_.y() ? mousePressedPos_.y():mouseCurrentPos_.y();
right = mousePressedPos_.x() > mouseCurrentPos_.x() ? mousePressedPos_.x():mouseCurrentPos_.x();
bottom = mousePressedPos_.y() > mouseCurrentPos_.y() ? mousePressedPos_.y():mouseCurrentPos_.y();
if(_mirrorView->isChecked())
{
int l = left;
left = qAbs(right - image_.width());
right = qAbs(l - image_.width());
}
emit roiChanged(QRect(left, top, right-left, bottom-top));
}
QWidget::mouseReleaseEvent(event);
}
void ObjWidget::contextMenuEvent(QContextMenuEvent * event) void ObjWidget::contextMenuEvent(QContextMenuEvent * event)
{ {
QAction * action = _menu->exec(event->globalPos()); QAction * action = _menu->exec(event->globalPos());
@ -502,15 +604,7 @@ void ObjWidget::contextMenuEvent(QContextMenuEvent * event)
} }
else if(action == _mirrorView) else if(action == _mirrorView)
{ {
graphicsView_->setTransform(QTransform().scale(this->isMirrorView()?-1.0:1.0, 1.0)); this->setMirrorView(_mirrorView->isChecked());
if(_graphicsViewMode->isChecked() && _autoScale->isChecked())
{
graphicsView_->fitInView(graphicsView_->sceneRect(), Qt::KeepAspectRatio);
}
else if(!_graphicsViewMode->isChecked())
{
this->update();
}
} }
else if(action == _delete) else if(action == _delete)
{ {

View File

@ -35,15 +35,19 @@ public:
void setId(int id); void setId(int id);
void setData(const std::vector<cv::KeyPoint> & keypoints, void setData(const std::vector<cv::KeyPoint> & keypoints,
const cv::Mat & descriptors, const cv::Mat & descriptors,
const IplImage * image); const IplImage * image,
const QString & detectorType,
const QString & descriptorType);
void resetKptsColor(); void resetKptsColor();
void setKptColor(int index, const QColor & color); void setKptColor(int index, const QColor & color);
void setGraphicsViewMode(bool on); void setGraphicsViewMode(bool on);
void setAutoScale(bool autoScale); void setAutoScale(bool autoScale);
void setSizedFeatures(bool on); void setSizedFeatures(bool on);
void setMirrorView(bool on);
void setAlpha(int alpha); void setAlpha(int alpha);
void setDeletable(bool deletable); void setDeletable(bool deletable);
void addRect(QGraphicsRectItem * rect); void addRect(QGraphicsRectItem * rect);
void clearRoiSelection() {mousePressedPos_ = mouseCurrentPos_ = QPoint();update();}
const std::vector<cv::KeyPoint> & keypoints() const {return keypoints_;} const std::vector<cv::KeyPoint> & keypoints() const {return keypoints_;}
const cv::Mat & descriptors() const {return descriptors_;} const cv::Mat & descriptors() const {return descriptors_;}
@ -53,6 +57,7 @@ public:
QColor defaultColor() const; QColor defaultColor() const;
bool isImageShown() const; bool isImageShown() const;
bool isFeaturesShown() const; bool isFeaturesShown() const;
bool isSizedFeatures() const;
bool isMirrorView() const; bool isMirrorView() const;
//QGraphicsScene * scene() const; //QGraphicsScene * scene() const;
std::vector<cv::KeyPoint> selectedKeypoints() const; std::vector<cv::KeyPoint> selectedKeypoints() const;
@ -69,16 +74,21 @@ protected:
virtual void paintEvent(QPaintEvent *event); virtual void paintEvent(QPaintEvent *event);
virtual void contextMenuEvent(QContextMenuEvent * event); virtual void contextMenuEvent(QContextMenuEvent * event);
virtual void resizeEvent(QResizeEvent* event); virtual void resizeEvent(QResizeEvent* event);
virtual void mousePressEvent(QMouseEvent * event);
virtual void mouseMoveEvent(QMouseEvent * event);
virtual void mouseReleaseEvent(QMouseEvent * event);
signals: signals:
void removalTriggered(ObjWidget *); void removalTriggered(ObjWidget *);
void selectionChanged(); void selectionChanged();
void roiChanged(const QRect &);
private: private:
void setupGraphicsView(); void setupGraphicsView();
void drawKeypoints(QPainter * painter = 0); void drawKeypoints(QPainter * painter = 0);
void setupUi(); void setupUi();
void updateItemsShown(); void updateItemsShown();
void computeScaleOffsets(float & scale, float & offsetX, float & offsetY);
private: private:
std::vector<cv::KeyPoint> keypoints_; std::vector<cv::KeyPoint> keypoints_;
@ -107,6 +117,10 @@ private:
QAction * _autoScale; QAction * _autoScale;
QAction * _sizedFeatures; QAction * _sizedFeatures;
QAction * _setAlpha; QAction * _setAlpha;
// selection stuff
QPoint mousePressedPos_;
QPoint mouseCurrentPos_;
}; };

View File

@ -269,6 +269,7 @@ void ParametersToolBox::changeParameter()
{ {
Settings::setParameter(sender()->objectName(), spinBox->value()); Settings::setParameter(sender()->objectName(), spinBox->value());
} }
emit parametersChanged();
} }
} }
void ParametersToolBox::changeParameter(const int & value) void ParametersToolBox::changeParameter(const int & value)
@ -291,5 +292,6 @@ void ParametersToolBox::changeParameter(const int & value)
{ {
Settings::setParameter(sender()->objectName(), value==Qt::Checked?true:false); Settings::setParameter(sender()->objectName(), value==Qt::Checked?true:false);
} }
emit parametersChanged();
} }
} }

View File

@ -29,6 +29,9 @@ private:
void addParameter(QVBoxLayout * layout, const QString & key, const bool & value); void addParameter(QVBoxLayout * layout, const QString & key, const bool & value);
void addParameter(QVBoxLayout * layout, const QString & name, QWidget * widget); void addParameter(QVBoxLayout * layout, const QString & name, QWidget * widget);
signals:
void parametersChanged();
private slots: private slots:
void changeParameter(); void changeParameter();
void changeParameter(const QString & value); void changeParameter(const QString & value);

View File

@ -14,6 +14,8 @@
<string>Add object</string> <string>Add object</string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,1,0"> <layout class="QVBoxLayout" name="verticalLayout" stretch="0,1,0">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3" stretch="1,0">
<item> <item>
<widget class="QLabel" name="label_instruction"> <widget class="QLabel" name="label_instruction">
<property name="text"> <property name="text">
@ -21,6 +23,22 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QComboBox" name="comboBox_selection">
<item>
<property name="text">
<string>Select region</string>
</property>
</item>
<item>
<property name="text">
<string>Select keypoints</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_2"> <layout class="QHBoxLayout" name="horizontalLayout_2">
<item> <item>

View File

@ -379,7 +379,7 @@
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>300</width> <width>300</width>
<height>128</height> <height>162</height>
</size> </size>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -407,7 +407,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>274</width> <width>274</width>
<height>459</height> <height>425</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_objects"> <layout class="QVBoxLayout" name="verticalLayout_objects">
@ -431,6 +431,13 @@
</widget> </widget>
</widget> </widget>
</item> </item>
<item>
<widget class="QPushButton" name="pushButton_updateObjects">
<property name="text">
<string>Update objects</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</widget> </widget>