ViSP
 All Classes Functions Variables Enumerations Enumerator Friends Groups Pages
vpFernClassifier.cpp
1 /****************************************************************************
2  *
3  * $Id: vpFernClassifier.cpp 4056 2013-01-05 13:04:42Z 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 objKeypoints.size();
191 
192 }
193 
212 unsigned int
214  const vpImagePoint &_iP,
215  const unsigned int _height, const unsigned int _width)
216 {
217  if((_iP.get_i()+_height) >= _I.getHeight()
218  || (_iP.get_j()+_width) >= _I.getWidth()) {
219  vpTRACE("Bad size for the subimage");
221  "Bad size for the subimage"));
222  }
223 
224  vpImage<unsigned char> subImage;
226  (unsigned int)_iP.get_i(),
227  (unsigned int)_iP.get_j(),
228  _height, _width, subImage);
229  this->setImage(subImage);
230 
231  /* initialise a structure containing the region of interest used in the
232  reference image */
233  modelROI_Ref.x = (int)_iP.get_u();
234  modelROI_Ref.y = (int)_iP.get_v();
235  modelROI_Ref.width = (int)_width;
236  modelROI_Ref.height = (int)_height;
237 
238  train();
239 
240  return objKeypoints.size();
241 }
242 
259 unsigned int
261  const vpRect& _rectangle)
262 {
263  vpImagePoint iP;
264  iP.set_i(_rectangle.getTop());
265  iP.set_j(_rectangle.getLeft());
266  return (this->buildReference(_I, iP,
267  (unsigned int)_rectangle.getHeight(),
268  (unsigned int)_rectangle.getWidth()));
269 }
270 
282 unsigned int
284 {
285  if(!hasLearn){
286  vpERROR_TRACE("The object has not been learned. ");
287  throw vpException(vpException::notInitialized , "object is not learned, load database or build the reference ");
288  }
289 
290  setImage(_I);
291  // resize image
292 // cv::resize(_image, image, Size(), 1./imgscale, 1./imgscale, INTER_CUBIC);
293  cv::Mat img = this->curIplImg;
294 
295  if(this->getBlurSetting()){
296  cv::GaussianBlur(img, img, cv::Size(this->getBlurSize(), this->getBlurSize()), this->getBlurSigma(), this->getBlurSigma());
297  }
298 
299  std::vector<cv::Mat> imgPyr;
300  cv::buildPyramid(img, imgPyr, ldetector.nOctaves-1);
301 
302 
303  ldetector(imgPyr, imgKeypoints, 500);
304 
305  unsigned int m = modelPoints.size();
306  unsigned int n = imgKeypoints.size();
307  std::vector<int> bestMatches(m, -1);
308  std::vector<float> maxLogProb(m, -FLT_MAX);
309  std::vector<float> signature;
310  unsigned int totalMatch = 0;
311 
312 
313  /* part of code from OpenCV planarObjectDetector */
314  currentImagePointsList.resize(0);
315  matchedReferencePoints.resize(0);
316 
317  for(unsigned int i = 0; i < n; i++ ){
318  cv::KeyPoint kpt = imgKeypoints[i];
319  kpt.pt.x /= (float)(1 << kpt.octave);
320  kpt.pt.y /= (float)(1 << kpt.octave);
321  int k = fernClassifier(imgPyr[(unsigned int)kpt.octave], kpt.pt, signature);
322  if( k >= 0 && (bestMatches[(unsigned int)k] < 0 || signature[(unsigned int)k] > maxLogProb[(unsigned int)k]) ){
323  maxLogProb[(unsigned int)k] = signature[(unsigned int)k];
324  bestMatches[(unsigned int)k] = (int)i;
325  totalMatch++;
326 
327  vpImagePoint ip_cur( imgKeypoints[i].pt.y, imgKeypoints[i].pt.x);
328 
329  currentImagePointsList.push_back(ip_cur);
330  matchedReferencePoints.push_back((unsigned int)k);
331 
332  }
333  }
334 
335  refPt.resize(0);
336  curPt.resize(0);
337  for(unsigned int i = 0; i < m; i++ ){
338  if( bestMatches[i] >= 0 ){
339  refPt.push_back(modelPoints[i].pt);
340  curPt.push_back(imgKeypoints[(unsigned int)bestMatches[i]].pt);
341  }
342  }
343 
344  return totalMatch;
345 }
346 
347 
348 
362 unsigned int
364  const vpImagePoint &_iP,
365  const unsigned int _height, const unsigned int _width)
366 {
367  if((_iP.get_i()+_height) >= _I.getHeight()
368  || (_iP.get_j()+_width) >= _I.getWidth()) {
369  vpTRACE("Bad size for the subimage");
371  "Bad size for the subimage"));
372  }
373 
374  vpImage<unsigned char> subImage;
375 
377  (unsigned int)_iP.get_i(),
378  (unsigned int)_iP.get_j(),
379  _height, _width, subImage);
380 
381  return this->matchPoint(subImage);
382 }
383 
395 unsigned int
397  const vpRect& _rectangle)
398 {
399  vpImagePoint iP;
400  iP.set_i(_rectangle.getTop());
401  iP.set_j(_rectangle.getLeft());
402  return (this->matchPoint(_I, iP,
403  (unsigned int)_rectangle.getHeight(),
404  (unsigned int)_rectangle.getWidth()));
405 }
406 
407 
424 void
426  const vpImage<unsigned char> &_Icurrent, unsigned int size)
427 {
428  for (unsigned int i = 0; i < matchedReferencePoints.size(); i++){
431  }
432 
433 }
434 
435 
446 void
447 vpFernClassifier::display(const vpImage<unsigned char> &_Icurrent, unsigned int size,
448  const vpColor &color)
449 {
450  for (unsigned int i = 0; i < matchedReferencePoints.size(); i++){
451  vpDisplay::displayCross (_Icurrent, currentImagePointsList[i], size, color);
452  }
453 }
454 
455 /* IO METHODS */
456 
465 void
466 vpFernClassifier::load(const std::string& _dataFile, const std::string& /*_objectName*/)
467 {
468  std::cout << " > Load data for the planar object detector..." << std::endl;
469 
470  /* part of code from OpenCV planarObjectDetector */
471  cv::FileStorage fs(_dataFile, cv::FileStorage::READ);
472  cv::FileNode node = fs.getFirstTopLevelNode();
473 
474  cv::FileNodeIterator it = node["model-roi"].begin(), it_end;
475  it >> modelROI.x >> modelROI.y >> modelROI.width >> modelROI.height;
476 
477  ldetector.read(node["detector"]);
478  fernClassifier.read(node["fern-classifier"]);
479 
480  const cv::FileNode node_ = node["model-points"];
481  cv::read(node_, modelPoints);
482 
483  cv::LDetector d(radius, threshold, nbOctave, nbView, patchSize, dist);
484  ldetector = d;
485  hasLearn = true;
486 }
487 
488 
495 void
496 vpFernClassifier::record(const std::string& _objectName, const std::string& _dataFile )
497 {
498  /* part of code from OpenCV planarObjectDetector */
499  cv::FileStorage fs(_dataFile, cv::FileStorage::WRITE);
500 
501  cv::WriteStructContext ws(fs, _objectName, CV_NODE_MAP);
502 
503  {
504  cv::WriteStructContext wsroi(fs, "model-roi", CV_NODE_SEQ + CV_NODE_FLOW);
505  cv::write(fs, modelROI_Ref.x);
506  cv::write(fs, modelROI_Ref.y);
507  cv::write(fs, modelROI_Ref.width);
508  cv::write(fs, modelROI_Ref.height);
509  }
510 
511  ldetector.write(fs, "detector");
512  cv::write(fs, "model-points", modelPoints);
513  fernClassifier.write(fs, "fern-classifier");
514 }
515 
516 
517 
524 void
526 {
527  if(curIplImg != NULL){
528  cvResetImageROI(curIplImg);
529  if((curIplImg->width % 8) == 0){
530  curIplImg->imageData = NULL;
531  cvReleaseImageHeader(&curIplImg);
532  }else{
533  cvReleaseImage(&curIplImg);
534  }
535  curIplImg = NULL;
536  }
537 
538  if((_I.getWidth()%8) == 0){
539  curIplImg = cvCreateImageHeader(cvSize((int)_I.getWidth(), (int)_I.getHeight()), IPL_DEPTH_8U, 1);
540  if(curIplImg != NULL){
541  curIplImg->imageData = (char*)_I.bitmap;
542  }else{
543  throw vpException(vpException::memoryAllocationError, "Could not create the image in the OpenCV format.");
544  }
545  }else{
547  }
548  if(curIplImg == NULL){
549  std::cout << "!> conversion failed" << std::endl;
550  throw vpException(vpException::notInitialized , "conversion failed");
551  }
552 }
553 
554 #endif
555