ViSP
 All Classes Functions Variables Enumerations Enumerator Friends Groups Pages
vpFernClassifier.cpp
1 /****************************************************************************
2  *
3  * $Id: vpFernClassifier.cpp 4303 2013-07-04 14:14:00Z fspindle $
4  *
5  * This file is part of the ViSP software.
6  * Copyright (C) 2005 - 2013 by INRIA. All rights reserved.
7  *
8  * This software is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * ("GPL") version 2 as published by the Free Software Foundation.
11  * See the file LICENSE.GPL at the root directory of this source
12  * distribution for additional information about the GNU GPL.
13  *
14  * For using ViSP with software that can not be combined with the GNU
15  * GPL, please contact INRIA about acquiring a ViSP Professional
16  * Edition License.
17  *
18  * See http://www.irisa.fr/lagadic/visp/visp.html for more information.
19  *
20  * This software was developed at:
21  * INRIA Rennes - Bretagne Atlantique
22  * Campus Universitaire de Beaulieu
23  * 35042 Rennes Cedex
24  * France
25  * http://www.irisa.fr/lagadic
26  *
27  * If you have questions regarding the use of this file, please contact
28  * INRIA at visp@inria.fr
29  *
30  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
31  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
32  *
33  *
34  * Description:
35  * Class that implements the Fern classifier and the YAPE detector thanks
36  * to the OpenCV library.
37  *
38  * Authors:
39  * Romain Tallonneau
40  *
41  *****************************************************************************/
42 
43 #include <visp/vpConfig.h>
44 
45 #if (VISP_HAVE_OPENCV_VERSION >= 0x020000) // Require opencv >= 2.0.0
46 
47 #include <visp/vpFernClassifier.h>
48 #include <visp/vpImageTools.h>
49 #include <visp/vpImageConvert.h>
50 #include <visp/vpColor.h>
51 #include <visp/vpDisplay.h>
52 
57 vpFernClassifier::vpFernClassifier():vpBasicKeyPoint(), gen(0, 256, 5, true, 0.6, 1.5, -CV_PI/2, CV_PI/2, -CV_PI/2, CV_PI/2)
58 {
59  init();
60 }
61 
72 vpFernClassifier::vpFernClassifier(const std::string& _dataFile, const std::string& _objectName)
73 {
74  init();
75  this->load(_dataFile, _objectName);
76 }
77 
83 {
84  if(curIplImg != NULL){
85  if(curIplImg->width % 8 == 0){
86  curIplImg->imageData = NULL;
87  cvReleaseImageHeader(&curIplImg);
88  }else{
89  cvReleaseImage(&curIplImg);
90  }
91  curIplImg = NULL;
92  }
93 }
94 
100 void
102 {
103  hasLearn = false;
104  nbClassfier = 100;
105  ClassifierSize = 11;
106  nbPoints = 200;
107  curIplImg = NULL;
108  blurImage = true;
109  radiusBlur = 7;
110  sigmaBlur = 1;
111  patchSize = 32;
112  radius = 7;
113  threshold = 20;
114  nbOctave = 2;
115  nbView = 2000;
116  dist = 2;
117  nbMinPoint = 10;
118 }
119 
120 
121 
122 
126 void
128 {
129  // initialise detector
130  cv::LDetector d(radius, threshold, nbOctave, nbView, patchSize, dist);
131 
132  //blur
133  cv::Mat obj = (cv::Mat)curIplImg;
134 
135  if(this->getBlurSetting()){
136  cv::GaussianBlur(obj, obj, cv::Size(getBlurSize(), getBlurSize()), getBlurSigma(), getBlurSigma());
137  }
138 
139  // build pyramid
140  std::vector<cv::Mat> objpyr;
141  cv::buildPyramid(obj, objpyr, d.nOctaves-1);
142 
143  // getPoints
144  d.getMostStable2D(obj, objKeypoints, 100, gen);
145 
146  ldetector = d;
147 
148  // train classifier
149  modelROI = cv::Rect(0, 0, objpyr[0].cols, objpyr[0].rows);
150  ldetector.getMostStable2D(objpyr[0], modelPoints, 100, gen);
151 
152  fernClassifier.trainFromSingleView(objpyr[0], modelPoints,
153  patchSize, (int)modelPoints.size(), 100, 11, 10000,
154  cv::FernClassifier::COMPRESSION_NONE, gen);
155 
156  /* from OpenCV format to ViSP format */
157  referenceImagePointsList.resize(0);
158  for (unsigned int i = 0; i < modelPoints.size(); i += 1){
159  vpImagePoint ip(
160  modelPoints[i].pt.y + modelROI_Ref.y,
161  modelPoints[i].pt.x + modelROI_Ref.x);
162  referenceImagePointsList.push_back(ip);
163  }
164 
165  // set flag
166  hasLearn = true;
167 }
168 
182 unsigned int
184 {
185  this->setImage(_I);
186 
187  train();
188 
189  _reference_computed = true;
190  return (unsigned int)objKeypoints.size();
191 }
192 
211 unsigned int
213  const vpImagePoint &_iP,
214  const unsigned int _height, const unsigned int _width)
215 {
216  if((_iP.get_i()+_height) >= _I.getHeight()
217  || (_iP.get_j()+_width) >= _I.getWidth()) {
218  vpTRACE("Bad size for the subimage");
220  "Bad size for the subimage"));
221  }
222 
223  vpImage<unsigned char> subImage;
225  (unsigned int)_iP.get_i(),
226  (unsigned int)_iP.get_j(),
227  _height, _width, subImage);
228  this->setImage(subImage);
229 
230  /* initialise a structure containing the region of interest used in the
231  reference image */
232  modelROI_Ref.x = (int)_iP.get_u();
233  modelROI_Ref.y = (int)_iP.get_v();
234  modelROI_Ref.width = (int)_width;
235  modelROI_Ref.height = (int)_height;
236 
237  train();
238 
239  return (unsigned int)objKeypoints.size();
240 }
241 
258 unsigned int
260  const vpRect& _rectangle)
261 {
262  vpImagePoint iP;
263  iP.set_i(_rectangle.getTop());
264  iP.set_j(_rectangle.getLeft());
265  return (this->buildReference(_I, iP,
266  (unsigned int)_rectangle.getHeight(),
267  (unsigned int)_rectangle.getWidth()));
268 }
269 
281 unsigned int
283 {
284  if(!hasLearn){
285  vpERROR_TRACE("The object has not been learned. ");
286  throw vpException(vpException::notInitialized , "object is not learned, load database or build the reference ");
287  }
288 
289  setImage(_I);
290  // resize image
291 // cv::resize(_image, image, Size(), 1./imgscale, 1./imgscale, INTER_CUBIC);
292  cv::Mat img = this->curIplImg;
293 
294  if(this->getBlurSetting()){
295  cv::GaussianBlur(img, img, cv::Size(this->getBlurSize(), this->getBlurSize()), this->getBlurSigma(), this->getBlurSigma());
296  }
297 
298  std::vector<cv::Mat> imgPyr;
299  cv::buildPyramid(img, imgPyr, ldetector.nOctaves-1);
300 
301 
302  ldetector(imgPyr, imgKeypoints, 500);
303 
304  unsigned int m = (unsigned int)modelPoints.size();
305  unsigned int n = (unsigned int)imgKeypoints.size();
306  std::vector<int> bestMatches(m, -1);
307  std::vector<float> maxLogProb(m, -FLT_MAX);
308  std::vector<float> signature;
309  unsigned int totalMatch = 0;
310 
311 
312  /* part of code from OpenCV planarObjectDetector */
313  currentImagePointsList.resize(0);
314  matchedReferencePoints.resize(0);
315 
316  for(unsigned int i = 0; i < n; i++ ){
317  cv::KeyPoint kpt = imgKeypoints[i];
318  kpt.pt.x /= (float)(1 << kpt.octave);
319  kpt.pt.y /= (float)(1 << kpt.octave);
320  int k = fernClassifier(imgPyr[(unsigned int)kpt.octave], kpt.pt, signature);
321  if( k >= 0 && (bestMatches[(unsigned int)k] < 0 || signature[(unsigned int)k] > maxLogProb[(unsigned int)k]) ){
322  maxLogProb[(unsigned int)k] = signature[(unsigned int)k];
323  bestMatches[(unsigned int)k] = (int)i;
324  totalMatch++;
325 
326  vpImagePoint ip_cur( imgKeypoints[i].pt.y, imgKeypoints[i].pt.x);
327 
328  currentImagePointsList.push_back(ip_cur);
329  matchedReferencePoints.push_back((unsigned int)k);
330 
331  }
332  }
333 
334  refPt.resize(0);
335  curPt.resize(0);
336  for(unsigned int i = 0; i < m; i++ ){
337  if( bestMatches[i] >= 0 ){
338  refPt.push_back(modelPoints[i].pt);
339  curPt.push_back(imgKeypoints[(unsigned int)bestMatches[i]].pt);
340  }
341  }
342 
343  return totalMatch;
344 }
345 
346 
347 
361 unsigned int
363  const vpImagePoint &_iP,
364  const unsigned int _height, const unsigned int _width)
365 {
366  if((_iP.get_i()+_height) >= _I.getHeight()
367  || (_iP.get_j()+_width) >= _I.getWidth()) {
368  vpTRACE("Bad size for the subimage");
370  "Bad size for the subimage"));
371  }
372 
373  vpImage<unsigned char> subImage;
374 
376  (unsigned int)_iP.get_i(),
377  (unsigned int)_iP.get_j(),
378  _height, _width, subImage);
379 
380  return this->matchPoint(subImage);
381 }
382 
394 unsigned int
396  const vpRect& _rectangle)
397 {
398  vpImagePoint iP;
399  iP.set_i(_rectangle.getTop());
400  iP.set_j(_rectangle.getLeft());
401  return (this->matchPoint(_I, iP,
402  (unsigned int)_rectangle.getHeight(),
403  (unsigned int)_rectangle.getWidth()));
404 }
405 
406 
423 void
425  const vpImage<unsigned char> &_Icurrent, unsigned int size)
426 {
427  for (unsigned int i = 0; i < matchedReferencePoints.size(); i++){
430  }
431 
432 }
433 
434 
445 void
446 vpFernClassifier::display(const vpImage<unsigned char> &_Icurrent, unsigned int size,
447  const vpColor &color)
448 {
449  for (unsigned int i = 0; i < matchedReferencePoints.size(); i++){
450  vpDisplay::displayCross (_Icurrent, currentImagePointsList[i], size, color);
451  }
452 }
453 
454 /* IO METHODS */
455 
464 void
465 vpFernClassifier::load(const std::string& _dataFile, const std::string& /*_objectName*/)
466 {
467  std::cout << " > Load data for the planar object detector..." << std::endl;
468 
469  /* part of code from OpenCV planarObjectDetector */
470  cv::FileStorage fs(_dataFile, cv::FileStorage::READ);
471  cv::FileNode node = fs.getFirstTopLevelNode();
472 
473  cv::FileNodeIterator it = node["model-roi"].begin(), it_end;
474  it >> modelROI.x >> modelROI.y >> modelROI.width >> modelROI.height;
475 
476  ldetector.read(node["detector"]);
477  fernClassifier.read(node["fern-classifier"]);
478 
479  const cv::FileNode node_ = node["model-points"];
480  cv::read(node_, modelPoints);
481 
482  cv::LDetector d(radius, threshold, nbOctave, nbView, patchSize, dist);
483  ldetector = d;
484  hasLearn = true;
485 }
486 
487 
494 void
495 vpFernClassifier::record(const std::string& _objectName, const std::string& _dataFile )
496 {
497  /* part of code from OpenCV planarObjectDetector */
498  cv::FileStorage fs(_dataFile, cv::FileStorage::WRITE);
499 
500  cv::WriteStructContext ws(fs, _objectName, CV_NODE_MAP);
501 
502  {
503  cv::WriteStructContext wsroi(fs, "model-roi", CV_NODE_SEQ + CV_NODE_FLOW);
504  cv::write(fs, modelROI_Ref.x);
505  cv::write(fs, modelROI_Ref.y);
506  cv::write(fs, modelROI_Ref.width);
507  cv::write(fs, modelROI_Ref.height);
508  }
509 
510  ldetector.write(fs, "detector");
511  cv::write(fs, "model-points", modelPoints);
512  fernClassifier.write(fs, "fern-classifier");
513 }
514 
515 
516 
523 void
525 {
526  if(curIplImg != NULL){
527  cvResetImageROI(curIplImg);
528  if((curIplImg->width % 8) == 0){
529  curIplImg->imageData = NULL;
530  cvReleaseImageHeader(&curIplImg);
531  }else{
532  cvReleaseImage(&curIplImg);
533  }
534  curIplImg = NULL;
535  }
536 
537  if((_I.getWidth()%8) == 0){
538  curIplImg = cvCreateImageHeader(cvSize((int)_I.getWidth(), (int)_I.getHeight()), IPL_DEPTH_8U, 1);
539  if(curIplImg != NULL){
540  curIplImg->imageData = (char*)_I.bitmap;
541  }else{
542  throw vpException(vpException::memoryAllocationError, "Could not create the image in the OpenCV format.");
543  }
544  }else{
546  }
547  if(curIplImg == NULL){
548  std::cout << "!> conversion failed" << std::endl;
549  throw vpException(vpException::notInitialized , "conversion failed");
550  }
551 }
552 
553 #endif
554