AddObjectDialog.cpp
Go to the documentation of this file.
1 /*
2 Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
3 All rights reserved.
4 
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7  * Redistributions of source code must retain the above copyright
8  notice, this list of conditions and the following disclaimer.
9  * Redistributions in binary form must reproduce the above copyright
10  notice, this list of conditions and the following disclaimer in the
11  documentation and/or other materials provided with the distribution.
12  * Neither the name of the Universite de Sherbrooke nor the
13  names of its contributors may be used to endorse or promote products
14  derived from this software without specific prior written permission.
15 
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 
28 #include "find_object/Camera.h"
29 #include "find_object/Settings.h"
31 #include "find_object/ObjWidget.h"
32 #include "find_object/QtOpenCV.h"
33 
34 #include "AddObjectDialog.h"
35 #include "ui_addObjectDialog.h"
36 #include "KeypointItem.h"
37 #include "ObjSignature.h"
38 
39 #include <stdio.h>
40 
41 #include <QGraphicsScene>
42 #include <QGraphicsPixmapItem>
43 #include <QMessageBox>
44 
45 #include <opencv2/imgproc/imgproc.hpp>
46 #include <opencv2/highgui/highgui.hpp>
47 
48 namespace find_object {
49 
50 AddObjectDialog::AddObjectDialog(Camera * camera, const cv::Mat & image, bool mirrorView, QWidget * parent, Qt::WindowFlags f) :
51  QDialog(parent, f),
52  camera_(camera),
53  objWidget_(0),
54  objSignature_(0)
55 {
56  ui_ = new Ui_addObjectDialog();
57  ui_->setupUi(this);
58 
61  UASSERT(detector_ != 0 && extractor_ != 0);
62 
63  connect(ui_->pushButton_cancel, SIGNAL(clicked()), this, SLOT(cancel()));
64  connect(ui_->pushButton_back, SIGNAL(clicked()), this, SLOT(back()));
65  connect(ui_->pushButton_next, SIGNAL(clicked()), this, SLOT(next()));
66  connect(ui_->pushButton_takePicture, SIGNAL(clicked()), this, SLOT(takePicture()));
67  connect(ui_->comboBox_selection, SIGNAL(currentIndexChanged(int)), this, SLOT(changeSelectionMode()));
68 
69  connect(ui_->cameraView, SIGNAL(selectionChanged()), this, SLOT(updateNextButton()));
70  connect(ui_->cameraView, SIGNAL(roiChanged(const cv::Rect &)), this, SLOT(updateNextButton(const cv::Rect &)));
71  ui_->cameraView->setMirrorView(mirrorView);
72 
73  if((camera_ && camera_->isRunning()) || image.empty())
74  {
75  this->setState(kTakePicture);
76  }
77  else if(!image.empty())
78  {
79  update(image);
81  }
82 }
83 
85 {
86  delete detector_;
87  delete extractor_;
88  if(objWidget_)
89  {
90  delete objWidget_;
91  objWidget_ = 0;
92  }
93  if(objSignature_)
94  {
95  delete objSignature_;
96  objSignature_ = 0;
97  }
98  delete ui_;
99 }
100 
102 {
103  *widget = objWidget_;
104  objWidget_= 0;
105  *signature = objSignature_;
106  objSignature_ = 0;
107 }
108 
109 void AddObjectDialog::closeEvent(QCloseEvent* event)
110 {
111  if(camera_)
112  {
113  disconnect(camera_, SIGNAL(imageReceived(const cv::Mat &)), this, SLOT(update(const cv::Mat &)));
114  }
115  QDialog::closeEvent(event);
116 }
117 
119 {
120  setState(state_+1);
121 }
123 {
124  setState(state_-1);
125 }
127 {
128  this->reject();
129 }
131 {
132  next();
133 }
134 
136 {
137  updateNextButton(cv::Rect());
138 }
139 
140 void AddObjectDialog::updateNextButton(const cv::Rect & rect)
141 {
142  roi_ = rect;
143  if(roi_.height && roi_.width && cameraImage_.cols)
144  {
145  //clip roi
146  if( roi_.x >= cameraImage_.cols ||
147  roi_.x+roi_.width <= 0 ||
148  roi_.y >= cameraImage_.rows ||
149  roi_.y+roi_.height <= 0)
150  {
151  //Not valid...
152  roi_ = cv::Rect();
153  }
154  else
155  {
156  if(roi_.x < 0)
157  {
158  roi_.x = 0;
159  }
160  if(roi_.x + roi_.width > cameraImage_.cols)
161  {
162  roi_.width = cameraImage_.cols - roi_.x;
163  }
164  if(roi_.y < 0)
165  {
166  roi_.y = 0;
167  }
168  if(roi_.y + roi_.height > cameraImage_.rows)
169  {
170  roi_.height = cameraImage_.rows - roi_.y;
171  }
172  }
173  }
174  if(state_ == kSelectFeatures)
175  {
176  if(ui_->comboBox_selection->currentIndex() == 1)
177  {
178  if(ui_->cameraView->selectedItems().size() > 0)
179  {
180  ui_->pushButton_next->setEnabled(true);
181  }
182  else
183  {
184  ui_->pushButton_next->setEnabled(false);
185  }
186  }
187  else
188  {
189  if(roi_.width == 0 || roi_.height == 0)
190  {
191  ui_->pushButton_next->setEnabled(false);
192  }
193  else
194  {
195  ui_->pushButton_next->setEnabled(true);
196  }
197  }
198  }
199 }
200 
202 {
203  this->setState(kSelectFeatures);
204 }
205 
207 {
208  state_ = state;
209  if(state == kTakePicture)
210  {
211  ui_->pushButton_cancel->setEnabled(true);
212  ui_->pushButton_back->setEnabled(false);
213  ui_->pushButton_next->setEnabled(false);
214  ui_->pushButton_takePicture->setEnabled(true);
215  ui_->label_instruction->setText(tr("Place the object in front of the camera and click \"Take picture\"."));
216  ui_->pushButton_next->setText(tr("Next"));
217  ui_->cameraView->setVisible(true);
218  ui_->cameraView->clearRoiSelection();
219  ui_->objectView->setVisible(false);
220  ui_->cameraView->setGraphicsViewMode(false);
221  ui_->comboBox_selection->setVisible(false);
222  if(!camera_ || !camera_->start())
223  {
224  QMessageBox::critical(this, tr("Camera error"), tr("Camera is not started!"));
225  ui_->pushButton_takePicture->setEnabled(false);
226  }
227  else
228  {
229  connect(camera_, SIGNAL(imageReceived(const cv::Mat &)), this, SLOT(update(const cv::Mat &)));
230  }
231  }
232  else if(state == kSelectFeatures)
233  {
234  if(camera_)
235  {
236  disconnect(camera_, SIGNAL(imageReceived(const cv::Mat &)), this, SLOT(update(const cv::Mat &)));
237  camera_->pause();
238  }
239 
240  ui_->pushButton_cancel->setEnabled(true);
241  ui_->pushButton_back->setEnabled(camera_);
242  ui_->pushButton_next->setEnabled(false);
243  ui_->pushButton_takePicture->setEnabled(false);
244  ui_->pushButton_next->setText(tr("Next"));
245  ui_->cameraView->setVisible(true);
246  ui_->cameraView->clearRoiSelection();
247  ui_->objectView->setVisible(false);
248  ui_->comboBox_selection->setVisible(true);
249 
250  if(ui_->comboBox_selection->currentIndex() == 1)
251  {
252  ui_->label_instruction->setText(tr("Select features representing the object."));
253  ui_->cameraView->setGraphicsViewMode(true);
254  }
255  else
256  {
257  ui_->label_instruction->setText(tr("Select region representing the object."));
258  ui_->cameraView->setGraphicsViewMode(false);
259  }
260  updateNextButton(cv::Rect());
261  }
262  else if(state == kVerifySelection)
263  {
264  if(camera_)
265  {
266  disconnect(camera_, SIGNAL(imageReceived(const cv::Mat &)), this, SLOT(update(const cv::Mat &)));
267  camera_->pause();
268  }
269 
270  ui_->pushButton_cancel->setEnabled(true);
271  ui_->pushButton_back->setEnabled(true);
272  ui_->pushButton_takePicture->setEnabled(false);
273  ui_->pushButton_next->setText(tr("End"));
274  ui_->cameraView->setVisible(true);
275  ui_->objectView->setVisible(true);
276  ui_->objectView->setMirrorView(ui_->cameraView->isMirrorView());
277  ui_->objectView->setSizedFeatures(ui_->cameraView->isSizedFeatures());
278  ui_->comboBox_selection->setVisible(false);
279  if(ui_->comboBox_selection->currentIndex() == 1)
280  {
281  ui_->cameraView->setGraphicsViewMode(true);
282  }
283  else
284  {
285  ui_->cameraView->setGraphicsViewMode(false);
286  }
287 
288  std::vector<cv::KeyPoint> selectedKeypoints = ui_->cameraView->selectedKeypoints();
289 
290  // Select keypoints
291  if(!cameraImage_.empty() &&
292  ((ui_->comboBox_selection->currentIndex() == 1 && selectedKeypoints.size()) ||
293  (ui_->comboBox_selection->currentIndex() == 0 && roi_.width && roi_.height)))
294  {
295  if(ui_->comboBox_selection->currentIndex() == 1)
296  {
297  roi_ = computeROI(selectedKeypoints);
298  }
299 
300  cv::Mat imgRoi(cameraImage_, roi_);
301 
302  if(ui_->comboBox_selection->currentIndex() == 1)
303  {
304  if(roi_.x != 0 || roi_.y != 0)
305  {
306  for(unsigned int i=0; i<selectedKeypoints.size(); ++i)
307  {
308  selectedKeypoints.at(i).pt.x -= roi_.x;
309  selectedKeypoints.at(i).pt.y -= roi_.y;
310  }
311  }
312  }
313  else
314  {
315  // Extract keypoints
316  selectedKeypoints.clear();
317  detector_->detect(imgRoi, selectedKeypoints);
318  }
319  ui_->objectView->updateImage(cvtCvMat2QImage(imgRoi.clone()));
320  ui_->objectView->updateData(selectedKeypoints, QMultiMap<int,int>());
321  ui_->objectView->setMinimumSize(roi_.width, roi_.height);
322  ui_->objectView->update();
323  ui_->pushButton_next->setEnabled(true);
324  }
325  else
326  {
327  UINFO("Please select items");
328  ui_->pushButton_next->setEnabled(false);
329  }
330  ui_->label_instruction->setText(tr("Selection : %1 features").arg(selectedKeypoints.size()));
331  }
332  else if(state == kClosing)
333  {
334  std::vector<cv::KeyPoint> keypoints = ui_->objectView->keypoints();
335  if((ui_->comboBox_selection->currentIndex() == 1 && keypoints.size()) ||
336  (ui_->comboBox_selection->currentIndex() == 0 && roi_.width && roi_.height))
337  {
338  cv::Mat descriptors;
339  cv::Mat imgRoi(cameraImage_, roi_);
340  if(keypoints.size())
341  {
342  // Extract descriptors
343  extractor_->compute(imgRoi, keypoints, descriptors);
344 
345  if(keypoints.size() != (unsigned int)descriptors.rows)
346  {
347  UERROR("keypoints=%d != descriptors=%d", (int)keypoints.size(), descriptors.rows);
348  }
349  }
350 
351  if(objWidget_)
352  {
353  delete objWidget_;
354  objWidget_ = 0;
355  }
356  if(objSignature_)
357  {
358  delete objSignature_;
359  objSignature_ = 0;
360  }
361  objSignature_ = new ObjSignature(0, imgRoi.clone(), "");
362  objSignature_->setData(keypoints, descriptors);
363  objWidget_ = new ObjWidget(0, keypoints, QMultiMap<int,int>(), cvtCvMat2QImage(imgRoi.clone()));
364 
365  this->accept();
366  }
367  }
368 }
369 
370 void AddObjectDialog::update(const cv::Mat & image)
371 {
372  cameraImage_ = cv::Mat();
373  if(!image.empty())
374  {
375  // convert to grayscale
376  if(image.channels() != 1 || image.depth() != CV_8U)
377  {
378  cv::cvtColor(image, cameraImage_, CV_BGR2GRAY);
379  }
380  else
381  {
382  cameraImage_ = image.clone();
383  }
384 
385  // Extract keypoints
386  std::vector<cv::KeyPoint> keypoints;
387  detector_->detect(cameraImage_, keypoints);
388 
389  ui_->cameraView->updateImage(cvtCvMat2QImage(cameraImage_));
390  ui_->cameraView->updateData(keypoints, QMultiMap<int,int>());
391  ui_->cameraView->update();
392  }
393  else
394  {
395  UWARN("Camera cannot get more images (maybe the end of stream is reached)...");
396  camera_->stop();
397  }
398 }
399 
400 cv::Rect AddObjectDialog::computeROI(const std::vector<cv::KeyPoint> & kpts)
401 {
402  cv::Rect roi(0,0,0,0);
403  int x1=0,x2=0,h1=0,h2=0;
404  for(unsigned int i=0; i<kpts.size(); ++i)
405  {
406  float radius = kpts.at(i).size / 2;
407  if(i==0)
408  {
409  x1 = int(kpts.at(i).pt.x - radius);
410  x2 = int(kpts.at(i).pt.x + radius);
411  h1 = int(kpts.at(i).pt.y - radius);
412  h2 = int(kpts.at(i).pt.y + radius);
413  }
414  else
415  {
416  if(x1 > int(kpts.at(i).pt.x - radius))
417  {
418  x1 = int(kpts.at(i).pt.x - radius);
419  }
420  else if(x2 < int(kpts.at(i).pt.x + radius))
421  {
422  x2 = int(kpts.at(i).pt.x + radius);
423  }
424  if(h1 > int(kpts.at(i).pt.y - radius))
425  {
426  h1 = int(kpts.at(i).pt.y - radius);
427  }
428  else if(h2 < int(kpts.at(i).pt.y + radius))
429  {
430  h2 = int(kpts.at(i).pt.y + radius);
431  }
432  }
433  roi.x = x1;
434  roi.y = h1;
435  roi.width = x2-x1;
436  roi.height = h2-h1;
437  //UINFO("ptx=%d, pty=%d", (int)kpts.at(i).pt.x, (int)kpts.at(i).pt.y);
438  //UINFO("x=%d, y=%d, w=%d, h=%d", roi.x, roi.y, roi.width, roi.height);
439  }
440 
441  return roi;
442 }
443 
444 } // namespace find_object
Ui_addObjectDialog * ui_
void update(const cv::Mat &)
static Feature2D * createKeypointDetector()
Definition: Settings.cpp:617
virtual bool start()
Definition: Camera.cpp:183
virtual bool isRunning()
Definition: Camera.h:50
#define UASSERT(condition)
virtual void closeEvent(QCloseEvent *event)
AddObjectDialog(Camera *camera, const cv::Mat &image, bool mirrorView, QWidget *parent=0, Qt::WindowFlags f=0)
virtual void detect(const cv::Mat &image, std::vector< cv::KeyPoint > &keypoints, const cv::Mat &mask=cv::Mat())
Definition: Settings.cpp:1457
void setData(const std::vector< cv::KeyPoint > &keypoints, const cv::Mat &descriptors)
Definition: ObjSignature.h:53
cv::Rect computeROI(const std::vector< cv::KeyPoint > &kpts)
virtual void compute(const cv::Mat &image, std::vector< cv::KeyPoint > &keypoints, cv::Mat &descriptors)
Definition: Settings.cpp:1478
virtual void stop()
Definition: Camera.cpp:55
#define UERROR(...)
ULogger class and convenient macros.
#define UWARN(...)
static Feature2D * createDescriptorExtractor()
Definition: Settings.cpp:954
FINDOBJECT_EXP QImage cvtCvMat2QImage(const cv::Mat &image, bool isBgr=true)
Definition: QtOpenCV.cpp:34
void retrieveObject(ObjWidget **widget, ObjSignature **signature)
#define UINFO(...)


find_object_2d
Author(s): Mathieu Labbe
autogenerated on Thu Jun 6 2019 19:22:26