Main MRPT website > C++ reference for MRPT 1.5.7
CImage.cpp
Go to the documentation of this file.
1 /* +---------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | http://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2017, Individual contributors, see AUTHORS file |
6  | See: http://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See details in http://www.mrpt.org/License |
8  +---------------------------------------------------------------------------+ */
9 
10 #include "base-precomp.h" // Precompiled headers
11 
12 #include <mrpt/utils/CImage.h>
16 #include <mrpt/compress/zip.h>
17 #include <mrpt/math/CMatrix.h>
18 #include <mrpt/math/fourier.h>
19 #include <mrpt/math/utils.h> // for roundup()
20 #include <mrpt/utils/round.h> // for round()
21 #include <mrpt/utils/CTicTac.h>
22 #include <mrpt/utils/CTimeLogger.h>
23 #include <mrpt/system/memory.h>
24 #include <mrpt/system/filesystem.h>
25 
26 // Universal include for all versions of OpenCV
27 #include <mrpt/otherlibs/do_opencv_includes.h>
28 
29 #if MRPT_HAS_MATLAB
30 # include <mexplus/mxarray.h>
31 #endif
32 
33 // Prototypes of SSE2/SSE3/SSSE3 optimized functions:
34 #include "CImage_SSEx.h"
35 
36 #if MRPT_HAS_WXWIDGETS
37 # include <wx/image.h>
38 #endif
39 
40 using namespace mrpt;
41 using namespace mrpt::utils;
42 using namespace mrpt::math;
43 using namespace mrpt::system;
44 using namespace std;
45 
46 // This must be added to any CSerializable class implementation file.
48 
49 
53 
55 
56 // Do performance time logging?
57 #define IMAGE_ALLOC_PERFLOG 0
58 
59 #if IMAGE_ALLOC_PERFLOG
60 mrpt::utils::CTimeLogger alloc_tims;
61 #endif
62 
63 /*---------------------------------------------------------------
64  Constructor
65  ---------------------------------------------------------------*/
66 CImage::CImage( unsigned int width,
67  unsigned int height,
68  TImageChannels nChannels,
69  bool originTopLeft ) :
70  img(NULL),
71  m_imgIsReadOnly(false),
72  m_imgIsExternalStorage(false)
73 {
75  changeSize( width, height, nChannels, originTopLeft );
76  MRPT_END
77 }
78 /*---------------------------------------------------------------
79  Default Constructor
80  ---------------------------------------------------------------*/
82  img(NULL),
83  m_imgIsReadOnly(false),
84  m_imgIsExternalStorage(false)
85 {
86 #if MRPT_HAS_OPENCV
88  changeSize( 1, 1, CH_RGB, true );
89  MRPT_END
90 #endif
91 }
92 
93 /*---------------------------------------------------------------
94  Copy constructor
95  ---------------------------------------------------------------*/
96 CImage::CImage( const CImage &o ) :
97  img(NULL),
98  m_imgIsReadOnly(false),
99  m_imgIsExternalStorage(false)
100 {
101  MRPT_START
102  *this = o;
103  MRPT_END
104 }
105 
106 /*---------------------------------------------------------------
107  Copy operator
108  ---------------------------------------------------------------*/
110 {
111  MRPT_START
112  if (this==&o) return *this;
113  releaseIpl();
115  m_imgIsReadOnly = false;
116 
117  if (!o.m_imgIsExternalStorage)
118  { // A normal image
119 #if MRPT_HAS_OPENCV
120  ASSERTMSG_(o.img!=NULL,"Source image in = operator has NULL IplImage*")
121  img = cvCloneImage( (IplImage*)o.img );
122 #endif
123  }
124  else
125  { // An externally stored image:
127  }
128  return *this;
129  MRPT_END
130 }
131 
132 /*---------------------------------------------------------------
133  swap
134  ---------------------------------------------------------------*/
136 {
137  std::swap( img, o.img );
138  std::swap( m_imgIsReadOnly, o.m_imgIsReadOnly );
140  std::swap( m_externalFile, o.m_externalFile );
141 }
142 
143 /*---------------------------------------------------------------
144  copyFromForceLoad
145 
146  Copies from another image, and, if that one is externally
147  stored, the image file will be actually loaded into memory
148  in "this" object.
149  ---------------------------------------------------------------*/
151 {
152  if (o.isExternallyStored())
153  {
154  // Load from that file:
156  THROW_TYPED_EXCEPTION_FMT(CExceptionExternalImageNotFound,"Error loading externally-stored image from: %s", o.getExternalStorageFileAbsolutePath().c_str());
157  }
158  else
159  { // It's not external storage.
160  *this = o;
161  }
162 }
163 
164 /*---------------------------------------------------------------
165  copyFastFrom
166  ---------------------------------------------------------------*/
168 {
169  MRPT_START
170  if (this==&o) return;
172  {
173  // Just copy the reference to the ext. file:
174  *this = o;
175  }
176  else
177  { // Normal copy
178 #if MRPT_HAS_OPENCV
179  if (!o.img) THROW_EXCEPTION("Origin image is empty! (o.img==NULL)")
180 #endif
181  // Erase current image:
182  releaseIpl();
183 
184  // Make the transfer of just the pointer:
185  img = o.img;
189 
190  o.img = NULL;
191  o.m_imgIsReadOnly = false;
192  o.m_imgIsExternalStorage=false;
193  }
194 
195  MRPT_END
196 }
197 
198 /*---------------------------------------------------------------
199  Constructor from IplImage
200  ---------------------------------------------------------------*/
201 CImage::CImage( void *iplImage ) :
202  img(NULL),
203  m_imgIsReadOnly(false),
204  m_imgIsExternalStorage(false)
205 {
206  MRPT_START
207 
208 #if MRPT_HAS_OPENCV
209  if (!iplImage)
210  changeSize( 1, 1, 1, true );
211  else
212  img = cvCloneImage( (IplImage*) iplImage );
213 #endif
214  MRPT_END
215 }
216 
217 /*---------------------------------------------------------------
218  Destructor
219  ---------------------------------------------------------------*/
221 {
222  releaseIpl();
223 }
224 
225 /*---------------------------------------------------------------
226  changeSize
227  ---------------------------------------------------------------*/
229  unsigned int width,
230  unsigned int height,
231  TImageChannels nChannels,
232  bool originTopLeft)
233 {
234  MRPT_START
235 
236 #if MRPT_HAS_OPENCV
237  // If we're resizing to exactly the current size, do nothing and avoid wasting mem allocs/deallocs!
238  if (img)
239  {
240  makeSureImageIsLoaded(); // For delayed loaded images stored externally
241  IplImage *ipl = static_cast<IplImage*>(img);
242  if (static_cast<unsigned int>(ipl->width)==width &&
243  static_cast<unsigned int>(ipl->height)==height &&
244  ipl->nChannels == nChannels &&
245  ipl->origin == ( originTopLeft ? 0:1)
246  )
247  {
248  return; // nothing to do, we're already right with the current IplImage!
249  }
250  }
251 
252  // Delete current img
253  releaseIpl();
254 
255 # if IMAGE_ALLOC_PERFLOG
256  const std::string sLog = mrpt::format("cvCreateImage %ux%u",width,height);
257  alloc_tims.enter(sLog.c_str());
258 # endif
259 
260  img = cvCreateImage( cvSize(width,height),IPL_DEPTH_8U, nChannels );
261  ((IplImage*)img)->origin = originTopLeft ? 0:1;
262 
263 # if IMAGE_ALLOC_PERFLOG
264  alloc_tims.leave(sLog.c_str());
265 # endif
266 
267 #else
268  THROW_EXCEPTION("The MRPT has been compiled with MRPT_HAS_OPENCV=0 !");
269 #endif
270 
271  MRPT_END
272 }
273 
274 /*---------------------------------------------------------------
275  loadFromFile
276  ---------------------------------------------------------------*/
277 bool CImage::loadFromFile( const std::string& fileName, int isColor )
278 {
279  MRPT_START
280 
281 #if MRPT_HAS_OPENCV
282  IplImage* newImg = cvLoadImage(fileName.c_str(),isColor);
283  if (newImg!=NULL) {
284  releaseIpl();
285  img = newImg;
286  return true;
287  } else {
288  return false;
289  }
290 #else
291  THROW_EXCEPTION("The MRPT has been compiled with MRPT_HAS_OPENCV=0 !");
292 #endif
293  MRPT_END
294 }
295 
296 /*---------------------------------------------------------------
297  saveToFile
298  ---------------------------------------------------------------*/
299 bool CImage::saveToFile( const std::string& fileName, int jpeg_quality ) const
300 {
301  MRPT_START
302 #if MRPT_HAS_OPENCV
303  makeSureImageIsLoaded(); // For delayed loaded images stored externally
304  ASSERT_(img!=NULL);
305 
306  #if MRPT_OPENCV_VERSION_NUM>0x110
307  int p[3];
308  p[0] = CV_IMWRITE_JPEG_QUALITY;
309  p[1] = jpeg_quality;
310  p[2] = 0;
311  return (0!= cvSaveImage(fileName.c_str(),img,p) );
312  #else
313  return (0!= cvSaveImage(fileName.c_str(),img) );
314  #endif
315 #else
316  THROW_EXCEPTION("The MRPT has been compiled with MRPT_HAS_OPENCV=0 !");
317 #endif
318  MRPT_END
319 }
320 
321 /*---------------------------------------------------------------
322  loadFromIplImage
323  ---------------------------------------------------------------*/
324 void CImage::loadFromIplImage( void* iplImage )
325 {
326  MRPT_START
327  ASSERT_(iplImage!=NULL)
328  releaseIpl();
329  if (iplImage)
330  {
331 #if MRPT_HAS_OPENCV
332  img = cvCloneImage( (IplImage*)iplImage );
333 #else
334  THROW_EXCEPTION("The MRPT has been compiled with MRPT_HAS_OPENCV=0 !");
335 #endif
336  }
337  MRPT_END
338 }
339 
340 /*---------------------------------------------------------------
341  setFromIplImageReadOnly
342  ---------------------------------------------------------------*/
343 void CImage::setFromIplImageReadOnly( void* iplImage )
344 {
345  MRPT_START
346  releaseIpl();
347 #if MRPT_HAS_OPENCV
348  ASSERT_(iplImage!=NULL)
349  ASSERTMSG_(iplImage!=this->img,"Trying to assign read-only to itself.")
350 
351  img = (IplImage*)iplImage;
352 #else
353  if (iplImage) {
354  THROW_EXCEPTION("The MRPT has been compiled with MRPT_HAS_OPENCV=0 !");
355  }
356 #endif
357  m_imgIsReadOnly = true;
359  MRPT_END
360 }
361 
362 /*---------------------------------------------------------------
363  setFromIplImage
364  ---------------------------------------------------------------*/
365 void CImage::setFromIplImage( void* iplImage )
366 {
367  MRPT_START
368 
369  releaseIpl();
370  if (iplImage)
371  {
372 #if MRPT_HAS_OPENCV
373  img = (IplImage*)iplImage;
374 #else
375  THROW_EXCEPTION("The MRPT has been compiled with MRPT_HAS_OPENCV=0 !");
376 #endif
377  }
378  m_imgIsReadOnly = false;
380 
381  MRPT_END
382 }
383 
384 /*---------------------------------------------------------------
385  loadFromMemoryBuffer
386  ---------------------------------------------------------------*/
388  unsigned int width,
389  unsigned int height,
390  bool color,
391  unsigned char *rawpixels,
392  bool swapRedBlue )
393 {
394  MRPT_START
395 
396 #if MRPT_HAS_OPENCV
397  resize(width,height,color ? 3:1, true);
398  m_imgIsReadOnly = false;
400 
401  if (color && swapRedBlue)
402  {
403  // Do copy & swap at once:
404  unsigned char *ptr_src = rawpixels;
405  unsigned char *ptr_dest = reinterpret_cast<unsigned char*>( ((IplImage*)img)->imageData );
406  const int bytes_per_row_out = ((IplImage*)img)->widthStep;
407 
408  for(int h=height; h--; )
409  {
410  for( unsigned int i = 0; i < width; i++, ptr_src += 3, ptr_dest += 3 )
411  {
412  unsigned char t0 = ptr_src[0], t1 = ptr_src[1], t2 = ptr_src[2];
413  ptr_dest[2] = t0; ptr_dest[1] = t1; ptr_dest[0] = t2;
414  }
415  ptr_dest += bytes_per_row_out - width*3;
416  }
417  }
418  else
419  {
420  if ( ((IplImage*)img)->widthStep == ((IplImage*)img)->width * ((IplImage*)img)->nChannels )
421  {
422  // Copy the image data:
423  memcpy( ((IplImage*)img)->imageData,
424  rawpixels,
425  ((IplImage*)img)->imageSize);
426  }
427  else
428  {
429  // Copy the image row by row:
430  unsigned char *ptr_src = rawpixels;
431  unsigned char *ptr_dest = reinterpret_cast<unsigned char*>( ((IplImage*)img)->imageData );
432  int bytes_per_row = width * (color ? 3:1);
433  int bytes_per_row_out = ((IplImage*)img)->widthStep;
434  for (unsigned int y=0;y<height;y++)
435  {
436  memcpy( ptr_dest, ptr_src, bytes_per_row );
437  ptr_src+=bytes_per_row;
438  ptr_dest+=bytes_per_row_out;
439  }
440  }
441  }
442 #else
443  THROW_EXCEPTION("The MRPT has been compiled with MRPT_HAS_OPENCV=0 !");
444 #endif
445  MRPT_END
446 }
447 
448 /*---------------------------------------------------------------
449  operator()
450  ---------------------------------------------------------------*/
451 unsigned char* CImage::operator()(
452  unsigned int col,
453  unsigned int row,
454  unsigned int channel) const
455 {
456 #if MRPT_HAS_OPENCV
457 
458 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG)
459  MRPT_START
460 #endif
461 
462  makeSureImageIsLoaded(); // For delayed loaded images stored externally
463  IplImage *ipl = ((IplImage*)img);
464 
465 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG)
466  ASSERT_(ipl);
467  if (row>=(unsigned int)ipl->height || col>=(unsigned int)ipl->width || channel>=(unsigned int)ipl->nChannels )
468  {
469  THROW_EXCEPTION( format("Pixel coordinates/channel out of bounds: row=%u/%u col=%u/%u chan=%u/%u",
470  row, ipl->height,
471  col, ipl->width,
472  channel, ipl->nChannels ) );
473  }
474 #endif
475 
476  return (unsigned char*) &ipl->imageData [ row * ipl->widthStep +
477  col * ipl->nChannels +
478  channel ];
479 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG)
480  MRPT_END
481 #endif
482 
483 #else
484  THROW_EXCEPTION("MRPT was compiled without OpenCV")
485 #endif
486 }
487 
488 /*---------------------------------------------------------------
489  get_unsafe()
490  ---------------------------------------------------------------*/
491 unsigned char* CImage::get_unsafe(
492  unsigned int col,
493  unsigned int row,
494  unsigned int channel) const
495 {
496 #if MRPT_HAS_OPENCV
497  makeSureImageIsLoaded(); // For delayed loaded images stored externally
498  IplImage *ipl = ((IplImage*)img);
499  return (unsigned char*) &ipl->imageData [ row * ipl->widthStep +
500  col * ipl->nChannels +
501  channel ];
502 #else
503  return NULL;
504 #endif
505 }
506 
507 /*---------------------------------------------------------------
508  Implements the writing to a CStream capability of CSerializable objects
509  ---------------------------------------------------------------*/
511 {
512 #if !MRPT_HAS_OPENCV
513  if (version)
514  *version = 100;
515  else
516  {
517  out << m_imgIsExternalStorage;
518 
520  out << m_externalFile;
521  // Nothing else to serialize!
522  }
523 #else
524  if (version)
525  *version = 8;
526  else
527  {
528  // Added in version 6: possibility of being stored offline:
529  out << m_imgIsExternalStorage;
530 
532  {
533  out << m_externalFile;
534  }
535  else
536  { // Normal image loaded in memory:
537  ASSERT_(img!=NULL);
538 
539  const bool hasColor = isColor();
540 
541  out << hasColor;
542 
543  // Version >2: Color->JPEG, GrayScale->BYTE's array!
544  if ( !hasColor )
545  {
546  // GRAY-SCALE: Raw bytes:
547  // Version 3: ZIP compression!
548  // Version 4: Skip zip if the image size <= 16Kb
549  int32_t width = ((IplImage*)img)->width;
550  int32_t height = ((IplImage*)img)->height;
551  int32_t origin = ((IplImage*)img)->origin;
552  int32_t imageSize = ((IplImage*)img)->imageSize;
553 
554  out << width << height << origin << imageSize;
555 
556  // Version 5: Use CImage::DISABLE_ZIP_COMPRESSION
557  bool imageStoredAsZip = !CImage::DISABLE_ZIP_COMPRESSION && (imageSize>16*1024);
558 
559  out << imageStoredAsZip;
560 
561  // Version 4: Skip zip if the image size <= 16Kb
562  if (imageStoredAsZip )
563  {
564  std::vector<unsigned char> tempBuf;
566  ((IplImage*)img)->imageData, // Data
567  ((IplImage*)img)->imageSize, // Size
568  tempBuf);
569 
570  int32_t zipDataLen = (int32_t )tempBuf.size();
571 
572  out << zipDataLen;
573 
574  out.WriteBuffer( &tempBuf[0], tempBuf.size() );
575  tempBuf.clear();
576  }
577  else
578  {
579  out.WriteBuffer( ((IplImage*)img)->imageData,((IplImage*)img)->imageSize );
580  }
581  }
582  else
583  {
584  // COLOR: High quality JPEG image
585 
586  // v7: If size is 0xN or Nx0, don't call "saveToStreamAsJPEG"!!
587  const int32_t width = ((IplImage*)img)->width;
588  const int32_t height = ((IplImage*)img)->height;
589 
590  // v8: If DISABLE_JPEG_COMPRESSION
592  {
593  // normal behavior: compress images:
594  out << width << height;
595 
596  if (width>=1 && height>=1)
597  {
598  // Save to temporary memory stream:
599  CMemoryStream aux;
601 
602  const uint32_t nBytes = static_cast<uint32_t>(aux.getTotalBytesCount());
603 
604  out << nBytes;
605  out.WriteBuffer( aux.getRawBufferData(), nBytes );
606  }
607  }
608  else
609  { // (New in v8)
610  // Don't JPEG-compress behavior:
611  // Use negative image sizes to signal this behavior:
612  const int32_t neg_width = -width;
613  const int32_t neg_height = -height;
614 
615  out << neg_width << neg_height;
616 
617  // Dump raw image data:
618  const IplImage *ipl = static_cast<const IplImage*>(img);
619  const size_t bytes_per_row = ipl->width * 3;
620 
621  out.WriteBuffer( &ipl->imageData[0], bytes_per_row*ipl->height );
622 
623  }
624  }
625  } // end m_imgIsExternalStorage=false
626  }
627 #endif
628 }
629 
630 /*---------------------------------------------------------------
631  Implements the reading from a CStream capability of CSerializable objects
632  ---------------------------------------------------------------*/
634 {
635 #if !MRPT_HAS_OPENCV
636  if (version==100)
637  {
640  in >> m_externalFile;
641  else
642  {
643  THROW_EXCEPTION("[CImage] Cannot deserialize image since MRPT has been compiled without OpenCV")
644  }
645  }
646 #else
647  releaseIpl(); // First, free current image.
648 
649  switch(version)
650  {
651  case 100: // Saved from an MRPT build without OpenCV:
652  {
655  in >> m_externalFile;
656  }
657  break;
658  case 0:
659  {
660  uint32_t width, height, nChannels, imgLength;
661  uint8_t originTopLeft;
662 
663  in >> width >> height >> nChannels >> originTopLeft >> imgLength;
664 
665  changeSize(width, height, nChannels, originTopLeft !=0 );
666  in.ReadBuffer( ((IplImage*)img)->imageData, imgLength );
667  } break;
668  case 1:
669  {
670  // Version 1: High quality JPEG image
671  CMemoryStream aux;
672  uint32_t nBytes;
673  in >> nBytes;
674 
675  aux.changeSize( nBytes + 10 );
676 
677  in.ReadBuffer( aux.getRawBufferData(), nBytes );
678 
679  aux.Seek(0);
680 
681  loadFromStreamAsJPEG( aux );
682 
683  } break;
684  case 2:
685  case 3:
686  case 4:
687  case 5:
688  case 6:
689  case 7:
690  case 8:
691  {
692  // Version 6: m_imgIsExternalStorage ??
693  if (version>=6)
695  else m_imgIsExternalStorage=false;
696 
698  {
699  // Just the file name:
700  in >> m_externalFile;
701  }
702  else
703  { // Normal, the whole image data:
704 
705  // Version 2: Color->JPEG, GrayScale->BYTE's array!
706  uint8_t hasColor;
707  in >> hasColor;
708  if (!hasColor)
709  {
710  // GRAY SCALE:
711  int32_t width,height,origin, imageSize;
712  in >> width >> height >> origin >> imageSize;
713 
714  changeSize(width, height, 1, origin == 0 );
715  ASSERT_( imageSize == ((IplImage*)img)->imageSize );
716 
717  if (version==2)
718  {
719  // RAW BYTES:
720  in.ReadBuffer( ((IplImage*)img)->imageData, imageSize );
721  }
722  else
723  {
724  // Version 3: ZIP compression!
725  bool imageIsZIP = true;
726 
727  // Version 4: Skip zip if the image size <= 16Kb
728  // Version 5: Use CImage::DISABLE_ZIP_COMPRESSION
729  if (version==4 && imageSize<=16*1024)
730  imageIsZIP = false;
731 
732  if (version>=5)
733  {
734  // It is stored int the stream:
735  in >> imageIsZIP;
736  }
737 
738  if (imageIsZIP)
739  {
740  uint32_t zipDataLen;
741  in >> zipDataLen;
742 
743  size_t outDataBufferSize = imageSize;
744  size_t outDataActualSize;
745 
747  in,
748  zipDataLen,
749  ((IplImage*)img)->imageData,
750  outDataBufferSize,
751  outDataActualSize );
752 
753  ASSERT_(outDataActualSize==outDataBufferSize);
754  }
755  else
756  {
757  // Raw bytes:
758  in.ReadBuffer( ((IplImage*)img)->imageData,((IplImage*)img)->imageSize );
759  }
760  }
761  }
762  else
763  {
764  bool loadJPEG=true;
765 
766  if (version>=7)
767  {
769  in >> width >> height;
770 
771  if (width>=1 && height>=1)
772  {
773  loadJPEG = true;
774  }
775  else
776  {
777  loadJPEG = false;
778 
779  if (width<0 && height<0)
780  {
781  // v8: raw image:
782  const int32_t real_w = -width;
783  const int32_t real_h = -height;
784 
785  this->changeSize(real_w,real_h,3,true);
786 
787  const IplImage *ipl = static_cast<const IplImage*>(img);
788  const size_t bytes_per_row = ipl->width * 3;
789  for (int y=0;y<ipl->height;y++)
790  {
791  const size_t nRead = in.ReadBuffer( &ipl->imageData[y*ipl->widthStep], bytes_per_row);
792  if (nRead!=bytes_per_row) THROW_EXCEPTION("Error: Truncated data stream while parsing raw image?")
793  }
794  }
795  else
796  {
797  // it's a 0xN or Nx0 image: just resize and load nothing:
798  this->changeSize(width,height,3,true);
799  }
800  }
801  }
802 
803  // COLOR IMAGE: JPEG
804  if (loadJPEG)
805  {
806  CMemoryStream aux;
807  uint32_t nBytes;
808  in >> nBytes;
809  aux.changeSize( nBytes + 10 );
810  in.ReadBuffer( aux.getRawBufferData(), nBytes );
811  aux.Seek(0);
812  loadFromStreamAsJPEG( aux );
813  }
814  }
815  }
816 
817  } break;
818  default:
820 
821  };
822 #endif
823 }
824 
825 /*---------------------------------------------------------------
826  Implements the writing to a mxArray for Matlab
827  ---------------------------------------------------------------*/
828 #if MRPT_HAS_MATLAB
829 // Add to implement mexplus::from template specialization
831 
833 {
834  cv::Mat cvImg = cv::cvarrToMat( this->getAs<IplImage>() );
835  return mexplus::from( cvImg );
836 }
837 #endif
838 
839 /*---------------------------------------------------------------
840  getSize
841  ---------------------------------------------------------------*/
843 {
844 #if MRPT_HAS_OPENCV
845  makeSureImageIsLoaded(); // For delayed loaded images stored externally
846  ASSERT_(img!=NULL);
847  s.x = ((IplImage*)img)->width;
848  s.y = ((IplImage*)img)->height;
849 #endif
850 }
851 
852 /*---------------------------------------------------------------
853  getWidth
854  ---------------------------------------------------------------*/
855 size_t CImage::getWidth() const
856 {
857 #if MRPT_HAS_OPENCV
858  makeSureImageIsLoaded(); // For delayed loaded images stored externally
859  ASSERT_(img!=NULL);
860  return ((IplImage*)img)->width;
861 #else
862  return 0;
863 #endif
864 }
865 
866 /*---------------------------------------------------------------
867  getRowStride
868  ---------------------------------------------------------------*/
869 size_t CImage::getRowStride() const
870 {
871 #if MRPT_HAS_OPENCV
872  makeSureImageIsLoaded(); // For delayed loaded images stored externally
873  ASSERT_(img!=NULL);
874  return ((IplImage*)img)->widthStep;
875 #else
876  return 0;
877 #endif
878 }
879 
880 
881 /*---------------------------------------------------------------
882  getWidth
883  ---------------------------------------------------------------*/
884 size_t CImage::getHeight() const
885 {
886 #if MRPT_HAS_OPENCV
887  makeSureImageIsLoaded(); // For delayed loaded images stored externally
888  ASSERT_(img!=NULL);
889  return ((IplImage*)img)->height;
890 #else
891  return 0;
892 #endif
893 }
894 
895 /*---------------------------------------------------------------
896  isColor
897  ---------------------------------------------------------------*/
898 bool CImage::isColor() const
899 {
900 #if MRPT_HAS_OPENCV
901  makeSureImageIsLoaded(); // For delayed loaded images stored externally
902  ASSERT_(img!=NULL);
903  return ((IplImage*)img)->nChannels > 1;
904 #else
905  return false;
906 #endif
907 }
908 
909 /*---------------------------------------------------------------
910  getChannelCount
911  ---------------------------------------------------------------*/
913 {
914 #if MRPT_HAS_OPENCV
915  makeSureImageIsLoaded(); // For delayed loaded images stored externally
916  ASSERT_(img!=NULL);
917  return static_cast<unsigned int >( ((IplImage*)img)->nChannels );
918 #else
919  return 0;
920 #endif
921 }
922 
923 
924 /*---------------------------------------------------------------
925  isOriginTopLeft
926  ---------------------------------------------------------------*/
928 {
929 #if MRPT_HAS_OPENCV
930  makeSureImageIsLoaded(); // For delayed loaded images stored externally
931  ASSERT_(img!=NULL);
932  return ((IplImage*)img)->origin == 0;
933 #else
934  THROW_EXCEPTION("MRPT compiled without OpenCV")
935 #endif
936 }
937 
938 
939 /*---------------------------------------------------------------
940  getAsFloat
941  ---------------------------------------------------------------*/
943  unsigned int col,
944  unsigned int row,
945  unsigned int channel) const
946 {
947  makeSureImageIsLoaded(); // For delayed loaded images stored externally
948  // [0,255]->[0,1]
949  return (*(*this)(col,row,channel)) / 255.0f;
950 }
951 
952 /*---------------------------------------------------------------
953  getAsFloat
954  ---------------------------------------------------------------*/
956  unsigned int col,
957  unsigned int row) const
958 {
959  // Is a RGB image??
960  if (isColor())
961  {
962  // Luminance: Y = 0.3R + 0.59G + 0.11B
963  unsigned char *pixels = (*this)(col,row,0);
964  return (pixels[0] * 0.3f + pixels[1] *0.59f + pixels[2] * 0.11f)/255.0f;
965  }
966  else
967  {
968  // [0,255]->[0,1]
969  return (*(*this)(col,row,0 /* Channel 0:Gray level */)) / 255.0f;
970  }
971 }
972 
973 /*---------------------------------------------------------------
974  getMaxAsFloat
975  ---------------------------------------------------------------*/
977 {
978  int x,y,cx = getWidth(), cy = getHeight();
979 
980  float maxPixel = 0;
981 
982  for (x=0;x<cx;x++)
983  for (y=0;y<cy;y++)
984  maxPixel = max( maxPixel, getAsFloat(x,y) );
985 
986  return maxPixel;
987 }
988 
989 /*---------------------------------------------------------------
990  grayscale
991  ---------------------------------------------------------------*/
993 {
994  CImage ret;
995  grayscale(ret);
996  return ret;
997 }
998 
999 // Auxiliary function for both ::grayscale() and ::grayscaleInPlace()
1000 #if MRPT_HAS_OPENCV
1001 IplImage *ipl_to_grayscale(const IplImage * img_src)
1002 {
1003  IplImage * img_dest = cvCreateImage( cvSize(img_src->width,img_src->height),IPL_DEPTH_8U, 1 );
1004  img_dest->origin = img_src->origin;
1005 
1006  // If possible, use SSE optimized version:
1007 #if MRPT_HAS_SSE3
1008  if (is_aligned<16>(img_src->imageData) &&
1009  (img_src->width & 0xF) == 0 &&
1010  img_src->widthStep==img_src->width*img_src->nChannels &&
1011  img_dest->widthStep==img_dest->width*img_dest->nChannels )
1012  {
1013  ASSERT_(is_aligned<16>(img_dest->imageData))
1014  image_SSSE3_bgr_to_gray_8u( (const uint8_t*)img_src->imageData, (uint8_t*)img_dest->imageData, img_src->width,img_src->height);
1015  return img_dest;
1016  }
1017 #endif
1018 
1019  // OpenCV Method:
1020  cvCvtColor( img_src, img_dest, CV_BGR2GRAY );
1021  return img_dest;
1022 }
1023 #endif
1024 
1025 /*---------------------------------------------------------------
1026  grayscale
1027  ---------------------------------------------------------------*/
1028 void CImage::grayscale( CImage &ret ) const
1029 {
1030 #if MRPT_HAS_OPENCV
1031  // The image is already grayscale??
1032  makeSureImageIsLoaded(); // For delayed loaded images stored externally
1033  const IplImage *ipl = this->getAs<const IplImage>();
1034  ASSERT_(ipl)
1035 
1036  if (ipl->nChannels==1)
1037  {
1038  ret = *this;
1039  return;
1040  }
1041  else
1042  {
1043  // Convert to a single luminance channel image
1045  }
1046 #endif
1047 }
1048 
1049 /*---------------------------------------------------------------
1050  grayscaleInPlace
1051  ---------------------------------------------------------------*/
1053 {
1054 #if MRPT_HAS_OPENCV
1055  makeSureImageIsLoaded(); // For delayed loaded images stored externally
1056  const IplImage *ipl = this->getAs<const IplImage>();
1057  ASSERT_(ipl)
1058  if (ipl->nChannels==1) return; // Already done.
1059 
1061 #endif
1062 }
1063 
1064 
1065 /*---------------------------------------------------------------
1066  scaleHalf
1067  ---------------------------------------------------------------*/
1068 void CImage::scaleHalf(CImage &out)const
1069 {
1070 #if MRPT_HAS_OPENCV
1071  makeSureImageIsLoaded(); // For delayed loaded images stored externally
1072  ASSERT_(img!=NULL)
1073 
1074  // Get this image size:
1075  const IplImage * img_src = ((IplImage*)img);
1076  const int w = img_src->width;
1077  const int h = img_src->height;
1078 
1079  // Create target image:
1080  IplImage * img_dest = cvCreateImage( cvSize(w>>1,h>>1),IPL_DEPTH_8U, img_src->nChannels );
1081  img_dest->origin = img_src->origin;
1082  memcpy(img_dest->colorModel,img_src->colorModel,4);
1083  memcpy(img_dest->channelSeq,img_src->channelSeq,4);
1084  img_dest->dataOrder=img_src->dataOrder;
1085 
1086 
1087  // If possible, use SSE optimized version:
1088 #if MRPT_HAS_SSE3
1089  if (img_src->nChannels==3 &&
1090  is_aligned<16>(img_src->imageData) &&
1091  is_aligned<16>(img_dest->imageData) &&
1092  (w & 0xF) == 0 &&
1093  img_src->widthStep==img_src->width*img_src->nChannels &&
1094  img_dest->widthStep==img_dest->width*img_dest->nChannels )
1095  {
1096  image_SSSE3_scale_half_3c8u( (const uint8_t*)img_src->imageData, (uint8_t*)img_dest->imageData, w,h);
1097  out.setFromIplImage(img_dest);
1098  return;
1099  }
1100 #endif
1101 
1102 #if MRPT_HAS_SSE2
1103  if (img_src->nChannels==1 &&
1104  is_aligned<16>(img_src->imageData) &&
1105  is_aligned<16>(img_dest->imageData) &&
1106  (w & 0xF) == 0 &&
1107  img_src->widthStep==img_src->width*img_src->nChannels &&
1108  img_dest->widthStep==img_dest->width*img_dest->nChannels )
1109  {
1110  image_SSE2_scale_half_1c8u( (const uint8_t*)img_src->imageData, (uint8_t*)img_dest->imageData, w,h);
1111 
1112  out.setFromIplImage(img_dest);
1113  return;
1114  }
1115 #endif
1116 
1117  // Fall back to slow method:
1118  cvResize( img_src, img_dest, IMG_INTERP_NN );
1119  out.setFromIplImage(img_dest);
1120 #endif
1121 }
1122 
1123 /*---------------------------------------------------------------
1124  scaleHalfSmooth
1125  ---------------------------------------------------------------*/
1127 {
1128 #if MRPT_HAS_OPENCV
1129  makeSureImageIsLoaded(); // For delayed loaded images stored externally
1130  ASSERT_(img!=NULL)
1131 
1132  // Get this image size:
1133  const IplImage * img_src = ((IplImage*)img);
1134  const int w = img_src->width;
1135  const int h = img_src->height;
1136 
1137  // Create target image:
1138  IplImage * img_dest = cvCreateImage( cvSize(w>>1,h>>1),IPL_DEPTH_8U, img_src->nChannels );
1139  img_dest->origin = img_src->origin;
1140  memcpy(img_dest->colorModel,img_src->colorModel,4);
1141  memcpy(img_dest->channelSeq,img_src->channelSeq,4);
1142  img_dest->dataOrder=img_src->dataOrder;
1143 
1144 
1145  // If possible, use SSE optimized version:
1146 #if MRPT_HAS_SSE2
1147  if (img_src->nChannels==1 &&
1148  is_aligned<16>(img_src->imageData) &&
1149  is_aligned<16>(img_dest->imageData) &&
1150  (w & 0xF) == 0 &&
1151  img_src->widthStep==img_src->width*img_src->nChannels &&
1152  img_dest->widthStep==img_dest->width*img_dest->nChannels )
1153  {
1154  image_SSE2_scale_half_smooth_1c8u( (const uint8_t*)img_src->imageData, (uint8_t*)img_dest->imageData, w,h);
1155 
1156  out.setFromIplImage(img_dest);
1157  return;
1158  }
1159 #endif
1160 
1161  // Fall back to slow method:
1162  cvResize( img_src, img_dest, IMG_INTERP_LINEAR );
1163  out.setFromIplImage(img_dest);
1164 #endif
1165 }
1166 
1167 /*---------------------------------------------------------------
1168  scaleDouble
1169  ---------------------------------------------------------------*/
1171 {
1172  out = *this;
1173  const TImageSize siz = this->getSize();
1174  out.scaleImage(siz.x*2,siz.y*2);
1175 }
1176 
1177 /*---------------------------------------------------------------
1178  getChannelsOrder
1179  ---------------------------------------------------------------*/
1180 const char * CImage::getChannelsOrder()const
1181 {
1182 #if MRPT_HAS_OPENCV
1183  makeSureImageIsLoaded(); // For delayed loaded images stored externally
1184  ASSERT_(img);
1185  return ((IplImage*)img)->channelSeq;
1186 #else
1187  THROW_EXCEPTION("MRPT compiled without OpenCV")
1188 #endif
1189 }
1190 
1191 
1192 /*---------------------------------------------------------------
1193  loadFromMemoryBuffer
1194  ---------------------------------------------------------------*/
1196  unsigned int width,
1197  unsigned int height,
1198  unsigned int bytesPerRow,
1199  unsigned char *red,
1200  unsigned char *green,
1201  unsigned char *blue )
1202 {
1203 #if MRPT_HAS_OPENCV
1204  MRPT_START
1205 
1206  // Fill in the IPL structure:
1207  changeSize( width, height, 3, true );
1208 
1209  // Copy the image data:
1210  for (unsigned int y=0;y<height;y++)
1211  {
1212  // The target pixels:
1213  unsigned char *dest = (unsigned char *)((IplImage*)img)->imageData + ((IplImage*)img)->widthStep * y;
1214 
1215  // Source channels:
1216  unsigned char *srcR = red + bytesPerRow * y;
1217  unsigned char *srcG = green + bytesPerRow * y;
1218  unsigned char *srcB = blue + bytesPerRow * y;
1219 
1220  for (unsigned int x=0;x<width;x++)
1221  {
1222  *(dest++) = *(srcB++);
1223  *(dest++) = *(srcG++);
1224  *(dest++) = *(srcR++);
1225  } // end of x
1226  } // end of y
1227 
1228  MRPT_END
1229 #endif
1230 }
1231 
1232 
1233 /*---------------------------------------------------------------
1234  setOriginTopLeft
1235  ---------------------------------------------------------------*/
1237 {
1238 #if MRPT_HAS_OPENCV
1239  makeSureImageIsLoaded(); // For delayed loaded images stored externally
1240  ASSERT_(img);
1241  ((IplImage*)img)->origin = val ? 0:1;
1242 #endif
1243 }
1244 
1245 /*---------------------------------------------------------------
1246  setPixel
1247  ---------------------------------------------------------------*/
1249  int x,
1250  int y,
1251  size_t color)
1252 {
1253 #if MRPT_HAS_OPENCV
1254 
1255 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG)
1256  MRPT_START
1257 #endif
1258 
1259  makeSureImageIsLoaded(); // For delayed loaded images stored externally
1260 
1261  IplImage *ipl = ((IplImage*)img);
1262 
1263 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG)
1264  ASSERT_(ipl);
1265 #endif
1266 
1267  if (x>=0 && y>=0 && y<ipl->height && x<ipl->width)
1268  {
1269  // The pixel coordinates is valid:
1270  if (ipl->nChannels==1)
1271  {
1272  *( (unsigned char*) &ipl->imageData [ y * ipl->widthStep + x ] ) = (unsigned char) color;
1273  }
1274  else
1275  {
1276 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG)
1277  ASSERT_( ipl->nChannels ==3 );
1278  if ( ipl->dataOrder!=0 )
1279  THROW_EXCEPTION("Please, use interleaved images like normal people!!! :-)");
1280 #endif
1281  unsigned char *dest = (unsigned char*) &ipl->imageData[ y * ipl->widthStep + 3*x ];
1282  unsigned char *src = (unsigned char*) &color;
1283 
1284  // Copy the color:
1285  *dest++ = *src++; // R
1286  *dest++ = *src++; // G
1287  *dest++ = *src++; // B
1288  }
1289  }
1290 
1291 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG)
1292  MRPT_END
1293 #endif
1294 
1295 #endif
1296 }
1297 
1298 /*---------------------------------------------------------------
1299  line
1300  ---------------------------------------------------------------*/
1302  int x0,
1303  int y0,
1304  int x1,
1305  int y1,
1306  const mrpt::utils::TColor color,
1307  unsigned int width,
1308  TPenStyle penStyle)
1309 {
1310 #if MRPT_HAS_OPENCV
1311  MRPT_UNUSED_PARAM(penStyle);
1312  makeSureImageIsLoaded(); // For delayed loaded images stored externally
1313  IplImage *ipl = ((IplImage*)img);
1314  ASSERT_(ipl);
1315 
1316  cvLine(ipl, cvPoint(x0,y0), cvPoint(x1,y1), CV_RGB(color.R,color.G,color.B), width );
1317 #endif
1318 }
1319 
1320 /*---------------------------------------------------------------
1321  drawCircle
1322  ---------------------------------------------------------------*/
1324  int x,
1325  int y,
1326  int radius,
1327  const mrpt::utils::TColor &color,
1328  unsigned int width)
1329 {
1330 #if MRPT_HAS_OPENCV
1331  makeSureImageIsLoaded(); // For delayed loaded images stored externally
1332  IplImage *ipl = ((IplImage*)img);
1333  ASSERT_(ipl);
1334 
1335  cvCircle( ipl, cvPoint(x,y), radius, CV_RGB (color.R,color.G,color.B), width );
1336 #endif
1337 } // end
1338 
1339 /*---------------------------------------------------------------
1340  update_patch
1341  --------------------------------------------------------------*/
1342 void CImage::update_patch(const CImage &patch,
1343  const unsigned int col_,
1344  const unsigned int row_)
1345 {
1346 #if MRPT_HAS_OPENCV
1347  IplImage *ipl_int = ((IplImage*)img);
1348  IplImage *ipl_ext = ((IplImage*)patch.img);
1349  ASSERT_(ipl_int);
1350  ASSERT_(ipl_ext);
1351  // We check that patch do not jut out of the image.
1352  if(row_+ipl_ext->height > getHeight() || col_+ipl_ext->width > getWidth())
1353  {
1354  THROW_EXCEPTION("Error : Patch jut out of image")
1355  }
1356  for (unsigned int i=0;i<patch.getHeight();i++)
1357  {
1358  memcpy( &ipl_int->imageData[(i+row_) * ipl_int->widthStep + col_ * ipl_int->nChannels],
1359  &ipl_ext->imageData[i * ipl_ext->widthStep ],
1360  ipl_ext->widthStep);
1361  }
1362 #endif
1363 }
1364 
1365 /*---------------------------------------------------------------
1366  extract_patch
1367  ---------------------------------------------------------------*/
1369  CImage &patch,
1370  const unsigned int col_,
1371  const unsigned int row_,
1372  const unsigned int col_num,
1373  const unsigned int row_num)const
1374 {
1375 #if MRPT_HAS_OPENCV
1376  makeSureImageIsLoaded(); // For delayed loaded images stored externally
1377 
1378  IplImage *ipl_int = ((IplImage*)img);
1379  ASSERT_(ipl_int);
1380 
1381  if ((ipl_int->width<(int)(col_+col_num)) || (ipl_int->height<(int)(row_+row_num)))
1382  {
1383  THROW_EXCEPTION( format("Trying to extract patch out of image boundaries: Image size=%ix%i, Patch size=%ux%u, extraction location=(%u,%u)",ipl_int->width,ipl_int->height, col_num, row_num, col_, row_ ) )
1384  }
1385 
1386  patch.resize(col_num,row_num,((IplImage*)img)->nChannels,true);
1387  IplImage *ipl_ext = ((IplImage*)patch.img);
1388  ASSERT_(ipl_ext);
1389 
1390  for (unsigned int i=0;i<row_num;i++)
1391  {
1392  memcpy( &ipl_ext->imageData[i * ipl_ext->widthStep ],
1393  &ipl_int->imageData[(i+row_) * ipl_int->widthStep + col_ * ipl_int->nChannels],
1394  ipl_ext->widthStep);
1395  }
1396 
1397 #endif
1398 }
1399 
1400 /*---------------------------------------------------------------
1401  correlate
1402  ---------------------------------------------------------------*/
1403 float CImage::correlate(const CImage &img2,int width_init,int height_init)const
1404 {
1405 #if MRPT_HAS_OPENCV
1406  makeSureImageIsLoaded(); // For delayed loaded images stored externally
1407 
1408  if ((img2.getWidth()+width_init>getWidth())|(img2.getHeight()+ height_init>getHeight()))
1409  THROW_EXCEPTION("Correlation Error!, image to correlate out of bounds");
1410 
1411  unsigned int i,j;
1412  float x1,x2;
1413  float syy=0.0f, sxy=0.0f, sxx=0.0f, m1=0.0f, m2=0.0f ,n=(float)(img2.getHeight()*img2.getWidth());
1414 // IplImage *ipl1 = (*this).img;
1415 // IplImage *ipl2 = img2.img;
1416 
1417  //find the means
1418  for (i=0;i<img2.getHeight();i++)
1419  {
1420  for (j=0;j<img2.getWidth();j++)
1421  {
1422  m1 += *(*this)(j+width_init,i+height_init);//(double)(ipl1->imageData[i*ipl1->widthStep + j ]);
1423  m2 += *img2(j,i); //(double)(ipl2->imageData[i*ipl2->widthStep + j ]);
1424  }//[ row * ipl->widthStep + col * ipl->nChannels + channel ];
1425  }
1426  m1 /= n;
1427  m2 /= n;
1428 
1429  for (i=0;i<img2.getHeight();i++)
1430  {
1431  for (j=0;j<img2.getWidth();j++)
1432  {
1433  x1 = *(*this)(j+width_init,i+height_init) - m1;//(double)(ipl1->imageData[i*ipl1->widthStep + j]) - m1;
1434  x2 = *img2(j,i) - m2;//(double)(ipl2->imageData[i*ipl2->widthStep + j]) - m2;
1435  sxx += x1*x1;
1436  syy += x2*x2;
1437  sxy += x1*x2;
1438  }
1439  }
1440 
1441  return sxy / sqrt(sxx * syy);
1442 #else
1443  return 0;
1444 #endif
1445 }
1446 
1447 
1448 /*---------------------------------------------------------------
1449  cross_correlation
1450  ---------------------------------------------------------------*/
1452  const CImage &patch_img,
1453  size_t &x_max,
1454  size_t &y_max,
1455  double &max_val,
1456  int x_search_ini,
1457  int y_search_ini,
1458  int x_search_size,
1459  int y_search_size,
1460  CImage *out_corr_image)const
1461 {
1462  MRPT_START
1463 
1464  makeSureImageIsLoaded(); // For delayed loaded images stored externally
1465 
1466 #if MRPT_HAS_OPENCV
1467  double mini;
1468  CvPoint min_point,max_point;
1469 
1470  bool entireImg = (x_search_ini<0 || y_search_ini<0 || x_search_size<0 || y_search_size<0);
1471 
1472  const IplImage *im, *patch_im;
1473 
1474  if( this->isColor() && patch_img.isColor() )
1475  {
1476  const IplImage *im_ = this->getAs<IplImage>();
1477  const IplImage *patch_im_ = patch_img.getAs<IplImage>();
1478 
1479  IplImage *aux = cvCreateImage( cvGetSize( im_ ), 8, 1 );
1480  IplImage *aux2 = cvCreateImage( cvGetSize( patch_im_ ), 8, 1 );
1481  cvCvtColor( im_, aux, CV_BGR2GRAY );
1482  cvCvtColor( patch_im_, aux2, CV_BGR2GRAY );
1483  im = aux;
1484  patch_im = aux2;
1485  }
1486  else
1487  {
1488  im = this->getAs<IplImage>();
1489  patch_im = patch_img.getAs<IplImage>();
1490  }
1491 
1492  if (entireImg)
1493  {
1494  x_search_size = im->width - patch_im->width;
1495  y_search_size = im->height - patch_im->height;
1496  }
1497 
1498  // JLBC: Perhaps is better to raise the exception always??
1499  if ((x_search_ini + x_search_size + patch_im->width-1)>im->width)
1500  x_search_size -= (x_search_ini + x_search_size + patch_im->width-1) - im->width;
1501 
1502  if ((y_search_ini + y_search_size + patch_im->height-1)>im->height)
1503  y_search_size -= (y_search_ini + y_search_size + patch_im->height-1) - im->height;
1504 
1505  ASSERT_( (x_search_ini + x_search_size + patch_im->width-1)<=im->width )
1506  ASSERT_( (y_search_ini + y_search_size + patch_im->height-1)<=im->height )
1507 
1508  IplImage *result = cvCreateImage(cvSize(x_search_size+1,y_search_size+1),IPL_DEPTH_32F, 1);
1509 
1510  const IplImage *ipl_ext;
1511 
1512  if (!entireImg)
1513  {
1514  IplImage *aux= cvCreateImage(cvSize(patch_im->width+x_search_size,patch_im->height+y_search_size),IPL_DEPTH_8U, 1);
1515  for (unsigned int i = 0 ; i < (unsigned int)y_search_size ; i++)
1516  {
1517  memcpy( &aux->imageData[i * aux->widthStep ],
1518  &im->imageData[(i+y_search_ini) * im->widthStep + x_search_ini * im->nChannels],
1519  aux->width * aux->nChannels ); //widthStep); <-- JLBC: widthstep SHOULD NOT be used as the length of each row (the last one may be shorter!!)
1520  }
1521  ipl_ext = aux;
1522  }
1523  else
1524  {
1525  ipl_ext = im;
1526  }
1527 
1528  // Compute cross correlation:
1529  cvMatchTemplate(ipl_ext,patch_im,result,CV_TM_CCORR_NORMED);
1530  //cvMatchTemplate(ipl_ext,patch_im,result,CV_TM_CCOEFF_NORMED);
1531 
1532  // Find the max point:
1533  cvMinMaxLoc(result,&mini,&max_val,&min_point,&max_point,NULL);
1534  x_max = max_point.x+x_search_ini+(round(patch_im->width-1)/2);
1535  y_max = max_point.y+y_search_ini+(round(patch_im->height-1)/2);
1536 
1537  // Free memory:
1538  if (!entireImg) {
1539  IplImage *aux = const_cast<IplImage*>(ipl_ext);
1540  cvReleaseImage( &aux );
1541  ipl_ext=NULL;
1542  }
1543 
1544  // Leave output image?
1545  if (out_corr_image)
1546  out_corr_image->setFromIplImage(result);
1547  else
1548  cvReleaseImage( &result );
1549 #else
1550  THROW_EXCEPTION("The MRPT has been compiled with MRPT_HAS_OPENCV=0 !");
1551 #endif
1552 
1553  MRPT_END
1554 }
1555 
1556 
1557 /*---------------------------------------------------------------
1558  normalize
1559  ---------------------------------------------------------------*/
1561 {
1562 #if MRPT_HAS_OPENCV
1563  makeSureImageIsLoaded(); // For delayed loaded images stored externally
1564  IplImage *ipl = getAs<IplImage>(); // Source Image
1565  ASSERT_(ipl)
1566  ASSERTMSG_( ipl->nChannels==1, "CImage::normalize() only defined for grayscale images.")
1567 
1568  uint8_t min_=255,max_=1;
1569  for (int y=0;y<ipl->height;y++)
1570  {
1571  const uint8_t *ptr = reinterpret_cast<const uint8_t*>( ipl->imageData + y*ipl->widthStep );
1572  for (int x=0;x<ipl->width;x++)
1573  {
1574  const uint8_t val = *ptr++;
1575  if (min_ > val) min_=val;
1576  if (max_ < val) max_=val;
1577  }
1578  }
1579 
1580  // Compute scale factor & build convert look-up-table:
1581  const double s=255.0/((double)max_-(double)min_);
1582  uint8_t lut[256];
1583  for (int v=0;v<256;v++) lut[v] = static_cast<uint8_t>( (v-min_)*s );
1584 
1585  // Apply LUT:
1586  for (int y=0;y<ipl->height;y++)
1587  {
1588  uint8_t *ptr = reinterpret_cast<uint8_t*>( ipl->imageData + y*ipl->widthStep );
1589  for (int x=0;x<ipl->width;x++)
1590  {
1591  *ptr = lut[*ptr];
1592  ptr++;
1593  }
1594  }
1595 #endif
1596 }
1597 
1598 /*---------------------------------------------------------------
1599  getAsMatrix
1600  ---------------------------------------------------------------*/
1602  CMatrixFloat &outMatrix,
1603  bool doResize,
1604  int x_min,
1605  int y_min,
1606  int x_max,
1607  int y_max
1608  ) const
1609 {
1610 #if MRPT_HAS_OPENCV
1611  MRPT_START
1612 
1613  makeSureImageIsLoaded(); // For delayed loaded images stored externally
1614  ASSERT_(img);
1615 
1616  // Set sizes:
1617  if (x_max==-1) x_max=((IplImage*)img)->width-1;
1618  if (y_max==-1) y_max=((IplImage*)img)->height-1;
1619 
1620  ASSERT_(x_min>=0 && x_min<((IplImage*)img)->width && x_min<x_max);
1621  ASSERT_(y_min>=0 && y_min<((IplImage*)img)->height && y_min<y_max);
1622 
1623  int lx = (x_max-x_min+1);
1624  int ly = (y_max-y_min+1);
1625 
1626  if (doResize || (int)outMatrix.getRowCount()<ly || (int)outMatrix.getColCount()<lx)
1627  outMatrix.setSize( y_max-y_min+1,x_max-x_min+1 );
1628 
1629  if (isColor())
1630  {
1631  // Luminance: Y = 0.3R + 0.59G + 0.11B
1632  for (int y=0;y<ly;y++)
1633  {
1634  unsigned char *pixels = this->get_unsafe(x_min,y_min+y,0);
1635  float aux;
1636  for (int x=0;x<lx;x++)
1637  {
1638  aux = *pixels++ * 0.3f*(1.0f/255);
1639  aux += *pixels++ * 0.59f*(1.0f/255);
1640  aux += *pixels++ * 0.11f*(1.0f/255);
1641  outMatrix.set_unsafe(y,x, aux);
1642  }
1643  }
1644  }
1645  else
1646  {
1647  for (int y=0;y<ly;y++)
1648  {
1649  unsigned char *pixels = this->get_unsafe(x_min,y_min+y,0);
1650  for (int x=0;x<lx;x++)
1651  outMatrix.set_unsafe(y,x, (*pixels++)*(1.0f/255) );
1652  }
1653  }
1654 
1655  MRPT_END
1656 #endif
1657 }
1658 
1659 /*---------------------------------------------------------------
1660  getAsRGBMatrices
1661  ---------------------------------------------------------------*/
1663  mrpt::math::CMatrixFloat &outMatrixR,
1664  mrpt::math::CMatrixFloat &outMatrixG,
1665  mrpt::math::CMatrixFloat &outMatrixB,
1666  bool doResize,
1667  int x_min,
1668  int y_min,
1669  int x_max,
1670  int y_max
1671  ) const
1672 {
1673 #if MRPT_HAS_OPENCV
1674  MRPT_START
1675 
1676  makeSureImageIsLoaded(); // For delayed loaded images stored externally
1677  ASSERT_(img);
1678 
1679  // Set sizes:
1680  if (x_max==-1) x_max=((IplImage*)img)->width-1;
1681  if (y_max==-1) y_max=((IplImage*)img)->height-1;
1682 
1683  ASSERT_(x_min>=0 && x_min<((IplImage*)img)->width && x_min<x_max);
1684  ASSERT_(y_min>=0 && y_min<((IplImage*)img)->height && y_min<y_max);
1685 
1686  int lx = (x_max-x_min+1);
1687  int ly = (y_max-y_min+1);
1688 
1689  if (doResize || (int)outMatrixR.getRowCount()<ly || (int)outMatrixR.getColCount()<lx)
1690  outMatrixR.setSize( y_max-y_min+1,x_max-x_min+1 );
1691  if (doResize || (int)outMatrixG.getRowCount()<ly || (int)outMatrixG.getColCount()<lx)
1692  outMatrixG.setSize( y_max-y_min+1,x_max-x_min+1 );
1693  if (doResize || (int)outMatrixB.getRowCount()<ly || (int)outMatrixB.getColCount()<lx)
1694  outMatrixB.setSize( y_max-y_min+1,x_max-x_min+1 );
1695 
1696  if (isColor())
1697  {
1698  for (int y=0;y<ly;y++)
1699  {
1700  unsigned char *pixels = this->get_unsafe(x_min,y_min+y,0);
1701  float aux;
1702  for (int x=0;x<lx;x++)
1703  {
1704  aux = *pixels++ * (1.0f/255);
1705  outMatrixR.set_unsafe(y,x, aux);
1706  aux = *pixels++ * (1.0f/255);
1707  outMatrixG.set_unsafe(y,x, aux);
1708  aux = *pixels++ * (1.0f/255);
1709  outMatrixB.set_unsafe(y,x, aux);
1710 
1711  }
1712  }
1713  }
1714  else
1715  {
1716  for (int y=0;y<ly;y++)
1717  {
1718  unsigned char *pixels = this->get_unsafe(x_min,y_min+y,0);
1719  for (int x=0;x<lx;x++)
1720  {
1721  outMatrixR.set_unsafe(y,x, (*pixels)*(1.0f/255) );
1722  outMatrixG.set_unsafe(y,x, (*pixels)*(1.0f/255) );
1723  outMatrixB.set_unsafe(y,x, (*pixels++)*(1.0f/255) );
1724  }
1725  }
1726  }
1727 
1728  MRPT_END
1729 #endif
1730 }
1731 
1732 
1733 /*---------------------------------------------------------------
1734  cross_correlation_FFT
1735  ---------------------------------------------------------------*/
1737  const CImage &in_img,
1738  CMatrixFloat &out_corr,
1739  int u_search_ini,
1740  int v_search_ini,
1741  int u_search_size,
1742  int v_search_size,
1743  float biasThisImg,
1744  float biasInImg ) const
1745 {
1746  MRPT_START
1747 
1748  makeSureImageIsLoaded(); // For delayed loaded images stored externally
1749  ASSERT_(img);
1750 
1751  // Set limits:
1752  if (u_search_ini==-1) u_search_ini=0;
1753  if (v_search_ini==-1) v_search_ini=0;
1754  if (u_search_size==-1) u_search_size=getWidth();
1755  if (v_search_size==-1) v_search_size=getHeight();
1756 
1757  int u_search_end = u_search_ini + u_search_size-1;
1758  int v_search_end = v_search_ini + v_search_size-1;
1759 
1760  ASSERT_(u_search_end<(int)getWidth());
1761  ASSERT_(v_search_end<(int)getHeight());
1762 
1763  // Find smallest valid size:
1764  size_t x,y;
1765  size_t actual_lx = max( u_search_size,(int)in_img.getWidth());
1766  size_t actual_ly = max( v_search_size,(int)in_img.getHeight());
1767  size_t lx = math::round2up( actual_lx );
1768  size_t ly = math::round2up( actual_ly );
1769 
1770 // printf("ly=%u lx=%u\n",ly,lx);
1771 
1772  CMatrix i1(ly,lx),i2(ly,lx);
1773 
1774  // We fill the images with the bias, such as when we substract the bias later on,
1775  // those pixels not really occupied by the image really becomes zero:
1776  i1.fill(biasInImg);
1777  i2.fill(biasThisImg);
1778 
1779  // Get as matrixes, padded with zeros up to power-of-two sizes:
1780  getAsMatrix(
1781  i2,
1782  false,
1783  u_search_ini,
1784  v_search_ini,
1785  u_search_ini+u_search_size-1,
1786  v_search_ini+v_search_size-1 );
1787  in_img.getAsMatrix(
1788  i1,
1789  false);
1790 
1791  // Remove the bias now:
1792  i2.array() -= biasThisImg;
1793  i1.array() -= biasInImg;
1794 
1795  // Fill the "padded zeros" with copies of the images:
1796 // SAVE_MATRIX(i1); SAVE_MATRIX(i2);
1797 
1798  // FFT:
1799  CMatrix I1_R,I1_I,I2_R,I2_I,ZEROS(ly,lx);
1800  math::dft2_complex(i1,ZEROS,I1_R,I1_I);
1801  math::dft2_complex(i2,ZEROS,I2_R,I2_I);
1802 
1803 // SAVE_MATRIX(I1_R); SAVE_MATRIX(I1_I);
1804 // SAVE_MATRIX(I2_R); SAVE_MATRIX(I2_I);
1805 
1806  // Compute the COMPLEX division of I2 by I1:
1807  for (y = 0;y<ly;y++)
1808  for (x = 0;x<lx;x++)
1809  {
1810  float r1 = I1_R.get_unsafe(y,x);
1811  float r2 = I2_R.get_unsafe(y,x);
1812 
1813  float ii1 = I1_I.get_unsafe(y,x);
1814  float ii2 = I2_I.get_unsafe(y,x);
1815 
1816  float den = square(r1)+square(ii1);
1817  I2_R.set_unsafe(y,x, (r1*r2+ii1*ii2)/den);
1818  I2_I.set_unsafe(y,x, (ii2*r1-r2*ii1)/den);
1819  }
1820 
1821 // I2_R.saveToTextFile("DIV_R.txt");
1822 // I2_I.saveToTextFile("DIV_I.txt");
1823 
1824  // IFFT:
1825  CMatrix res_R,res_I;
1826  math::idft2_complex(I2_R,I2_I,res_R,res_I);
1827 
1828  out_corr.setSize(actual_ly,actual_lx);
1829  for (y = 0;y<actual_ly;y++)
1830  for (x = 0;x<actual_lx;x++)
1831  out_corr(y,x) = sqrt( square(res_R(y,x)) + square(res_I(y,x)) );
1832 
1833  MRPT_END
1834 }
1835 
1836 
1837 /*---------------------------------------------------------------
1838  getAsMatrixTiled
1839  ---------------------------------------------------------------*/
1840 void CImage::getAsMatrixTiled( CMatrix &outMatrix ) const
1841 {
1842 #if MRPT_HAS_OPENCV
1843  MRPT_START
1844 
1845  makeSureImageIsLoaded(); // For delayed loaded images stored externally
1846  ASSERT_(img);
1847 
1848  // The size of the matrix:
1849  size_t matrix_lx = outMatrix.getColCount();
1850  size_t matrix_ly = outMatrix.getRowCount();
1851 
1852  if (isColor())
1853  {
1854  // Luminance: Y = 0.3R + 0.59G + 0.11B
1855  for (unsigned int y=0;y<matrix_ly;y++)
1856  {
1857  unsigned char *min_pixels = (*this)(0,y % ((IplImage*)img)->height,0);
1858  unsigned char *max_pixels = min_pixels + ((IplImage*)img)->width*3;
1859  unsigned char *pixels = min_pixels;
1860  float aux;
1861  for (unsigned int x=0;x<matrix_lx;x++)
1862  {
1863  aux = *pixels++ * 0.30f;
1864  aux += *pixels++ * 0.59f;
1865  aux += *pixels++ * 0.11f;
1866  outMatrix.set_unsafe(y,x, aux);
1867  if (pixels>=max_pixels)
1868  pixels = min_pixels;
1869  }
1870  }
1871  }
1872  else
1873  {
1874  for (unsigned int y=0;y<matrix_ly;y++)
1875  {
1876  unsigned char *min_pixels = (*this)(0,y % ((IplImage*)img)->height,0);
1877  unsigned char *max_pixels = min_pixels + ((IplImage*)img)->width;
1878  unsigned char *pixels = min_pixels;
1879  for (unsigned int x=0;x<matrix_lx;x++)
1880  {
1881  outMatrix.set_unsafe(y,x, *pixels++ );
1882  if (pixels>=max_pixels) pixels = min_pixels;
1883  }
1884  }
1885  }
1886 
1887  MRPT_END
1888 #endif
1889 }
1890 
1891 
1892 /*---------------------------------------------------------------
1893  setExternalStorage
1894  ---------------------------------------------------------------*/
1896 {
1897  releaseIpl();
1898  m_externalFile = fileName;
1899  m_imgIsExternalStorage = true;
1900 }
1901 
1902 /*---------------------------------------------------------------
1903  unload
1904  ---------------------------------------------------------------*/
1906 {
1908  const_cast<CImage*>(this)->releaseIpl( true ); // Do NOT mark the image as NON external
1909 }
1910 
1911 /*---------------------------------------------------------------
1912  releaseIpl
1913  ---------------------------------------------------------------*/
1914 void CImage::releaseIpl(bool thisIsExternalImgUnload) MRPT_NO_THROWS
1915 {
1916 #if MRPT_HAS_OPENCV
1917  if (img && !m_imgIsReadOnly)
1918  {
1919  IplImage *ptr=(IplImage*)img;
1920  cvReleaseImage( &ptr );
1921  }
1922  img = NULL;
1923  m_imgIsReadOnly = false;
1924  if (!thisIsExternalImgUnload)
1925  {
1926  m_imgIsExternalStorage = false;
1927  m_externalFile = string();
1928  }
1929 #endif
1930 }
1931 
1932 /*---------------------------------------------------------------
1933  makeSureImageIsLoaded
1934  ---------------------------------------------------------------*/
1936 {
1937  if (img!=NULL) return; // OK, continue
1938 
1940  {
1941  // Load the file:
1942  string wholeFile;
1944 
1945  const std::string tmpFile = m_externalFile;
1946 
1947  bool ret = const_cast<CImage*>(this)->loadFromFile(wholeFile);
1948 
1949  // These are removed by "loadFromFile", and that's good, just fix it here and carry on.
1950  m_imgIsExternalStorage = true;
1951  m_externalFile = tmpFile;
1952 
1953  if (!ret)
1954  THROW_TYPED_EXCEPTION_FMT(CExceptionExternalImageNotFound,"Error loading externally-stored image from: %s", wholeFile.c_str());
1955  }
1956  else THROW_EXCEPTION("img is NULL in a non-externally stored image.");
1957 }
1958 
1959 /*---------------------------------------------------------------
1960  getExternalStorageFileAbsolutePath
1961  ---------------------------------------------------------------*/
1963 {
1964  ASSERT_(m_externalFile.size()>2);
1965 
1966  if (m_externalFile[0]=='/' || ( m_externalFile[1]==':' && m_externalFile[2]=='\\' ) )
1967  {
1968  out_path= m_externalFile;
1969  }
1970  else
1971  {
1972  out_path = IMAGES_PATH_BASE;
1973 
1974  size_t N=IMAGES_PATH_BASE.size()-1;
1975  if (IMAGES_PATH_BASE[N]!='/' && IMAGES_PATH_BASE[N]!='\\' )
1976  out_path+= "/";
1977 
1978  out_path+= m_externalFile;
1979  }
1980 }
1981 
1982 /*---------------------------------------------------------------
1983  flipVertical
1984  ---------------------------------------------------------------*/
1985 void CImage::flipVertical(bool also_swapRB )
1986 {
1987 #if MRPT_HAS_OPENCV
1988  IplImage *ptr=(IplImage*)img;
1989  int options = CV_CVTIMG_FLIP;
1990  if(also_swapRB) options |= CV_CVTIMG_SWAP_RB;
1991  cvConvertImage(ptr,ptr,options);
1992 #endif
1993 }
1994 
1996 {
1997 #if MRPT_HAS_OPENCV
1998  IplImage *ptr=(IplImage*)img;
1999  cvFlip(ptr,nullptr,1);
2000 #endif
2001 }
2002 
2003 /*---------------------------------------------------------------
2004  swapRB
2005  ---------------------------------------------------------------*/
2007 {
2008 #if MRPT_HAS_OPENCV
2009  makeSureImageIsLoaded(); // For delayed loaded images stored externally
2010  ASSERT_(img!=NULL);
2011  IplImage *ptr=(IplImage*)img;
2012  cvConvertImage(ptr,ptr,CV_CVTIMG_SWAP_RB);
2013 #endif
2014 }
2015 
2016 /*---------------------------------------------------------------
2017  rectifyImageInPlace
2018  ---------------------------------------------------------------*/
2019 void CImage::rectifyImageInPlace( void *mapX, void *mapY )
2020 {
2021 #if MRPT_HAS_OPENCV
2022  makeSureImageIsLoaded(); // For delayed loaded images stored externally
2023  ASSERT_(img!=NULL);
2024 
2025 #if MRPT_OPENCV_VERSION_NUM<0x200
2026  THROW_EXCEPTION("This method requires OpenCV 2.0.0 or above.")
2027 #else
2028 
2029  IplImage *srcImg = getAs<IplImage>(); // Source Image
2030  IplImage *outImg = cvCreateImage( cvGetSize( srcImg ), srcImg->depth, srcImg->nChannels );
2031 
2032  cv::Mat *_mapX, *_mapY;
2033  _mapX = static_cast<cv::Mat*>(mapX);
2034  _mapY = static_cast<cv::Mat*>(mapY);
2035 
2036  IplImage _mapXX = *_mapX;
2037  IplImage _mapYY = *_mapY;
2038 
2039  cvRemap(srcImg,outImg, &_mapXX,&_mapYY,CV_INTER_CUBIC);
2040 #endif
2041 
2042  releaseIpl();
2043  img = outImg;
2044 #endif
2045 }
2046 
2047 /*---------------------------------------------------------------
2048  rectifyImageInPlace
2049  ---------------------------------------------------------------*/
2051 {
2052 #if MRPT_HAS_OPENCV
2053  makeSureImageIsLoaded(); // For delayed loaded images stored externally
2054  ASSERT_(img!=NULL);
2055  // MRPT -> OpenCV Input Transformation
2056  IplImage *srcImg = getAs<IplImage>(); // Source Image
2057  IplImage *outImg; // Output Image
2058  outImg = cvCreateImage( cvGetSize( srcImg ), srcImg->depth, srcImg->nChannels );
2059 
2060  double aux1[3][3], aux2[1][5];
2061  const CMatrixDouble33 &cameraMatrix = cameraParams.intrinsicParams;
2062 
2063  for (int i=0;i<3;i++)
2064  for (int j=0;j<3;j++)
2065  aux1[i][j] = cameraMatrix(i,j);
2066  for (int i=0;i<5;i++)
2067  aux2[0][i]=cameraParams.dist[i];
2068 
2069  CvMat inMat = cvMat( cameraMatrix.getRowCount(), cameraMatrix.getColCount(), CV_64F, aux1 );
2070  CvMat distM = cvMat( 1, 5, CV_64F, aux2 );
2071 
2072  // Remove distortion
2073  cvUndistort2( srcImg, outImg, &inMat, &distM );
2074 
2075  // Assign the output image to the IPLImage pointer within the CImage
2076  releaseIpl();
2077  img = outImg;
2078 #endif
2079 }
2080 
2081 /*---------------------------------------------------------------
2082  rectifyImage
2083  ---------------------------------------------------------------*/
2085  CImage &out_img,
2086  const mrpt::utils::TCamera &cameraParams ) const
2087 {
2088 #if MRPT_HAS_OPENCV
2089  makeSureImageIsLoaded(); // For delayed loaded images stored externally
2090  ASSERT_(img!=NULL);
2091  // MRPT -> OpenCV Input Transformation
2092  const IplImage *srcImg = getAs<IplImage>(); // Source Image
2093  IplImage *outImg; // Output Image
2094  outImg = cvCreateImage( cvGetSize( srcImg ), srcImg->depth, srcImg->nChannels );
2095 
2096  double aux1[3][3], aux2[1][5];
2097  const CMatrixDouble33 &cameraMatrix = cameraParams.intrinsicParams;
2098 
2099  for (int i=0;i<3;i++)
2100  for (int j=0;j<3;j++)
2101  aux1[i][j] = cameraMatrix(i,j);
2102  for (int i=0;i<5;i++)
2103  aux2[0][i]=cameraParams.dist[i];
2104 
2105  CvMat inMat = cvMat( cameraMatrix.getRowCount(), cameraMatrix.getColCount(), CV_64F, aux1 );
2106  CvMat distM = cvMat( 1, 5, CV_64F, aux2 );
2107 
2108  // Remove distortion
2109  cvUndistort2( srcImg, outImg, &inMat, &distM );
2110 
2111  // OpenCV -> MRPT Output Transformation
2112  out_img.loadFromIplImage( outImg );
2113 
2114  // Release Output Image
2115  cvReleaseImage( &outImg );
2116 #endif
2117 } // end CImage::rectifyImage
2118 
2119 
2120 /*---------------------------------------------------------------
2121  filterMedian
2122  ---------------------------------------------------------------*/
2123 void CImage::filterMedian( CImage &out_img, int W ) const
2124 {
2125 #if MRPT_HAS_OPENCV
2126  makeSureImageIsLoaded(); // For delayed loaded images stored externally
2127  ASSERT_(img!=NULL);
2128  // MRPT -> OpenCV Input Transformation
2129  const IplImage *srcImg = getAs<IplImage>(); // Source Image
2130  IplImage *outImg; // Output Image
2131  outImg = cvCreateImage( cvGetSize( srcImg ), srcImg->depth, srcImg->nChannels );
2132 
2133  // Filter
2134  cvSmooth( srcImg, outImg, CV_MEDIAN, W );
2135 
2136  outImg->origin = srcImg->origin;
2137 
2138  // OpenCV -> MRPT Output Transformation
2139  out_img.loadFromIplImage( outImg );
2140 
2141  // Release Output Image
2142  cvReleaseImage( &outImg );
2143 #endif
2144 }
2145 
2146 /*---------------------------------------------------------------
2147  filterMedian
2148  ---------------------------------------------------------------*/
2150 {
2151 #if MRPT_HAS_OPENCV
2152  makeSureImageIsLoaded(); // For delayed loaded images stored externally
2153  ASSERT_(img!=NULL);
2154  // MRPT -> OpenCV Input Transformation
2155  IplImage *srcImg = getAs<IplImage>(); // Source Image
2156  IplImage *outImg; // Output Image
2157  outImg = cvCreateImage( cvGetSize( srcImg ), srcImg->depth, srcImg->nChannels );
2158 
2159  // Filter
2160  cvSmooth( srcImg, outImg, CV_MEDIAN, W );
2161 
2162  outImg->origin = srcImg->origin;
2163 
2164  // Assign the output image to the IPLImage pointer within the CImage
2165  releaseIpl();
2166  img = outImg;
2167 #endif
2168 }
2169 
2170 /*---------------------------------------------------------------
2171  filterGaussian
2172  ---------------------------------------------------------------*/
2173 void CImage::filterGaussian( CImage &out_img, int W, int H ) const
2174 {
2175 #if MRPT_HAS_OPENCV
2176  makeSureImageIsLoaded(); // For delayed loaded images stored externally
2177  ASSERT_(img!=NULL);
2178  // MRPT -> OpenCV Input Transformation
2179  const IplImage *srcImg = getAs<IplImage>(); // Source Image
2180  IplImage *outImg; // Output Image
2181  outImg = cvCreateImage( cvGetSize( srcImg ), srcImg->depth, srcImg->nChannels );
2182 
2183  // Filter
2184  cvSmooth( srcImg, outImg, CV_GAUSSIAN, W, H );
2185 
2186  outImg->origin = srcImg->origin;
2187 
2188  // OpenCV -> MRPT Output Transformation
2189  out_img.loadFromIplImage( outImg );
2190 
2191  // Release Output Image
2192  cvReleaseImage( &outImg );
2193 #endif
2194 }
2195 
2196 /*---------------------------------------------------------------
2197  filterGaussianInPlace
2198  ---------------------------------------------------------------*/
2199 void CImage::filterGaussianInPlace( int W, int H )
2200 {
2201 #if MRPT_HAS_OPENCV
2202  makeSureImageIsLoaded(); // For delayed loaded images stored externally
2203  ASSERT_(img!=NULL);
2204  // MRPT -> OpenCV Input Transformation
2205  IplImage *srcImg = getAs<IplImage>(); // Source Image
2206  IplImage *outImg; // Output Image
2207  outImg = cvCreateImage( cvGetSize( srcImg ), srcImg->depth, srcImg->nChannels );
2208 
2209  // Filter
2210  cvSmooth( srcImg, outImg, CV_GAUSSIAN, W, H );
2211 
2212  outImg->origin = srcImg->origin;
2213 
2214  // Assign the output image to the IPLImage pointer within the CImage
2215  releaseIpl();
2216  img = outImg;
2217 #endif
2218 }
2219 
2220 
2221 /*---------------------------------------------------------------
2222  scaleImage
2223  ---------------------------------------------------------------*/
2224 void CImage::scaleImage( unsigned int width, unsigned int height, TInterpolationMethod interp )
2225 {
2226 #if MRPT_HAS_OPENCV
2227  makeSureImageIsLoaded(); // For delayed loaded images stored externally
2228  ASSERT_(img!=NULL);
2229  IplImage *srcImg = getAs<IplImage>(); // Source Image
2230 
2231  if( static_cast<unsigned int>(srcImg->width) == width && static_cast<unsigned int>(srcImg->height) == height )
2232  return;
2233 
2234  IplImage *outImg; // Output Image
2235  outImg = cvCreateImage( cvSize(width,height), srcImg->depth, srcImg->nChannels );
2236 
2237  // Resize:
2238  cvResize( srcImg, outImg, (int)interp );
2239 
2240  outImg->origin = srcImg->origin;
2241 
2242  // Assign the output image to the IPLImage pointer within the CImage
2243  releaseIpl();
2244  img = outImg;
2245 #endif
2246 }
2247 
2248 /*---------------------------------------------------------------
2249  scaleImage
2250  ---------------------------------------------------------------*/
2251 void CImage::scaleImage( CImage &out_img, unsigned int width, unsigned int height, TInterpolationMethod interp ) const
2252 {
2253 #if MRPT_HAS_OPENCV
2254  makeSureImageIsLoaded(); // For delayed loaded images stored externally
2255  ASSERT_(img!=NULL);
2256  const IplImage *srcImg = getAs<IplImage>(); // Source Image
2257 
2258  if( static_cast<unsigned int>(srcImg->width) == width && static_cast<unsigned int>(srcImg->height) == height )
2259  {
2260  // already at the required size:
2261  out_img = *this;
2262  return;
2263  }
2264 
2265  IplImage *outImg; // Output Image
2266  outImg = cvCreateImage( cvSize(width,height), srcImg->depth, srcImg->nChannels );
2267 
2268  // Resize:
2269  cvResize( srcImg, outImg, (int)interp );
2270  outImg->origin = srcImg->origin;
2271 
2272  // Assign:
2273  out_img.setFromIplImage(outImg);
2274 #endif
2275 }
2276 
2277 
2278 /*---------------------------------------------------------------
2279  rotateImage
2280  ---------------------------------------------------------------*/
2281 void CImage::rotateImage( double angle_radians, unsigned int center_x, unsigned int center_y, double scale )
2282 {
2283 #if MRPT_HAS_OPENCV
2284  makeSureImageIsLoaded(); // For delayed loaded images stored externally
2285  ASSERT_(img!=NULL);
2286 
2287  IplImage *srcImg = getAs<IplImage>(); // Source Image
2288  IplImage *outImg; // Output Image
2289  outImg = cvCreateImage( cvGetSize( srcImg ), srcImg->depth, srcImg->nChannels );
2290 
2291  // Based on the blog entry:
2292  // http://blog.weisu.org/2007/12/opencv-image-rotate-and-zoom-rotation.html
2293 
2294  // Apply rotation & scale:
2295  float m[6];
2296  CvMat M = cvMat(2, 3, CV_32F, m);
2297 
2298  m[0] = (float)(scale*cos(angle_radians));
2299  m[1] = (float)(scale*sin(angle_radians));
2300  m[3] = -m[1];
2301  m[4] = m[0];
2302  m[2] = center_x;
2303  m[5] = center_y;
2304 
2305  cvGetQuadrangleSubPix( srcImg, outImg, &M );
2306 
2307  outImg->origin = srcImg->origin;
2308 
2309  // Assign the output image to the IPLImage pointer within the CImage
2310  releaseIpl();
2311  img = outImg;
2312 
2313 #endif
2314 }
2315 
2316 
2317 /** Draw onto this image the detected corners of a chessboard. The length of cornerCoords must be the product of the two check_sizes.
2318 *
2319 * \param cornerCoords [IN] The pixel coordinates of all the corners.
2320 * \param check_size_x [IN] The number of squares, in the X direction
2321 * \param check_size_y [IN] The number of squares, in the Y direction
2322 *
2323 * \return false if the length of cornerCoords is inconsistent (nothing is drawn then).
2324 */
2326  std::vector<TPixelCoordf> &cornerCoords,
2327  unsigned int check_size_x,
2328  unsigned int check_size_y,
2329  unsigned int lines_width,
2330  unsigned int r)
2331 {
2332 #if MRPT_HAS_OPENCV
2333 
2334  if (cornerCoords.size()!=check_size_x*check_size_y) return false;
2335 
2336  IplImage* ipl = this->getAs<IplImage>();
2337 
2338  unsigned int x, y,i;
2339  CvPoint prev_pt = cvPoint(0, 0);
2340  const int line_max = 8;
2341  CvScalar line_colors[8];
2342 
2343  line_colors[0] = CV_RGB(255,0,0);
2344  line_colors[1] = CV_RGB(255,128,0);
2345  line_colors[2] = CV_RGB(255,128,0);
2346  line_colors[3] = CV_RGB(200,200,0);
2347  line_colors[4] = CV_RGB(0,255,0);
2348  line_colors[5] = CV_RGB(0,200,200);
2349  line_colors[6] = CV_RGB(0,0,255);
2350  line_colors[7] = CV_RGB(255,0,255);
2351 
2352  CCanvas::selectTextFont("10x20");
2353 
2354  for( y = 0, i = 0; y < check_size_y; y++ )
2355  {
2356  CvScalar color = line_colors[y % line_max];
2357  for( x = 0; x < check_size_x; x++, i++ )
2358  {
2359  CvPoint pt;
2360  pt.x = cvRound( cornerCoords[i].x);
2361  pt.y = cvRound( cornerCoords[i].y);
2362 
2363  if( i != 0 ) cvLine(ipl, prev_pt, pt, color, lines_width );
2364 
2365  cvLine(ipl,
2366  cvPoint( pt.x - r, pt.y - r ),
2367  cvPoint( pt.x + r, pt.y + r ), color, lines_width );
2368  cvLine(ipl,
2369  cvPoint( pt.x - r, pt.y + r),
2370  cvPoint( pt.x + r, pt.y - r), color, lines_width );
2371 
2372  if (r>0)
2373  cvCircle(ipl, pt, r+1, color );
2374  prev_pt = pt;
2375 
2376  // Text label with the corner index in the first and last corners:
2377  if (i==0 || i==cornerCoords.size()-1)
2379  }
2380  }
2381 
2382  return true;
2383 #else
2384  return false;
2385 #endif
2386 }
2387 
2388 
2389 /** Replaces this grayscale image with a RGB version of it.
2390  * \sa grayscaleInPlace
2391  */
2392 void CImage::colorImage( CImage &ret ) const
2393 {
2394 #if MRPT_HAS_OPENCV
2395  if (this->isColor()) {
2396  ret = *this;
2397  return;
2398  }
2399 
2400  const IplImage *srcImg = getAs<IplImage>(); // Source Image
2401  IplImage *outImg = cvCreateImage( cvGetSize( srcImg ), srcImg->depth, 3 );
2402 
2403  cvCvtColor( srcImg, outImg, CV_GRAY2BGR );
2404 
2405  outImg->origin = srcImg->origin;
2406 
2407  // Assign the output image to the IPLImage pointer within the CImage
2408  ret.setFromIplImage(outImg);
2409 #endif
2410 }
2411 
2412 /** Replaces this grayscale image with a RGB version of it.
2413  * \sa grayscaleInPlace
2414  */
2416 {
2417 #if MRPT_HAS_OPENCV
2418  if (this->isColor()) return;
2419 
2420  IplImage *srcImg = getAs<IplImage>(); // Source Image
2421  IplImage *outImg; // Output Image
2422  outImg = cvCreateImage( cvGetSize( srcImg ), srcImg->depth, 3 );
2423 
2424  cvCvtColor( srcImg, outImg, CV_GRAY2BGR );
2425 
2426  outImg->origin = srcImg->origin;
2427 
2428  // Assign the output image to the IPLImage pointer within the CImage
2429  releaseIpl();
2430  img = outImg;
2431 #endif
2432 }
2433 
2434 /*---------------------------------------------------------------
2435  joinImagesHorz
2436  ---------------------------------------------------------------*/
2437 void CImage::joinImagesHorz( const CImage &im1, const CImage &im2 )
2438 {
2439 #if MRPT_HAS_OPENCV
2440  ASSERT_( im1.getHeight() == im2.getHeight() );
2441 
2442  const IplImage* _im1 = im1.getAs<IplImage>();
2443  const IplImage* _im2 = im2.getAs<IplImage>();
2444 
2445  ASSERT_( _im1->depth == _im2->depth && _im1->nChannels == _im2->nChannels );
2446 
2447  IplImage *out = cvCreateImage( cvSize( _im1->width + _im2->width, _im1->height ), _im1->depth, _im1->nChannels );
2448 
2449  cvSetImageROI( out, cvRect( 0, 0, _im1->width, _im1->height ) );
2450  cvCopy( _im1, out );
2451  cvSetImageROI( out, cvRect( _im1->width, 0, _im2->width, _im2->height ) );
2452  cvCopy( _im2, out );
2453  cvSetImageROI( out, cvRect( 0, 0, out->width, out->height ) );
2454 
2455  IplImage *out2;
2456  if( (int)_im1->nChannels != (int)this->getChannelCount() ) // Convert the input to the output channel format
2457  {
2458  out2 = cvCreateImage( cvSize( _im1->width + _im2->width, _im1->height ), _im1->depth, this->getChannelCount() );
2459  cvCvtColor( out, out2, CV_GRAY2BGR );
2460  this->setFromIplImageReadOnly( out2 );
2461  }
2462  else // Assign the output image to the IPLImage pointer within the CImage
2463  this->setFromIplImageReadOnly( out );
2464 
2465 
2466 
2467 #endif
2468 } // end
2469 
2470 
2471 /*---------------------------------------------------------------
2472  equalizeHist
2473  ---------------------------------------------------------------*/
2474 void CImage::equalizeHist( CImage &outImg ) const
2475 {
2476 #if MRPT_HAS_OPENCV
2477  // Convert to a single luminance channel image
2478  const IplImage *srcImg = getAs<IplImage>(); // Source Image
2479  ASSERT_(srcImg!=NULL)
2480 
2481  outImg.changeSize( srcImg->width, srcImg->height, 1,isOriginTopLeft());
2482 
2483  if (srcImg->nChannels==1)
2484  { // Grayscale:
2485  cvEqualizeHist(srcImg, outImg.getAs<IplImage>() );
2486  }
2487  else
2488  { // Color:
2489  IplImage *hsv = cvCreateImage(cvGetSize(srcImg), 8, 3);
2490  IplImage *h = cvCreateImage(cvGetSize(srcImg), 8, 1);
2491  IplImage *s = cvCreateImage(cvGetSize(srcImg), 8, 1);
2492  IplImage *v = cvCreateImage(cvGetSize(srcImg), 8, 1);
2493 
2494  cvCvtColor(srcImg, hsv, CV_BGR2HSV);
2495  cvSplit(hsv, h, s, v, NULL);
2496 
2497  cvEqualizeHist(v, v);
2498 
2499  cvMerge(h, s, v, NULL, hsv);
2500  cvCvtColor(hsv, outImg.getAs<IplImage>(), CV_HSV2BGR);
2501 
2502  cvReleaseImage(&hsv);
2503  cvReleaseImage(&h);
2504  cvReleaseImage(&s);
2505  cvReleaseImage(&v);
2506  }
2507 
2508 #endif
2509 }
2510 
2511 /*---------------------------------------------------------------
2512  equalizeHistInPlace
2513  ---------------------------------------------------------------*/
2515 {
2516 #if MRPT_HAS_OPENCV
2517  // Convert to a single luminance channel image
2518  IplImage *srcImg = getAs<IplImage>(); // Source Image
2519  ASSERT_(srcImg!=NULL);
2520 
2521  IplImage *outImg = cvCreateImage( cvGetSize( srcImg ), srcImg->depth, srcImg->nChannels );
2522  outImg->origin = srcImg->origin;
2523 
2524  if (srcImg->nChannels==1)
2525  { // Grayscale:
2526  cvEqualizeHist(srcImg, outImg );
2527  }
2528  else
2529  { // Color:
2530  IplImage *hsv = cvCreateImage(cvGetSize(srcImg), 8, 3);
2531  IplImage *h = cvCreateImage(cvGetSize(srcImg), 8, 1);
2532  IplImage *s = cvCreateImage(cvGetSize(srcImg), 8, 1);
2533  IplImage *v = cvCreateImage(cvGetSize(srcImg), 8, 1);
2534 
2535  cvCvtColor(srcImg, hsv, CV_BGR2HSV);
2536  cvSplit(hsv, h, s, v, NULL);
2537 
2538  cvEqualizeHist(v, v);
2539 
2540  cvMerge(h, s, v, NULL, hsv);
2541  cvCvtColor(hsv, outImg, CV_HSV2BGR);
2542 
2543  cvReleaseImage(&hsv);
2544  cvReleaseImage(&h);
2545  cvReleaseImage(&s);
2546  cvReleaseImage(&v);
2547  }
2548 
2549  // Assign the output image to the IPLImage pointer within the CImage
2550  releaseIpl();
2551  img = outImg;
2552 
2553 #endif
2554 }
2555 
2556 
2557 template <unsigned int HALF_WIN_SIZE>
2558 void image_KLT_response_template(const uint8_t* in, const int widthStep, int x, int y, int32_t &_gxx,int32_t &_gyy,int32_t &_gxy)
2559 {
2560  const unsigned int min_x = x-HALF_WIN_SIZE;
2561  const unsigned int min_y = y-HALF_WIN_SIZE;
2562 
2563  int32_t gxx = 0;
2564  int32_t gxy = 0;
2565  int32_t gyy = 0;
2566 
2567  const unsigned int WIN_SIZE = 1+2*HALF_WIN_SIZE;
2568 
2569  unsigned int yy = min_y;
2570  for (unsigned int iy=WIN_SIZE; iy ; --iy, ++yy)
2571  {
2572  const uint8_t* ptr = in + widthStep*yy+ min_x;
2573  unsigned int xx = min_x;
2574  for (unsigned int ix = WIN_SIZE; ix; --ix, ++xx)
2575  {
2576  const int32_t dx = ptr[+1]-ptr[-1];
2577  const int32_t dy = ptr[+widthStep]-ptr[-widthStep];
2578  gxx += dx * dx;
2579  gxy += dx * dy;
2580  gyy += dy * dy;
2581  }
2582  }
2583  _gxx = gxx;
2584  _gyy = gyy;
2585  _gxy = gxy;
2586 }
2587 
2588 
2589 
2591  const unsigned int x,
2592  const unsigned int y,
2593  const unsigned int half_window_size ) const
2594 {
2595 #if MRPT_HAS_OPENCV
2596  const IplImage *srcImg = this->getAs<IplImage>();
2597  ASSERT_(srcImg!=NULL)
2598  ASSERTMSG_(srcImg->nChannels==1, "KLT_response only works with grayscale images.")
2599 
2600  const unsigned int img_w = srcImg->width;
2601  const unsigned int img_h = srcImg->height;
2602  const int widthStep = srcImg->widthStep;
2603 
2604  // If any of those predefined values worked, do the generic way:
2605  const unsigned int min_x = x-half_window_size;
2606  const unsigned int max_x = x+half_window_size;
2607  const unsigned int min_y = y-half_window_size;
2608  const unsigned int max_y = y+half_window_size;
2609 
2610  // Since min_* are "unsigned", checking "<" will detect negative numbers:
2611  ASSERTMSG_(min_x<img_w && max_x<img_w && min_y<img_h && max_y<img_h, "Window is out of image bounds")
2612 
2613  // Gradient sums: Use integers since they're much faster than doubles/floats!!
2614  int32_t gxx = 0;
2615  int32_t gxy = 0;
2616  int32_t gyy = 0;
2617 
2618  const uint8_t* img_data = reinterpret_cast<const uint8_t*>(srcImg->imageData); //*VERY IMPORTANT*: Use unsigned
2619  switch (half_window_size)
2620  {
2621  case 2: image_KLT_response_template<2>(img_data,widthStep,x,y,gxx,gyy,gxy); break;
2622  case 3: image_KLT_response_template<3>(img_data,widthStep,x,y,gxx,gyy,gxy); break;
2623  case 4: image_KLT_response_template<4>(img_data,widthStep,x,y,gxx,gyy,gxy); break;
2624  case 5: image_KLT_response_template<5>(img_data,widthStep,x,y,gxx,gyy,gxy); break;
2625  case 6: image_KLT_response_template<6>(img_data,widthStep,x,y,gxx,gyy,gxy); break;
2626  case 7: image_KLT_response_template<7>(img_data,widthStep,x,y,gxx,gyy,gxy); break;
2627  case 8: image_KLT_response_template<8>(img_data,widthStep,x,y,gxx,gyy,gxy); break;
2628  case 9: image_KLT_response_template<9>(img_data,widthStep,x,y,gxx,gyy,gxy); break;
2629  case 10: image_KLT_response_template<10>(img_data,widthStep,x,y,gxx,gyy,gxy); break;
2630  case 11: image_KLT_response_template<11>(img_data,widthStep,x,y,gxx,gyy,gxy); break;
2631  case 12: image_KLT_response_template<12>(img_data,widthStep,x,y,gxx,gyy,gxy); break;
2632  case 13: image_KLT_response_template<13>(img_data,widthStep,x,y,gxx,gyy,gxy); break;
2633  case 14: image_KLT_response_template<14>(img_data,widthStep,x,y,gxx,gyy,gxy); break;
2634  case 15: image_KLT_response_template<15>(img_data,widthStep,x,y,gxx,gyy,gxy); break;
2635  case 16: image_KLT_response_template<16>(img_data,widthStep,x,y,gxx,gyy,gxy); break;
2636  case 32: image_KLT_response_template<32>(img_data,widthStep,x,y,gxx,gyy,gxy); break;
2637 
2638  default:
2639  for (unsigned int yy = min_y; yy<=max_y; yy++)
2640  {
2641  const uint8_t* ptr = img_data + widthStep*yy+ min_x;
2642  for (unsigned int xx = min_x; xx<=max_x; xx++)
2643  {
2644  const int32_t dx = ptr[+1]-ptr[-1];
2645  const int32_t dy = ptr[+widthStep]-ptr[-widthStep];
2646  gxx += dx * dx;
2647  gxy += dx * dy;
2648  gyy += dy * dy;
2649  }
2650  }
2651  break;
2652  }
2653  // Convert to float's and normalize in the way:
2654  const float K = 0.5f/( (max_y-min_y+1) * (max_x-min_x+1) );
2655  const float Gxx = gxx * K;
2656  const float Gxy = gxy * K;
2657  const float Gyy = gyy * K;
2658 
2659  // Return the minimum eigenvalue of:
2660  // ( gxx gxy )
2661  // ( gxy gyy )
2662  // See, for example: mrpt::math::detail::eigenVectorsMatrix_special_2x2():
2663  const float t = Gxx+Gyy; // Trace
2664  const float de = Gxx*Gyy-Gxy*Gxy; // Det
2665  // The smallest eigenvalue is:
2666  return 0.5f * (t - std::sqrt( t*t - 4.0f*de ) );
2667 #else
2668  return 0;
2669 #endif
2670 }
2671 
2672 
2673 /** Marks the channel ordering in a color image (this doesn't actually modify the image data, just the format description)
2674  */
2676 {
2677 #if MRPT_HAS_OPENCV
2678  makeSureImageIsLoaded(); // For delayed loaded images stored externally
2679  ASSERT_(img);
2680  strcpy( ((IplImage*)img)->channelSeq, "RGB");
2681 #else
2682  THROW_EXCEPTION("MRPT compiled without OpenCV")
2683 #endif
2684 }
2685 
2687 {
2688 #if MRPT_HAS_OPENCV
2689  makeSureImageIsLoaded(); // For delayed loaded images stored externally
2690  ASSERT_(img);
2691  strcpy( ((IplImage*)img)->channelSeq, "BGR");
2692 #else
2693  THROW_EXCEPTION("MRPT compiled without OpenCV")
2694 #endif
2695 }
2696 
2697 
2698 /** Loads the image from an XPM array, as #include'd from a ".xpm" file.
2699  * \sa loadFromFile
2700  * \return false on any error */
2701 bool CImage::loadFromXPM( const char** xpm_array, bool swap_rb )
2702 {
2703 #if MRPT_HAS_OPENCV && MRPT_HAS_WXWIDGETS
2704  try {
2705  const wxImage b(xpm_array);
2706 
2707  const size_t lx = b.GetWidth();
2708  const size_t ly = b.GetHeight();
2709 
2710  this->loadFromMemoryBuffer(lx,ly,true,b.GetData(), swap_rb);
2711  return true;
2712  }
2713  catch(std::exception &e)
2714  {
2715  std::cerr << "[CImage::loadFromXPM] " << e.what() << std::endl;
2716  return false;
2717  }
2718 #else
2719  MRPT_UNUSED_PARAM(xpm_array); MRPT_UNUSED_PARAM(swap_rb);
2720  return false;
2721 #endif // MRPT_HAS_OPENCV && MRPT_HAS_WXWIDGETS
2722 }
2723 
2724 
2725 // Load from TGA files. Used in loadFromFile()
2726 // Contains code from https://github.com/tjohnman/Simple-Targa-Library/blob/master/src/simpleTGA.cpp (FreeBSD license)
2727 bool CImage::loadTGA(const std::string& fileName, mrpt::utils::CImage &out_RGB, mrpt::utils::CImage &out_alpha)
2728 {
2729 #if MRPT_HAS_OPENCV
2730  std::fstream stream;
2731  stream.open(fileName.c_str(), std::fstream::in | std::fstream::binary);
2732  if (!stream.is_open())
2733  {
2734  std::cerr << "[CImage::loadTGA] Couldn't open file '"<< fileName <<"'.\n";
2735  return false;
2736  }
2737 
2738  stream.seekg(0, std::ios_base::end);
2739  //long length = stream.tellg();
2740  stream.seekg(0, std::ios_base::beg);
2741 
2742  // Simple uncompressed true-color image
2743  char dumpBuffer[12];
2744  char trueColorHeader[] = "\0\0\2\0\0\0\0\0\0\0\0\0";
2745  stream.read(dumpBuffer, 12);
2746  if(memcmp(dumpBuffer, trueColorHeader, 12) != 0)
2747  {
2748  std::cerr << "[CImage::loadTGA] Unsupported format or invalid file.\n";
2749  return false;
2750  }
2751 
2752  unsigned short width, height;
2753  unsigned char bpp;
2754 
2755  stream.read((char *)&width, 2);
2756  stream.read((char *)&height, 2);
2757  bpp = stream.get();
2758  if(bpp!=32)
2759  {
2760  std::cerr << "[CImage::loadTGA] Only 32 bpp format supported!\n";
2761  return false;
2762  }
2763 
2764  unsigned char desc;
2765  desc = stream.get();
2766  if(desc!= 8 && desc!=32)
2767  {
2768  std::cerr << "[CImage::loadTGA] Unsupported format or invalid file.\n";
2769  return false;
2770  }
2771  const bool origin_is_low_corner = (desc==8);
2772 
2773  // Data section
2774  std::vector<uint8_t> bytes(width*height*4);
2775  stream.read((char *)&bytes[0], width*height*4);
2776  stream.close();
2777 
2778  // Move data to images:
2779  out_RGB.resize(width,height, CH_RGB, true );
2780  out_alpha.resize(width,height, CH_GRAY, true );
2781 
2782  size_t idx=0;
2783  for (unsigned int r=0;r<height;r++)
2784  {
2785  unsigned int actual_row = origin_is_low_corner ? (height-1-r) : r;
2786  IplImage *ipl = ((IplImage*)out_RGB.img);
2787  unsigned char* data= (unsigned char*) &ipl->imageData[ actual_row * ipl->widthStep ];
2788 
2789  IplImage *ipl_alpha = ((IplImage*)out_alpha.img);
2790  unsigned char* data_alpha= (unsigned char*)&ipl->imageData[ actual_row * ipl_alpha->widthStep ];
2791 
2792  for (unsigned int c=0;c<width;c++)
2793  {
2794  *data++ = bytes[idx++]; // R
2795  *data++ = bytes[idx++]; // G
2796  *data++ = bytes[idx++]; // B
2797  *data_alpha++ = bytes[idx++]; // A
2798  }
2799  }
2800 
2801  return true;
2802 #else
2803  return false;
2804 #endif // MRPT_HAS_OPENCV
2805 }
virtual void textOut(int x0, int y0, const std::string &str, const mrpt::utils::TColor color)
Renders 2D text using bitmap fonts.
Definition: CCanvas.cpp:397
void BASE_IMPEXP memcpy(void *dest, size_t destSize, const void *src, size_t copyCount) MRPT_NO_THROWS
An OS and compiler independent version of "memcpy".
Definition: os.cpp:358
bool is_aligned< 16 >(const void *ptr)
Definition: memory.h:107
float getAsFloat(unsigned int col, unsigned int row, unsigned int channel) const
Returns the contents of a given pixel at the desired channel, in float format: [0,255]->[0,1] The coordinate origin is pixel(0,0)=top-left corner of the image.
Definition: CImage.cpp:942
void equalizeHistInPlace()
Equalize the image histogram, replacing the original image.
Definition: CImage.cpp:2514
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei imageSize
Definition: glext.h:3639
float correlate(const CImage &img2int, int width_init=0, int height_init=0) const
Computes the correlation coefficient (returned as val), between two images This function use grayscal...
Definition: CImage.cpp:1403
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
Definition: zip.h:16
GLdouble GLdouble t
Definition: glext.h:3610
TImageChannels getChannelCount() const
Returns the number of channels, typically 1 (GRAY) or 3 (RGB)
Definition: CImage.cpp:912
static bool DISABLE_JPEG_COMPRESSION
By default, when storing images through the CSerializable interface, RGB images are JPEG-compressed t...
Definition: CImage.h:192
static int SERIALIZATION_JPEG_QUALITY
Unless DISABLE_JPEG_COMPRESSION=true, this sets the JPEG quality (range 1-100) of serialized RGB imag...
Definition: CImage.h:196
std::string m_externalFile
The file name of a external storage image.
Definition: CImage.h:921
unsigned char red[10]
Definition: PbMapMaker.cpp:976
This namespace provides a OS-independent interface to many useful functions: filenames manipulation...
Definition: math_frwds.h:29
static bool loadTGA(const std::string &fileName, mrpt::utils::CImage &out_RGB, mrpt::utils::CImage &out_alpha)
Loads a TGA true-color RGBA image as two CImage objects, one for the RGB channels plus a separate gra...
Definition: CImage.cpp:2727
CImage scaleDouble() const
Returns a new image scaled up to double its original size.
Definition: CImage.h:312
The virtual base class which provides a unified interface for all persistent objects in MRPT...
Definition: CSerializable.h:39
bool m_imgIsReadOnly
Set to true only when using setFromIplImageReadOnly.
Definition: CImage.h:916
A class for storing images as grayscale or RGB bitmaps.
Definition: CImage.h:101
void drawCircle(int x, int y, int radius, const mrpt::utils::TColor &color=mrpt::utils::TColor(255, 255, 255), unsigned int width=1) MRPT_OVERRIDE
Draws a circle of a given radius.
Definition: CImage.cpp:1323
#define IMPLEMENTS_SERIALIZABLE(class_name, base, NameSpace)
This must be inserted in all CSerializable classes implementation files.
void flipVertical(bool also_swapRB=false)
Flips the image vertically.
Definition: CImage.cpp:1985
GLenum GLenum GLenum GLenum GLenum scale
Definition: glext.h:5717
#define THROW_TYPED_EXCEPTION_FMT(exceptionClass, _FORMAT_STRING,...)
void rotateImage(double angle_radians, unsigned int center_x, unsigned int center_y, double scale=1.0)
Rotates the image by the given angle around the given center point, with an optional scale factor...
Definition: CImage.cpp:2281
void image_SSSE3_bgr_to_gray_8u(const uint8_t *in, uint8_t *out, int w, int h)
Convert a RGB image (3cu8) into a GRAYSCALE (1c8u) image, using Y=77*R+150*G+29*B.
void rectifyImageInPlace(const mrpt::utils::TCamera &cameraParams)
Rectify (un-distort) the image according to a certain camera matrix and vector of distortion coeffici...
Definition: CImage.cpp:2050
void copyFastFrom(CImage &o)
Moves an image from another object, erasing the origin image in the process (this is much faster than...
Definition: CImage.cpp:167
#define THROW_EXCEPTION(msg)
void resize(unsigned int width, unsigned int height, TImageChannels nChannels, bool originTopLeft)
Changes the size of the image, erasing previous contents (does NOT scale its current content...
Definition: CImage.h:209
void getAsMatrix(mrpt::math::CMatrixFloat &outMatrix, bool doResize=true, int x_min=0, int y_min=0, int x_max=-1, int y_max=-1) const
Returns the image as a matrix with pixel grayscale values in the range [0,1].
Definition: CImage.cpp:1601
A pair (x,y) of pixel coordinates (integer resolution).
Definition: TPixelCoord.h:37
void rectifyImage(CImage &out_img, const mrpt::utils::TCamera &cameraParams) const
Rectify (un-distort) the image according to some camera parameters, and returns an output un-distorte...
Definition: CImage.cpp:2084
GLenum GLsizei n
Definition: glext.h:4618
const char * getChannelsOrder() const
Returns a string of the form "BGR","RGB" or "GRAY" indicating the channels ordering.
Definition: CImage.cpp:1180
float getMaxAsFloat() const
Return the maximum pixel value of the image, as a float value in the range [0,1]. ...
Definition: CImage.cpp:976
void unload() const MRPT_NO_THROWS
For external storage image objects only, this method unloads the image from memory (or does nothing i...
Definition: CImage.cpp:1905
void WriteBuffer(const void *Buffer, size_t Count)
Writes a block of bytes to the stream from Buffer.
Definition: CStream.cpp:67
void filterMedian(CImage &out_img, int W=3) const
Filter the image with a Median filter with a window size WxW, returning the filtered image in out_img...
Definition: CImage.cpp:2123
#define MRPT_NO_THROWS
C++11 noexcept: Used after member declarations.
void flipHorizontal()
Flips the image horizontally.
Definition: CImage.cpp:1995
void colorImageInPlace()
Replaces this grayscale image with a RGB version of it.
Definition: CImage.cpp:2415
STL namespace.
static TColor blue
Predefined colors.
Definition: TColor.h:67
char BASE_IMPEXP * strcpy(char *dest, size_t destSize, const char *source) MRPT_NO_THROWS
An OS-independent version of strcpy.
Definition: os.cpp:296
bool loadFromFile(const std::string &fileName, int isColor=-1)
Load image from a file, whose format is determined from the extension (internally uses OpenCV)...
Definition: CImage.cpp:277
GLdouble s
Definition: glext.h:3602
GLuint src
Definition: glext.h:6303
int TImageChannels
For use in mrpt::utils::CImage.
Definition: CImage.h:40
void normalize()
Optimize the brightness range of an image without using histogram Only for one channel images...
Definition: CImage.cpp:1560
void loadFromIplImage(void *iplImage)
Reads the image from a OpenCV IplImage object (making a COPY).
Definition: CImage.cpp:324
static std::string IMAGES_PATH_BASE
By default, ".".
Definition: CImage.h:668
GLenum GLsizei width
Definition: glext.h:3513
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:3962
const T * getAs() const
Returns a pointer to a const T* containing the image - the idea is to call like "img.getAs<IplImage>()" so we can avoid here including OpenCV&#39;s headers.
Definition: CImage.h:517
virtual ~CImage()
Destructor:
Definition: CImage.cpp:220
CImage & operator=(const CImage &o)
Copy operator (if the image is externally stored, the writen image will be such as well)...
Definition: CImage.cpp:109
T square(const T x)
Inline function for the square of a number.
Definition: bits.h:52
void readFromStream(mrpt::utils::CStream &in, int version)
Introduces a pure virtual method responsible for loading from a CStream This can not be used directly...
Definition: CImage.cpp:633
unsigned char uint8_t
Definition: rptypes.h:43
void image_SSE2_scale_half_smooth_1c8u(const uint8_t *in, uint8_t *out, int w, int h)
Average each 2x2 pixels into 1x1 pixel (arithmetic average)
Definition: CImage_SSE2.cpp:70
GLuint color
Definition: glext.h:7093
void cross_correlation_FFT(const CImage &in_img, math::CMatrixFloat &out_corr, int u_search_ini=-1, int v_search_ini=-1, int u_search_size=-1, int v_search_size=-1, float biasThisImg=0, float biasInImg=0) const
Computes the correlation matrix between this image and another one.
Definition: CImage.cpp:1736
void image_SSSE3_scale_half_3c8u(const uint8_t *in, uint8_t *out, int w, int h)
Subsample each 2x2 pixel block into 1x1 pixel, taking the first pixel & ignoring the other 3...
Definition: CImage_SSE3.cpp:37
void getAsMatrixTiled(math::CMatrix &outMatrix) const
Returns the image as a matrix, where the image is "tiled" (repeated) the required number of times to ...
Definition: CImage.cpp:1840
This base class is used to provide a unified interface to files,memory buffers,..Please see the deriv...
Definition: CStream.h:38
This base provides a set of functions for maths stuff.
Definition: CArrayNumeric.h:19
T round2up(T val)
Round up to the nearest power of two of a given number.
void loadFromMemoryBuffer(unsigned int width, unsigned int height, bool color, unsigned char *rawpixels, bool swapRedBlue=false)
Reads the image from raw pixels buffer in memory.
Definition: CImage.cpp:387
#define MRPT_END
float KLT_response(const unsigned int x, const unsigned int y, const unsigned int half_window_size) const
Compute the KLT response at a given pixel (x,y) - Only for grayscale images (for efficiency it avoids...
Definition: CImage.cpp:2590
#define MRPT_UNUSED_PARAM(a)
Can be used to avoid "not used parameters" warnings from the compiler.
This CStream derived class allow using a memory buffer as a CStream.
Definition: CMemoryStream.h:26
const GLubyte * c
Definition: glext.h:5590
#define MRPT_THROW_UNKNOWN_SERIALIZATION_VERSION(__V)
For use in CSerializable implementations.
GLint GLvoid * img
Definition: glext.h:3645
void cross_correlation(const CImage &patch_img, size_t &u_max, size_t &v_max, double &max_val, int u_search_ini=-1, int v_search_ini=-1, int u_search_size=-1, int v_search_size=-1, CImage *out_corr_image=NULL) const
Computes the correlation between this image and another one, encapsulating the openCV function cvMatc...
Definition: CImage.cpp:1451
void image_KLT_response_template(const uint8_t *in, const int widthStep, int x, int y, int32_t &_gxx, int32_t &_gyy, int32_t &_gxy)
Definition: CImage.cpp:2558
#define CH_RGB
Definition: CImage.h:42
IplImage * ipl_to_grayscale(const IplImage *img_src)
Definition: CImage.cpp:1001
void writeToStream(mrpt::utils::CStream &out, int *getVersion) const
Introduces a pure virtual method responsible for writing to a CStream.
Definition: CImage.cpp:510
virtual void selectTextFont(const std::string &fontName)
Select the current font used when drawing text.
Definition: CCanvas.cpp:249
GLuint GLuint end
Definition: glext.h:3512
CImage grayscale() const
Returns a grayscale version of the image, or itself if it is already a grayscale image.
Definition: CImage.cpp:992
void scaleImage(unsigned int width, unsigned int height, TInterpolationMethod interp=IMG_INTERP_CUBIC)
Scales this image to a new size, interpolating as needed.
Definition: CImage.cpp:2224
A RGB color - 8bit.
Definition: TColor.h:26
void line(int x0, int y0, int x1, int y1, const mrpt::utils::TColor color, unsigned int width=1, TPenStyle penStyle=psSolid) MRPT_OVERRIDE
Draws a line.
Definition: CImage.cpp:1301
int val
Definition: mrpt_jpeglib.h:953
std::string BASE_IMPEXP format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
Definition: format.cpp:21
GLubyte GLubyte b
Definition: glext.h:5575
void setChannelsOrder_RGB()
Marks the channel ordering in a color image as "RGB" (this doesn&#39;t actually modify the image data...
Definition: CImage.cpp:2675
#define IMPLEMENTS_MEXPLUS_FROM(complete_type)
size_t getRowStride() const
Returns the row stride of the image: this is the number of bytes between two consecutive rows...
Definition: CImage.cpp:869
bool isExternallyStored() const MRPT_NO_THROWS
See setExternalStorage().
Definition: CImage.h:671
void saveToStreamAsJPEG(mrpt::utils::CStream &out, const int jpeg_quality=95) const
Save image to binary stream as a JPEG (.jpg) compressed format.
void swapRB()
Swaps red and blue channels.
Definition: CImage.cpp:2006
int version
Definition: mrpt_jpeglib.h:898
void setFromIplImage(void *iplImage)
Reads the image from a OpenCV IplImage object (WITHOUT making a copy).
Definition: CImage.cpp:365
void changeSize(unsigned int width, unsigned int height, TImageChannels nChannels, bool originTopLeft)
Resize the buffers in "img" to accomodate a new image size and/or format.
Definition: CImage.cpp:228
std::string BASE_IMPEXP format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
bool loadFromXPM(const char **xpm_array, bool swap_rb=true)
Loads the image from an XPM array, as #include&#39;d from a ".xpm" file.
Definition: CImage.cpp:2701
void setFromIplImageReadOnly(void *iplImage)
Reads the image from a OpenCV IplImage object (WITHOUT making a copy) and from now on the image canno...
Definition: CImage.cpp:343
GLsizei const GLchar ** string
Definition: glext.h:3919
void swap(CImage &o)
Very efficient swap of two images (just swap the internal pointers)
Definition: CImage.cpp:135
GLint GLint GLsizei GLsizei GLsizei GLint GLenum GLenum const GLvoid * pixels
Definition: glext.h:3545
mrpt::math::CMatrixDouble33 intrinsicParams
Matrix of intrinsic parameters (containing the focal length and principal point coordinates) ...
Definition: TCamera.h:54
void BASE_IMPEXP idft2_complex(const CMatrixFloat &in_real, const CMatrixFloat &in_imag, CMatrixFloat &out_real, CMatrixFloat &out_imag)
Compute the 2D inverse Discrete Fourier Transform (DFT).
Definition: math.cpp:1560
void image_SSE2_scale_half_1c8u(const uint8_t *in, uint8_t *out, int w, int h)
Subsample each 2x2 pixel block into 1x1 pixel, taking the first pixel & ignoring the other 3...
Definition: CImage_SSE2.cpp:40
void copyFromForceLoad(const CImage &o)
Copies from another image, and, if that one is externally stored, the image file will be actually loa...
Definition: CImage.cpp:150
void * getRawBufferData()
Method for getting a pointer to the raw stored data.
void filterMedianInPlace(int W=3)
Filter the image with a Median filter with a window size WxH, replacing "this" image by the filtered ...
Definition: CImage.cpp:2149
TInterpolationMethod
Interpolation methods for images.
Definition: CImage.h:31
void setChannelsOrder_BGR()
Marks the channel ordering in a color image as "BGR" (this doesn&#39;t actually modify the image data...
Definition: CImage.cpp:2686
#define MRPT_START
__int32 int32_t
Definition: rptypes.h:48
void makeSureImageIsLoaded() const
Checks if the image is of type "external storage", and if so and not loaded yet, load it...
Definition: CImage.cpp:1935
const GLdouble * v
Definition: glext.h:3603
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
void update_patch(const CImage &patch, const unsigned int col, const unsigned int row)
Update a part of this image with the "patch" given as argument.
Definition: CImage.cpp:1342
void releaseIpl(bool thisIsExternalImgUnload=false) MRPT_NO_THROWS
Release the internal IPL image, if not NULL or read-only.
Definition: CImage.cpp:1914
unsigned char * operator()(unsigned int col, unsigned int row, unsigned int channel=0) const
Returns a pointer to a given pixel information.
Definition: CImage.cpp:451
GLdouble GLdouble GLdouble r
Definition: glext.h:3618
CImage scaleHalfSmooth() const
Returns a new image scaled down to half its original size (averaging between every two rows) ...
Definition: CImage.h:297
mrpt::math::CArrayDouble< 5 > dist
[k1 k2 t1 t2 k3] -> k_i: parameters of radial distortion, t_i: parameters of tangential distortion (d...
Definition: TCamera.h:55
virtual mxArray * writeToMatlab() const
Introduces a pure virtual method responsible for writing to a mxArray Matlab object, typically a MATLAB struct whose contents are documented in each derived class.
Definition: CSerializable.h:79
GLclampf green
Definition: glext.h:3510
CImage scaleHalf() const
Returns a new image scaled down to half its original size.
Definition: CImage.h:282
void equalizeHist(CImage &outImg) const
Equalize the image histogram, saving the new image in the given output object.
Definition: CImage.cpp:2474
void filterGaussianInPlace(int W=3, int H=3)
Filter the image with a Gaussian filter with a window size WxH, returning the filtered image in out_i...
Definition: CImage.cpp:2199
GLenum GLenum GLvoid * row
Definition: glext.h:3533
CImage()
Default constructor: initialize an 1x1 RGB image.
Definition: CImage.cpp:81
void extract_patch(CImage &patch, const unsigned int col=0, const unsigned int row=0, const unsigned int width=1, const unsigned int height=1) const
Extract a patch from this image, saveing it into "patch" (its previous contents will be overwritten)...
Definition: CImage.cpp:1368
bool drawChessboardCorners(std::vector< TPixelCoordf > &cornerCoords, unsigned int check_size_x, unsigned int check_size_y, unsigned int lines_width=1, unsigned int circles_radius=4)
Draw onto this image the detected corners of a chessboard.
Definition: CImage.cpp:2325
#define CH_GRAY
Definition: CImage.h:41
GLuint in
Definition: glext.h:6301
bool isOriginTopLeft() const
Returns true if the coordinates origin is top-left, or false if it is bottom-left.
Definition: CImage.cpp:927
void changeSize(uint64_t newSize)
Change size. This would be rarely used. Use ">>" operators for writing to stream. ...
#define ASSERT_(f)
A versatile "profiler" that logs the time spent within each pair of calls to enter(X)-leave(X), among other stats.
Definition: CTimeLogger.h:41
double leave(const char *func_name)
End of a named section.
Definition: CTimeLogger.h:102
uint64_t getTotalBytesCount() MRPT_OVERRIDE
Returns the total size of the internal buffer.
int round(const T value)
Returns the closer integer (int) to x.
Definition: round.h:26
bool saveToFile(const std::string &fileName, int jpeg_quality=95) const
Save the image to a file, whose format is determined from the extension (internally uses OpenCV)...
Definition: CImage.cpp:299
uint64_t Seek(int64_t Offset, CStream::TSeekOrigin Origin=sFromBeginning) MRPT_OVERRIDE
Introduces a pure virtual method for moving to a specified position in the streamed resource...
GLenum GLint GLint y
Definition: glext.h:3516
static bool DISABLE_ZIP_COMPRESSION
By default, when storing images through the CSerializable interface, grayscale images will be ZIP com...
Definition: CImage.h:188
bool m_imgIsExternalStorage
Set to true only when using setExternalStorage.
Definition: CImage.h:920
bool isColor() const
Returns true if the image is RGB, false if it is grayscale.
Definition: CImage.cpp:898
void colorImage(CImage &ret) const
Returns a RGB version of the grayscale image, or itself if it is already a RGB image.
Definition: CImage.cpp:2392
void BASE_IMPEXP compress(void *inData, size_t inDataSize, std::vector< unsigned char > &outData)
Compress an array of bytes into another one.
Definition: zip.cpp:36
unsigned char * get_unsafe(unsigned int col, unsigned int row, unsigned int channel=0) const
Access to pixels without checking boundaries - Use normally the () operator better, which checks the coordinates.
Definition: CImage.cpp:491
GLuint interp
Definition: glext.h:6197
void setExternalStorage(const std::string &fileName) MRPT_NO_THROWS
By using this method the image is marked as referenced to an external file, which will be loaded only...
Definition: CImage.cpp:1895
GLclampf GLclampf blue
Definition: glext.h:3510
GLenum GLint x
Definition: glext.h:3516
void BASE_IMPEXP decompress(void *inData, size_t inDataSize, std::vector< unsigned char > &outData, size_t outDataEstimatedSize)
Decompress an array of bytes into another one.
Definition: zip.cpp:165
This class is a "CSerializable" wrapper for "CMatrixFloat".
Definition: CMatrix.h:30
TPenStyle
Definition of pen styles.
Definition: CCanvas.h:53
GLenum GLsizei GLsizei height
Definition: glext.h:3523
void BASE_IMPEXP dft2_complex(const CMatrixFloat &in_real, const CMatrixFloat &in_imag, CMatrixFloat &out_real, CMatrixFloat &out_imag)
Compute the 2D Discrete Fourier Transform (DFT) of a complex matrix, returning the real and imaginary...
Definition: math.cpp:1451
void setOriginTopLeft(bool val)
Changes the property of the image stating if the top-left corner (vs.
Definition: CImage.cpp:1236
unsigned __int32 uint32_t
Definition: rptypes.h:49
void enter(const char *func_name)
Start of a named section.
Definition: CTimeLogger.h:97
#define ASSERTMSG_(f, __ERROR_MSG)
GLsizei GLsizei GLenum GLenum const GLvoid * data
Definition: glext.h:3520
Used in mrpt::utils::CImage.
Definition: exceptions.h:31
GLfloat GLfloat p
Definition: glext.h:5587
void * img
The internal IplImage pointer to the actual image content.
Definition: CImage.h:912
size_t getWidth() const MRPT_OVERRIDE
Returns the width of the image in pixels.
Definition: CImage.cpp:855
void getExternalStorageFileAbsolutePath(std::string &out_path) const
Only if isExternallyStored() returns true.
Definition: CImage.cpp:1962
void grayscaleInPlace()
Replaces the image with a grayscale version of it.
Definition: CImage.cpp:1052
void joinImagesHorz(const CImage &im1, const CImage &im2)
Joins two images side-by-side horizontally.
Definition: CImage.cpp:2437
void filterGaussian(CImage &out_img, int W=3, int H=3) const
Filter the image with a Gaussian filter with a window size WxH, replacing "this" image by the filtere...
Definition: CImage.cpp:2173
TImageSize getSize() const
Return the size of the image.
Definition: CImage.h:569
struct mxArray_tag mxArray
Forward declaration for mxArray (avoid #including as much as possible to speed up compiling) ...
Definition: CSerializable.h:17
void setPixel(int x, int y, size_t color) MRPT_OVERRIDE
Changes the value of the pixel (x,y).
Definition: CImage.cpp:1248
Structure to hold the parameters of a pinhole camera model.
Definition: TCamera.h:31
size_t getHeight() const MRPT_OVERRIDE
Returns the height of the image in pixels.
Definition: CImage.cpp:884
void getAsRGBMatrices(mrpt::math::CMatrixFloat &outMatrixR, mrpt::math::CMatrixFloat &outMatrixG, mrpt::math::CMatrixFloat &outMatrixB, bool doResize=true, int x_min=0, int y_min=0, int x_max=-1, int y_max=-1) const
Returns the image as RGB matrices with pixel values in the range [0,1].
Definition: CImage.cpp:1662
std::string getExternalStorageFileAbsolutePath() const
Only if isExternallyStored() returns true.
Definition: CImage.h:682
void loadFromStreamAsJPEG(CStream &in)
Reads the image from a binary stream containing a binary jpeg file.



Page generated by Doxygen 1.8.14 for MRPT 1.5.7 Git: 5902e14cc Wed Apr 24 15:04:01 2019 +0200 at lun oct 28 01:39:17 CET 2019