topical media & game development

talk show tell print

lib-of-vs-addons-ofxOpenCv-src-ofxCvFloatImage.cpp / cpp



  
  include <ofxCvGrayscaleImage.h>
  include <ofxCvColorImage.h>
  include <ofxCvFloatImage.h>
  
  //--------------------------------------------------------------------------------
  ofxCvFloatImage::ofxCvFloatImage() {
      init();
  }
  
  //--------------------------------------------------------------------------------
  ofxCvFloatImage::ofxCvFloatImage( const ofxCvFloatImage& _mom ) {
      init(); 
      if( _mom.bAllocated ) {
          // cast non-const,  to get read access to the mon::cvImage
          ofxCvFloatImage& mom = const_cast<ofxCvFloatImage&>(_mom); 
          allocate(mom.width, mom.height);    
          cvCopy( mom.getCvImage(), cvImage, 0 );
      } else {
          ofLog(OF_LOG_NOTICE, "in ofxCvFloatImage copy constructor, mom not allocated");
      }    
  }
  
  //--------------------------------------------------------------------------------
  void ofxCvFloatImage::init() {
      ipldepth = IPL_DEPTH_32F;
      iplchannels = 1;
      gldepth = GL_FLOAT;
      glchannels = GL_LUMINANCE;
      floatPixels = NULL; 
      bFloatPixelsDirty = true;
      floatPixelsW = 0;
      floatPixelsH = 0;   
      cvGrayscaleImage = NULL;
      scaleMin = 0.0f;
      scaleMax = 1.0f;
  }
  
  //--------------------------------------------------------------------------------
  void ofxCvFloatImage::clear() {
      if (bAllocated == true){
          if( cvGrayscaleImage != NULL ){
              cvReleaseImage( &cvGrayscaleImage );
          }
          if( floatPixels != NULL ) {
              delete floatPixels;
              floatPixels = NULL;
              bFloatPixelsDirty = true;
              floatPixelsW = 0;
              floatPixelsH = 0;             
          }
      }
      ofxCvImage::clear();    //call clear in base class    
  }
  
  //--------------------------------------------------------------------------------
  void ofxCvFloatImage::setNativeScale( float _scaleMin, float _scaleMax ) {
      scaleMin = _scaleMin;
      scaleMax = _scaleMax;
  }
  
  //--------------------------------------------------------------------------------
  void ofxCvFloatImage::flagImageChanged() {
      bFloatPixelsDirty = true;
      ofxCvImage::flagImageChanged();
  }
  
  //--------------------------------------------------------------------------------
  void ofxCvFloatImage::convertFloatToGray( IplImage* floatImg, IplImage* grayImg ) {
      // map from scaleMin-scaleMax to 0-255
      float scale = 255.0f/(scaleMax-scaleMin);
      cvConvertScale( floatImg, grayImg, scale, -(scaleMin*scale) );
  }
  
  //--------------------------------------------------------------------------------
  void ofxCvFloatImage::convertGrayToFloat( IplImage* grayImg, IplImage* floatImg ) {
      // map from 0-255 to scaleMin-scaleMax
      cvConvertScale( grayImg, floatImg, (scaleMax-scaleMin)/255.0f, scaleMin );
  }
  
  // Set Pixel Data
  
  //-------------------------------------------------------------------------------------
  void ofxCvFloatImage::set(float value){  
          cvSet(cvImage, cvScalar(value));
      flagImageChanged();
  }
  
  //--------------------------------------------------------------------------------
  void ofxCvFloatImage::operator *= ( float scalar ){
      for( int i=0; i<height; i++ ) { 
          float* ptr = (float*)(cvImage->imageData + (i+roiY)*cvImage->widthStep); 
          for( int j=0; j<width; j++ ) { 
              ptr[(j+roiX)] *= scalar; 
          } 
      } 
  }
  
  //--------------------------------------------------------------------------------
  void ofxCvFloatImage::operator /= ( float scalar ){
      scalar = 1.0 / scalar;
      for( int i=0; i<height; i++ ) { 
          float* ptr = (float*)(cvImage->imageData + (i+roiY)*cvImage->widthStep); 
          for( int j=0; j<width; j++ ) { 
              ptr[(j+roiX)] *= scalar; 
          } 
      } 
  }
  
  //--------------------------------------------------------------------------------
  void ofxCvFloatImage::setFromPixels( unsigned char* _pixels, int w, int h ) {    
      if( cvGrayscaleImage == NULL ) {
          cvGrayscaleImage = cvCreateImage( cvSize(cvImage->width,cvImage->height), IPL_DEPTH_8U, 1 );
      }
      
      cvSetImageROI(cvGrayscaleImage, cvRect(roiX,roiY,width,height));  //make sure ROI is in sync
  
      ofRectangle roi = getROI();
      ofRectangle inputROI = ofRectangle( roi.x, roi.y, w, h);
      ofRectangle iRoi = getIntersectionROI( roi, inputROI );
          
      if( iRoi.width > 0 && iRoi.height > 0 ) {
          // copy pixels from _pixels, however many we have or will fit in cvGrayscaleImage
          for( int i=0; i < iRoi.height; i++ ) {
              memcpy( cvGrayscaleImage->imageData + ((i+(int)iRoi.y)*cvGrayscaleImage->widthStep) + (int)iRoi.x,
                      _pixels + (i*w),
                      (int)(iRoi.width) );
          }
          convertGrayToFloat(cvGrayscaleImage, cvImage);
          flagImageChanged();
      } else {
          ofLog(OF_LOG_ERROR, "in setFromPixels, ROI mismatch");
      }    
  }
  
  //--------------------------------------------------------------------------------
  void ofxCvFloatImage::setFromPixels( float* _pixels, int w, int h ) {
      ofRectangle roi = getROI();
      ofRectangle inputROI = ofRectangle( roi.x, roi.y, w, h);
      ofRectangle iRoi = getIntersectionROI( roi, inputROI );
          
      if( iRoi.width > 0 && iRoi.height > 0 ) {
          // copy pixels from _pixels, however many we have or will fit in cvImage
          for( int i=0; i < iRoi.height; i++ ) {
              memcpy( cvImage->imageData + ((i+(int)iRoi.y)*cvImage->widthStep) + (int)iRoi.x*sizeof(float),
                      _pixels + (i*w),
                      (int)(iRoi.width*sizeof(float)) );
          }
          flagImageChanged();
      } else {
          ofLog(OF_LOG_ERROR, "in setFromPixels, ROI mismatch");
      }     
  }
  
  //--------------------------------------------------------------------------------
  void ofxCvFloatImage::operator = ( unsigned char* _pixels ) {
      setFromPixels( _pixels, width, height );
  }
  
  //--------------------------------------------------------------------------------
  void ofxCvFloatImage::operator = ( float* _pixels ) {
      setFromPixels( _pixels, width, height );
  }
  
  //--------------------------------------------------------------------------------
  void ofxCvFloatImage::operator = ( const ofxCvGrayscaleImage& _mom ) {
      // cast non-const,  no worries, we will reverse any chages
      ofxCvGrayscaleImage& mom = const_cast<ofxCvGrayscaleImage&>(_mom); 
          if( pushSetBothToTheirIntersectionROI(*this,mom) ) {
          convertGrayToFloat(mom.getCvImage(), cvImage);
          popROI();       //restore prevoius ROI
          mom.popROI();   //restore prevoius ROI              
          flagImageChanged();
          } else {
          ofLog(OF_LOG_ERROR, "in =, ROI mismatch");
          }
  }
  
  //--------------------------------------------------------------------------------
  void ofxCvFloatImage::operator = ( const ofxCvColorImage& _mom ) {
      // cast non-const,  no worries, we will reverse any chages
      ofxCvColorImage& mom = const_cast<ofxCvColorImage&>(_mom); 
          if( pushSetBothToTheirIntersectionROI(*this,mom) ) {
          if( cvGrayscaleImage == NULL ) {
              cvGrayscaleImage = cvCreateImage( cvSize(cvImage->width,cvImage->height), IPL_DEPTH_8U, 1 );
          }
          cvSetImageROI(cvGrayscaleImage, cvRect(roiX,roiY,width,height));
                  cvCvtColor( mom.getCvImage(), cvGrayscaleImage, CV_RGB2GRAY );
          convertGrayToFloat(cvGrayscaleImage, cvImage);                
          popROI();       //restore prevoius ROI
          mom.popROI();   //restore prevoius ROI   
          cvSetImageROI(cvGrayscaleImage, cvRect(roiX,roiY,width,height));
          flagImageChanged();
          } else {
          ofLog(OF_LOG_ERROR, "in =, ROI mismatch");
          }
  }
  
  //--------------------------------------------------------------------------------
  void ofxCvFloatImage::operator = ( const ofxCvFloatImage& _mom ) {
      if(this != &_mom) {  //check for self-assignment
          // cast non-const,  no worries, we will reverse any chages
          ofxCvFloatImage& mom = const_cast<ofxCvFloatImage&>(_mom);     
          if( pushSetBothToTheirIntersectionROI(*this,mom) ) {
              cvCopy( mom.getCvImage(), cvImage, 0 );
              popROI();       //restore prevoius ROI
              mom.popROI();   //restore prevoius ROI             
              flagImageChanged();
          } else {
              ofLog(OF_LOG_ERROR, "in =, ROI mismatch");
          }
      } else {
          ofLog(OF_LOG_WARNING, "in =, you are assigning a ofxCvFloatImage to itself");
      }
  }
  
  //--------------------------------------------------------------------------------
  void ofxCvFloatImage::operator = ( const IplImage* _mom ) {
      ofxCvImage::operator = (_mom);
  }
  
  //--------------------------------------------------------------------------------
  void ofxCvFloatImage::operator *= ( ofxCvImage& mom ) {
          if( mom.getCvImage()->nChannels == cvImage->nChannels && 
          mom.getCvImage()->depth == cvImage->depth )
      {
          if( pushSetBothToTheirIntersectionROI(*this,mom) ) {
              cvMul( cvImage, mom.getCvImage(), cvImageTemp );
              swapTemp();
              popROI();       //restore prevoius ROI
              mom.popROI();   //restore prevoius ROI              
              flagImageChanged();
          } else {
              ofLog(OF_LOG_ERROR, "in *=, ROI mismatch");
          }
          } else {
          ofLog(OF_LOG_ERROR, "in *=, images need to have matching type");
          }
  }
  
  //--------------------------------------------------------------------------------
  void ofxCvFloatImage::operator &= ( ofxCvImage& mom ) {
          if( mom.getCvImage()->nChannels == cvImage->nChannels && 
          mom.getCvImage()->depth == cvImage->depth )
      {
          if( pushSetBothToTheirIntersectionROI(*this,mom) ) {
              //this is doing it bit-wise; probably not what we want
              cvAnd( cvImage, mom.getCvImage(), cvImageTemp );
              swapTemp();
              popROI();       //restore prevoius ROI
              mom.popROI();   //restore prevoius ROI              
              flagImageChanged();
          } else {
              ofLog(OF_LOG_ERROR, "in &=, ROI mismatch");
          }
          } else {
          ofLog(OF_LOG_ERROR, "in &=, images need to have matching type");
          }
  }
  
  //--------------------------------------------------------------------------------
  void ofxCvFloatImage::addWeighted( ofxCvGrayscaleImage& mom, float f ) {
          if( pushSetBothToTheirIntersectionROI(*this,mom) ) {
          convertGrayToFloat(mom.getCvImage(), cvImageTemp);
          cvAddWeighted( cvImageTemp, f, cvImage, 1.0f-f,0, cvImage );
          popROI();       //restore prevoius ROI
          mom.popROI();   //restore prevoius ROI           
          flagImageChanged();
      } else {
          ofLog(OF_LOG_ERROR, "in addWeighted, ROI mismatch");
      }
  }
  
  // Get Pixel Data
  
  //--------------------------------------------------------------------------------
  unsigned char*  ofxCvFloatImage::getPixels(){
      if(bPixelsDirty) {
      
          if( cvGrayscaleImage == NULL ) {
              cvGrayscaleImage = cvCreateImage( cvSize(cvImage->width,cvImage->height), IPL_DEPTH_8U, 1 );
          }
           
          cvSetImageROI(cvGrayscaleImage, cvRect(roiX,roiY,width,height));  //make sure ROI is in sync
          convertFloatToGray(cvImage, cvGrayscaleImage);   
      
          if(pixels == NULL) {
              // we need pixels, allocate it
              pixels = new unsigned char[width*height];
              pixelsWidth = width;
              pixelsHeight = height;            
          } else if(pixelsWidth != width || pixelsHeight != height) {
              // ROI changed, reallocate pixels for new size
              delete pixels;
              pixels = new unsigned char[width*height];
              pixelsWidth = width;
              pixelsHeight = height;
          }
          
          // copy from ROI to pixels
          for( int i = 0; i < height; i++ ) {
              memcpy( pixels + (i*width),
                      cvGrayscaleImage->imageData + ((i+roiY)*cvGrayscaleImage->widthStep) + roiX,
                      width );
          }
          bPixelsDirty = false;
      }
          return pixels;        
  }
  
  //--------------------------------------------------------------------------------
  float*  ofxCvFloatImage::getPixelsAsFloats(){
      if(bFloatPixelsDirty) {
          if(floatPixels == NULL) {
              // we need pixels, allocate it
              floatPixels = new float[width*height];
              floatPixelsW = width;
              floatPixelsH = height;            
          } else if(floatPixelsW != width || floatPixelsH != height) {
              // ROI changed, reallocate floatPixels for new size
              delete floatPixels;
              floatPixels = new float[width*height];
              floatPixelsW = width;
              floatPixelsH = height;
          }
          
          // copy from ROI to pixels
          for( int i = 0; i < height; i++ ) {
              memcpy( floatPixels + (i*width),
                      cvImage->imageData + ((i+roiY)*cvImage->widthStep) + roiX*sizeof(float),
                      width*sizeof(float) );
          }
          bFloatPixelsDirty = false;
      }
          return floatPixels;     
  }
  
  // Draw Image
  
  // Image Filter Operations
  
  //--------------------------------------------------------------------------------
  void ofxCvFloatImage::contrastStretch() {
          double minVal, maxVal;
          cvMinMaxLoc( cvImage, &minVal, &maxVal, NULL, NULL, 0 );
      rangeMap( cvImage, minVal,maxVal, scaleMin,scaleMax );
      flagImageChanged();
  }
  
  //--------------------------------------------------------------------------------
  void ofxCvFloatImage::convertToRange(float min, float max ){
      rangeMap( cvImage, scaleMin,scaleMax, min,max);
      flagImageChanged();
  }
  
  // Image Transformation Operations
  
  //--------------------------------------------------------------------------------
  void ofxCvFloatImage::resize( int w, int h ) {
  
      // note, one image copy operation could be ommitted by
      // reusing the temporal image storage
  
      IplImage* temp = cvCreateImage( cvSize(w,h), IPL_DEPTH_32F, 1 );
      cvResize( cvImage, temp );
      clear();
      allocate( w, h );
      cvCopy( temp, cvImage );
      cvReleaseImage( &temp );
  }
  
  //--------------------------------------------------------------------------------
  void ofxCvFloatImage::scaleIntoMe( ofxCvImage& mom, int interpolationMethod ){
      //for interpolation you can pass in:
      //CV_INTER_NN - nearest-neigbor interpolation,
      //CV_INTER_LINEAR - bilinear interpolation (used by default)
      //CV_INTER_AREA - resampling using pixel area relation. It is preferred method 
      //                for image decimation that gives moire-free results. In case of 
      //                zooming it is similar to CV_INTER_NN method.
      //CV_INTER_CUBIC - bicubic interpolation.
          
      if( mom.getCvImage()->nChannels == cvImage->nChannels && 
          mom.getCvImage()->depth == cvImage->depth ) {
      
          if ((interpolationMethod != CV_INTER_NN) &&
              (interpolationMethod != CV_INTER_LINEAR) &&
              (interpolationMethod != CV_INTER_AREA) &&
              (interpolationMethod != CV_INTER_CUBIC) ){
              ofLog(OF_LOG_WARNING, "in scaleIntoMe, setting interpolationMethod to CV_INTER_NN");
                      interpolationMethod = CV_INTER_NN;
              }
          cvResize( mom.getCvImage(), cvImage, interpolationMethod );
          flagImageChanged();
  
      } else {
          ofLog(OF_LOG_ERROR, "in scaleIntoMe, mom image type has to match");
      }
  }
  


(C) Æliens 04/09/2009

You may not copy or print any of this material without explicit permission of the author or the publisher. In case of other copyright issues, contact the author.