Matrix.h
Go to the documentation of this file.
00001 /* Copyright (C) 2012 Christian Lutz, Thorsten Engesser
00002  * 
00003  * This file is part of motld
00004  * 
00005  * Some parts of this implementation are based
00006  * on materials to a lecture by Thomas Brox
00007  * 
00008  * This program is free software: you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation, either version 3 of the License, or
00011  * (at your option) any later version.
00012  * 
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  * 
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00020  */
00021 
00022 
00023 #ifndef MATRIX_H
00024 #define MATRIX_H
00025 
00026 #include <math.h>
00027 #include <stdio.h>
00028 #include <string.h>
00029 #include <stdlib.h>
00030 #include <iostream>
00031 #include <fstream>
00032 #include <string>
00033 #include <queue>
00034 #include <stack>
00035 #include <vector>
00036 #include <algorithm>
00037 #ifdef GNU_COMPILER
00038 #include <strstream>
00039 #else
00040 #include <sstream>
00041 #endif
00042 
00043 #ifndef PI
00044 #define PI 3.1415926536
00045 #endif
00046 
00047 #ifndef round
00048 #define round(x) floor(x + 0.5)
00049 #endif
00050 
00051 #define MAXF(a,b,c,d) MAX(MAX(a,b),MAX(c,d))
00052 #define MINF(a,b,c,d) MIN(MIN(a,b),MIN(c,d))
00053 #ifndef MIN
00054 #define MIN(a,b) (a < b ? a : b)
00055 #define MAX(a,b) (a > b ? a : b)
00056 #endif
00057 
00058 namespace motld {
00059 
00061   struct ObjectBox
00062   {
00064     float x;
00066     float y;
00068     float width;
00070     float height;
00072     int objectId;
00073   };
00074 
00076   class Matrix {
00077   public:
00079     inline Matrix();
00081     inline Matrix(const int width, const int height);
00083     Matrix(const Matrix& copyFrom);
00085     Matrix(const int width, const int height, const float value);
00087     virtual ~Matrix();
00088 
00090     void copyFromCharArray(unsigned char * source);
00092     void copyFromFloatArray(float * source, int srcwidth, int width, int height);
00094     void copyFromFloatArray(const float * const source, int srcwidth, int srcheight, int x, int y, int width, int height);
00096     void fromRGB(const Matrix& rMatrix, const Matrix& gMatrix, const Matrix& bMatrix);
00098     void fromRGB(unsigned char * source);
00100     void derivativeX(Matrix& result) const;
00102     void derivativeY(Matrix& result) const;
00104     void scharrDerivativeX(Matrix& result) const;
00106     void scharrDerivativeY(Matrix& result) const;
00108     void sobelDerivativeX(Matrix& result) const;
00110     void sobelDerivativeY(Matrix& result) const;
00112     void gaussianSmooth(const float sigma, const int filterSize = 0);
00114     void writeToPGM(const char *filename) const;
00116     Matrix getRectSubPix(float centerx, float centery, int width, int height) const;
00117  
00119     void setSize(int width, int height);
00121     void halfSizeImage(Matrix& result) const;
00123     void downsample(int newWidth, int newHeight);
00125     void downsampleBilinear(int newWidth, int newHeight);  
00127     void upsample(int newWidth, int newHeight);
00129     void upsampleBilinear(int newWidth, int newHeight);
00131     void rescale(int newWidth, int newHeight);
00132   
00134     void fill(const float value);
00136     void cut(Matrix& result,const int x1, const int y1, const int x2, const int y2);
00138     void clip(float aMin, float aMax);
00140     void inv3();
00141 
00142     // Some drawing utilities
00144     void drawLine(int x1, int y1, int x2, int y2, float value = 255);
00146     void drawCross(int x, int y, int value = 255, int crossSize = 1);
00148     void drawBox(ObjectBox b, int value = 255);
00150     void drawDashedBox(ObjectBox b, int value = 255, int dashLength = 3, bool dotted = false);
00152     void drawPatch(const Matrix & b, int x, int y, float avg = 0);
00154     void drawHistogram(const float * histogram, int x, int y, int value = 255, int nbins = 7, int psize = 15);
00156     void drawNumber(int x, int y, int n, int value = 255);
00157     
00159     inline float& operator()(const int ax, const int ay) const;
00161     inline Matrix& operator=(const float value);
00163     Matrix& operator=(const Matrix& copyFrom);
00165     Matrix& operator+=(const float value);
00167     Matrix& operator*=(const float value);
00168 
00170     float avg() const;
00172     float norm2() const;
00174     inline int xSize() const;
00176     inline int ySize() const;
00178     inline int size() const;
00180     inline float* data() const;
00181   
00183     Matrix affineWarp(const Matrix & t, const ObjectBox & b, const bool & preservear) const;
00185     static Matrix createWarpMatrix(const float& angle, const float& scale);
00187     float* createSummedAreaTable() const;
00189     float** createSummedAreaTable2() const;
00190   
00191   protected:
00192     int ivWidth, ivHeight;
00193     float *ivData;
00194   };
00195 
00197   Matrix operator*(const Matrix& m1, const Matrix& m2);
00199   std::ostream& operator<<(std::ostream& aStream, const Matrix& aMatrix);
00200 
00202   void writePPM(const char* filename, const Matrix& rMatrix, const Matrix& gMatrix, const Matrix& bMatrix);
00203 
00204 
00205 /**************************************************************************************************
00206  * IMPLEMENTATION                                                                                 *
00207  **************************************************************************************************/ 
00208 
00209   inline Matrix::Matrix()
00210   {
00211 
00212 
00213     ivData = NULL; 
00214     ivWidth = ivHeight = 0;
00215   }
00216 
00217   inline Matrix::Matrix(const int width, const int height)
00218     : ivWidth(width), ivHeight(height)
00219   {
00220     ivData = new float[width*height];
00221   }
00222 
00223   Matrix::Matrix(const Matrix& copyFrom)
00224     : ivWidth(copyFrom.ivWidth), ivHeight(copyFrom.ivHeight)
00225   {
00226     if (copyFrom.ivData == 0) ivData = 0;
00227     else {
00228       int wholeSize = ivWidth*ivHeight;
00229       ivData = new float[wholeSize];
00230       memcpy(ivData, copyFrom.ivData, wholeSize * sizeof(float));
00231       //for (register int i = 0; i < wholeSize; i++)
00232       //  ivData[i] = copyFrom.ivData[i];
00233     }
00234   }
00235 
00236   Matrix::Matrix(const int width, const int height, const float value)
00237     : ivWidth(width), ivHeight(height)
00238   {
00239     ivData = new float[width*height];
00240     fill(value);
00241   }
00242 
00243   Matrix::~Matrix()
00244   {
00245     delete [] ivData;
00246   }
00247 
00248   void Matrix::copyFromCharArray(unsigned char * source)
00249   {
00250     delete [] ivData;
00251     int wholeSize = ivWidth*ivHeight;
00252     ivData = new float[wholeSize];
00253     for (register int i = 0; i < wholeSize; ++i)
00254       ivData[i] = (float)source[i];
00255   }
00256 
00257   void Matrix::copyFromFloatArray(const float * const source, int srcwidth, int srcheight, 
00258                                   int x, int y, int width, int height)
00259   {
00260     delete [] ivData;
00261     ivWidth = width; ivHeight = height;
00262     ivData = new float[width*height];
00263 #pragma omp parallel for
00264     for (int dy = 0; dy < height; ++dy)
00265       memcpy(ivData + dy * width, source + (y + dy) * srcwidth + x, width * sizeof(float));
00266   }
00267 
00268   void Matrix::copyFromFloatArray(float * source, int srcwidth, int width, int height)
00269   {
00270     delete [] ivData;
00271     ivWidth = width; ivHeight = height;
00272     ivData = new float[width*height];
00273     for (int dy = 0; dy < height; ++dy)
00274       memcpy(ivData + dy * width, source + dy * srcwidth, width * sizeof(float));
00275   }
00276 
00277   void Matrix::fromRGB(const Matrix& rMatrix, const Matrix& gMatrix, const Matrix& bMatrix) 
00278   {
00279     //delete [] ivData;
00280     int wholeSize = ivWidth*ivHeight;
00281     //ivData = new float[wholeSize];
00282     float * rData = rMatrix.data();
00283     float * gData = gMatrix.data();
00284     float * bData = bMatrix.data();
00285     for (int i = 0; i < wholeSize; ++i)
00286       ivData[i] = (rData[i] + gData[i] + bData[i]) * (1.0/3.0);
00287   }
00288 
00289   void Matrix::fromRGB(unsigned char * source)
00290   {
00291     //delete [] ivData;
00292     int wholeSize = ivWidth*ivHeight;
00293     //ivData = new float[wholeSize];
00294     unsigned char * green = source + wholeSize;
00295     unsigned char * blue = green + wholeSize;
00296     for (int i = 0; i < wholeSize; ++i)
00297       ivData[i] = ((float)source[i] + (float)green[i] + (float)blue[i]) * (1.0/3.0);
00298   }
00299 
00300   void Matrix::derivativeX(Matrix& result) const
00301   {
00302     result.setSize(ivWidth, ivHeight);
00303     for(int y = 0; y < ivHeight; ++y)
00304     {
00305       result(0,y) = ivData[1 + y*ivWidth] - ivData[y*ivWidth];
00306       for(int x = 1; x < ivWidth-1; ++x)
00307         result(x,y) = (ivData[x+1 +y*ivWidth] - ivData[x-1 +y*ivWidth]); // * 0.5;   
00308       result(ivWidth-1,y) = ivData[ivWidth-1 + y*ivWidth] - ivData[ivWidth-2 + y*ivWidth];   
00309     }
00310   }
00311 
00312   void Matrix::derivativeY(Matrix& result) const
00313   {
00314     result.setSize(ivWidth, ivHeight);
00315     for(int x = 0; x < ivWidth; ++x)
00316     {
00317       result(x,0) = ivData[x + ivWidth] - ivData[x];
00318       result(x,ivHeight-1) = ivData[x + (ivHeight-1)*ivWidth] - ivData[x + (ivHeight-2)*ivWidth];    
00319     }
00320     for(int y = 1; y < ivHeight-1; ++y)
00321       for(int x = 0; x < ivWidth; ++x)
00322         result(x,y) = (ivData[x + (y+1)*ivWidth] - ivData[x + (y-1)*ivWidth]); // * 0.5;   
00323   }
00324 
00326   void Matrix::scharrDerivativeX(Matrix& result) const
00327   {
00328     if(ivWidth * ivHeight == 0)return;
00329     Matrix tmp;
00330     this->derivativeX(tmp); //apply [-1,0,1]
00331     result.setSize(ivWidth, ivHeight);
00332     //apply [3;10;3]
00333     for(int x=0; x<ivWidth; ++x)
00334     {
00335       result(x,0) = 13 * tmp(x,0) + 3 * tmp(x,1);
00336       result(x,ivHeight-1) = 13 * tmp(x,ivHeight-1) + 3 * tmp(x,ivHeight-2);   
00337     }
00338     for(int y = 1; y < ivHeight-1; ++y)
00339       for(int x = 0; x < ivWidth; ++x)
00340         result(x,y) = 3 * (tmp(x,y-1) + tmp(x,y+1)) + 10 * tmp(x,y);   
00341 
00342   }
00343 
00345   void Matrix::scharrDerivativeY(Matrix& result) const
00346   {
00347     if(ivWidth * ivHeight == 0)return;
00348     Matrix tmp;
00349     this->derivativeY(tmp);
00350     result.setSize(ivWidth, ivHeight);
00351     for(int y = 0; y < ivHeight; ++y)
00352     {
00353       result(0,y) = 13 * tmp(0,y) + 3 * tmp(1,y);
00354       for(int x = 1; x < ivWidth-1; ++x)
00355         result(x,y) = 3 * (tmp(x-1,y) + tmp(x+1,y)) + 10 * tmp(x,y);   
00356       result(ivWidth-1,y) = 13 * tmp(ivWidth-1,y) + 3 * tmp(ivWidth-2,y);   
00357     }
00358   }
00359 
00361   void Matrix::sobelDerivativeX(Matrix& result) const
00362   {
00363     if(ivWidth * ivHeight == 0)return;
00364     Matrix tmp;
00365     this->derivativeX(tmp); //apply [-1,0,1]
00366     result.setSize(ivWidth, ivHeight);
00367     //apply [1;2;1]
00368     for(int x=0; x<ivWidth; ++x)
00369     {
00370       result(x,0) = 3 * tmp(x,0) + 1 * tmp(x,1);
00371       result(x,ivHeight-1) = 3 * tmp(x,ivHeight-1) + 1 * tmp(x,ivHeight-2);   
00372       for(int y = 1; y < ivHeight-1; ++y)
00373         result(x,y) = 1 * (tmp(x,y-1) + tmp(x,y+1)) + 2 * tmp(x,y);   
00374     }
00375   }
00376 
00378   void Matrix::sobelDerivativeY(Matrix& result) const
00379   {
00380     if(ivWidth * ivHeight == 0)return;
00381     Matrix tmp;
00382     this->derivativeY(tmp);
00383     result.setSize(ivWidth, ivHeight);
00384     for(int y=0; y<ivHeight; ++y)
00385     {
00386       result(0,y) = 3 * tmp(0,y) + 1 * tmp(1,y);
00387       result(ivWidth-1,y) = 3 * tmp(ivWidth-1,y) + 1 * tmp(ivWidth-2,y);   
00388       for(int x = 1; x < ivWidth-1; ++x)
00389         result(x,y) = 1 * (tmp(x-1,y) + tmp(x+1,y)) + 2 * tmp(x,y);   
00390     }
00391   }
00392 
00393   void Matrix::gaussianSmooth(const float sigma, const int filterSize)
00394   {
00395     Matrix temp(ivWidth, ivHeight, 0);
00396     int fSize = filterSize > 0 ? filterSize : (sigma*6 + 1);
00397     //force to be odd
00398     if (!(fSize%2))
00399       fSize++;
00400     // compute gaussian weights
00401     float* weights = new float[fSize];
00402     float sumWeights = 0;
00403     for (int i = 0; i < fSize; i++)
00404     {
00405       float x = (i - (fSize>>1));
00406       weights[i] =  1.0 / (sqrt(2*PI) * sigma) * exp(-x*x / (2*sigma*sigma));
00407       sumWeights += weights[i];
00408     }
00409     // normalize weights
00410     for (int i = 0; i < fSize; i++)
00411       weights[i] *= 1.0 / sumWeights;
00412     
00413     // apply filter in x-direction  
00414     for (int x = 0; x < ivWidth; x++)
00415       for (int i = 0; i < fSize; i++)
00416       {
00417         int xtemp = x + i - (fSize>>1);
00418         xtemp = xtemp < 0 ? 0 : (xtemp >= ivWidth ? ivWidth-1 : xtemp);
00419         for (int y = 0; y < ivHeight; y++)
00420           temp(x,y) += ivData[xtemp + y*ivWidth] * weights[i];
00421       }      
00422     // apply filter in y-direction  
00423     fill(0);
00424     for (int y = 0; y < ivHeight; y++)
00425       for (int i = 0; i < fSize; i++)
00426       {
00427         int ytemp = y + i - (fSize>>1);
00428         ytemp = ytemp < 0 ? 0 : (ytemp >= ivHeight ? ivHeight-1 : ytemp);
00429         for (int x = 0; x < ivWidth; x++)
00430           ivData[x + y*ivWidth] += temp(x, ytemp) * weights[i];
00431       }
00432     delete [] weights;
00433   }
00434 
00436 //maybe use [1/16 1/4 3/8 1/4 1/16]^2 instead
00437   void Matrix::halfSizeImage(Matrix& result) const 
00438   {  
00439     //downsample in x-direction
00440     Matrix temp((ivWidth+1)>>1, ivHeight);
00441     for (int y = 0; y < ivHeight; ++y)
00442     {
00443       temp(0,y) = 0.75 * ivData[0 + y*ivWidth] + 0.25 * ivData[1 + y*ivWidth];
00444       if (ivWidth%2) //odd
00445         temp(ivWidth>>1,y) = 0.75 * ivData[ivWidth-1 + y*ivWidth] + 0.25 * ivData[ivWidth-2 + y*ivWidth];
00446       for (int x = 1; x < (ivWidth>>1); ++x)
00447         temp(x,y) = 0.5 * ivData[(x<<1) + y*ivWidth] + 0.25 * (ivData[(x<<1)-1 + y*ivWidth] + ivData[(x<<1)+1 + y*ivWidth]);
00448     }  
00449     //downsample in y-direction
00450     result.setSize((ivWidth+1)>>1, (ivHeight+1)>>1);  
00451     for (int x = 0; x < result.ivWidth; ++x)
00452     {
00453       result(x,0) = 0.75 * temp(x,0) + 0.25 * temp(x,1);
00454       if (ivHeight%2) //odd
00455         result(x,ivHeight>>1) = 0.75 * temp(x,ivHeight-1) + 0.25 * temp(x,ivHeight-2);
00456       for (int y = 1; y < (ivHeight>>1); ++y)
00457         result(x,y) = 0.5 * temp(x,y<<1) + 0.25 * (temp(x,(y<<1)-1) + temp(x,(y<<1)+1));
00458     }
00459   }
00460 
00461   void Matrix::writeToPGM(const char *filename) const
00462   {
00463     FILE *aStream;
00464     aStream = fopen(filename,"wb");
00465     // write header
00466     char line[60];
00467     sprintf(line,"P5\n%d %d\n255\n",ivWidth,ivHeight);
00468     fwrite(line,strlen(line),1,aStream);
00469     // write data
00470     for (int i = 0; i < ivWidth*ivHeight; i++) {
00471       char dummy = (char)ivData[i];
00472       fwrite(&dummy,1,1,aStream);
00473     }
00474     fclose(aStream);
00475   }
00476 
00477   Matrix Matrix::getRectSubPix(float centerx, float centery, int width, int height) const
00478   {
00479     Matrix result(width, height);
00480     float cx = centerx - (width-1)*0.5f, cy = centery - (height-1)*0.5f;
00481     int srcx = floor(cx), srcy = floor(cy);
00482     float a = cx - srcx, b = cy - srcy,
00483       a11 = (1.f-a)*(1.f-b),
00484       a12 = a*(1.f-b),
00485       a21 = (1.f-a)*b,
00486       a22 = a*b;
00487     if(srcx >= 0 && srcy >= 0 && srcx+width < ivWidth && srcy+height < ivHeight)
00488     { // patch is completely inside the image
00489       for(int y=0; y<height; ++y)
00490       {
00491         for(int x=0; x<width; ++x)
00492         {
00493           result(x,y) = a11*operator()(srcx+x,srcy+y)
00494             + a12*operator()(srcx+x+1,srcy+y)
00495             + a21*operator()(srcx+x,srcy+y+1)
00496             + a22*operator()(srcx+x+1,srcy+y+1);    
00497         }
00498       }
00499     }else{ 
00500       float avgValue = this->avg();
00501       for(int y=0; y<height; ++y)
00502       {
00503         for(int x=0; x<width; ++x)
00504         {
00505           if(srcx+x<0 || srcx+x+1>=ivWidth || srcy+y<0 || srcy+y+1>=ivHeight)
00506             result(x,y) = avgValue;
00507           else
00508             result(x,y) = a11*operator()(srcx+x,srcy+y)
00509               + a12*operator()(srcx+x+1,srcy+y)
00510               + a21*operator()(srcx+x,srcy+y+1)
00511               + a22*operator()(srcx+x+1,srcy+y+1);  
00512           /*
00513           // copy from border (not very efficient)  
00514           result(x,y) = a11*operator()(MAX(0,MIN(ivWidth-1,srcx+x)),MAX(0,MIN(ivHeight-1,srcy+y)))
00515           + a12*operator()(MAX(0,MIN(ivWidth-1,srcx+x+1)),MAX(0,MIN(ivHeight-1,srcy+y)))
00516           + a21*operator()(MAX(0,MIN(ivWidth-1,srcx+x)),MAX(0,MIN(ivHeight-1,srcy+y+1)))
00517           + a22*operator()(MAX(0,MIN(ivWidth-1,srcx+x+1)),MAX(0,MIN(ivHeight-1,srcy+y+1)));  */  
00518         }
00519       }
00520     }
00521     return result;
00522   }
00523 
00524   void Matrix::setSize(int width, int height)
00525   {
00526     if (ivWidth == width && ivHeight == height)
00527       return;
00528     if (ivData != 0) 
00529       delete[] ivData;
00530     ivData = new float[width*height];
00531     ivWidth = width;
00532     ivHeight = height;
00533   }
00534 
00535   void Matrix::downsample(int newWidth, int newHeight)
00536   {
00537     // Downsample in x-direction
00538     int aIntermedSize = newWidth*ivHeight;
00539     float* aIntermedData = new float[aIntermedSize];
00540     if (newWidth < ivWidth) {
00541       for (int i = 0; i < aIntermedSize; i++)
00542         aIntermedData[i] = 0.0;
00543       float factor = ((float)ivWidth)/newWidth;
00544       for (int y = 0; y < ivHeight; y++) {
00545         int aFineOffset = y*ivWidth;
00546         int aCoarseOffset = y*newWidth;
00547         int i = aFineOffset;
00548         int j = aCoarseOffset;
00549         int aLastI = aFineOffset+ivWidth;
00550         int aLastJ = aCoarseOffset+newWidth;
00551         float rest = factor;
00552         float part = 1.0;
00553         do {
00554           if (rest > 1.0) {
00555             aIntermedData[j] += part*ivData[i];
00556             rest -= part;
00557             part = 1.0;
00558             i++;
00559             if (rest <= 0.0) {
00560               rest = factor;
00561               j++;
00562             }
00563           }
00564           else {
00565             aIntermedData[j] += rest*ivData[i];
00566             part = 1.0-rest;
00567             rest = factor;
00568             j++;
00569           }
00570         }
00571         while (i < aLastI && j < aLastJ);
00572       }
00573     }
00574     else {
00575       float* aTemp = aIntermedData;
00576       aIntermedData = ivData;
00577       ivData = aTemp;
00578     }
00579     // Downsample in y-direction
00580     delete[] ivData;
00581     int aDataSize = newWidth*newHeight;
00582     ivData = new float[aDataSize];
00583     if (newHeight < ivHeight) {
00584       for (int i = 0; i < aDataSize; i++)
00585         ivData[i] = 0.0;
00586       float factor = ((float)ivHeight)/newHeight;
00587       for (int x = 0; x < newWidth; x++) {
00588         int i = x;
00589         int j = x;
00590         int aLastI = ivHeight*newWidth+x;
00591         int aLastJ = newHeight*newWidth+x;
00592         float rest = factor;
00593         float part = 1.0;
00594         do {
00595           if (rest > 1.0) {
00596             ivData[j] += part*aIntermedData[i];
00597             rest -= part;
00598             part = 1.0;
00599             i += newWidth;
00600             if (rest <= 0.0) {
00601               rest = factor;
00602               j += newWidth;
00603             }
00604           }
00605           else {
00606             ivData[j] += rest*aIntermedData[i];
00607             part = 1.0-rest;
00608             rest = factor;
00609             j += newWidth;
00610           }
00611         }
00612         while (i < aLastI && j < aLastJ);
00613       }
00614     }
00615     else {
00616       float* aTemp = ivData;
00617       ivData = aIntermedData;
00618       aIntermedData = aTemp;
00619     }
00620     // Normalize
00621     float aNormalization = ((float)aDataSize)/size();
00622     for (int i = 0; i < aDataSize; i++)
00623       ivData[i] *= aNormalization;
00624     // Adapt size of matrix
00625     ivWidth = newWidth;
00626     ivHeight = newHeight;
00627     delete[] aIntermedData;
00628   }
00629 
00630   void Matrix::downsampleBilinear(int newWidth, int newHeight)
00631   {
00632     int newSize = newWidth*newHeight;
00633     float* newData = new float[newSize];
00634     float factorX = ((float)ivWidth)/newWidth;
00635     float factorY = ((float)ivHeight)/newHeight;
00636     for (int y = 0; y < newHeight; y++)
00637       for (int x = 0; x < newWidth; x++) {
00638         float ax = (x+0.5)*factorX-0.5;
00639         float ay = (y+0.5)*factorY-0.5;
00640         if (ax < 0) ax = 0.0;
00641         if (ay < 0) ay = 0.0;
00642         int x1 = (int)ax;
00643         int y1 = (int)ay;
00644         int x2 = x1+1;
00645         int y2 = y1+1;
00646         float alphaX = ax-x1;
00647         float alphaY = ay-y1;
00648         if (x1 < 0) x1 = 0;
00649         if (y1 < 0) y1 = 0;
00650         if (x2 >= ivWidth) x2 = ivWidth-1;
00651         if (y2 >= ivHeight) y2 = ivHeight-1;
00652         float a = (1.0-alphaX)*ivData[x1+y1*ivWidth]+alphaX*ivData[x2+y1*ivWidth];
00653         float b = (1.0-alphaX)*ivData[x1+y2*ivWidth]+alphaX*ivData[x2+y2*ivWidth];
00654         newData[x+y*newWidth] = (1.0-alphaY)*a+alphaY*b;
00655       }
00656     delete[] ivData;
00657     ivData = newData;
00658     ivWidth = newWidth;
00659     ivHeight = newHeight;
00660   }
00661 
00662   void Matrix::upsample(int newWidth, int newHeight)
00663   {
00664     // Upsample in x-direction
00665     int aIntermedSize = newWidth*ivHeight;
00666     float* aIntermedData = new float[aIntermedSize];
00667     if (newWidth > ivWidth) {
00668       for (int i = 0; i < aIntermedSize; i++)
00669         aIntermedData[i] = 0.0;
00670       float factor = ((float)newWidth)/ivWidth;
00671       for (int y = 0; y < ivHeight; y++) {
00672         int aFineOffset = y*newWidth;
00673         int aCoarseOffset = y*ivWidth;
00674         int i = aCoarseOffset;
00675         int j = aFineOffset;
00676         int aLastI = aCoarseOffset+ivWidth;
00677         int aLastJ = aFineOffset+newWidth;
00678         float rest = factor;
00679         float part = 1.0;
00680         do {
00681           if (rest > 1.0) {
00682             aIntermedData[j] += part*ivData[i];
00683             rest -= part;
00684             part = 1.0;
00685             j++;
00686             if (rest <= 0.0) {
00687               rest = factor;
00688               i++;
00689             }
00690           }
00691           else {
00692             aIntermedData[j] += rest*ivData[i];
00693             part = 1.0-rest;
00694             rest = factor;
00695             i++;
00696           }
00697         }
00698         while (i < aLastI && j < aLastJ);
00699       }
00700     }
00701     else {
00702       float* aTemp = aIntermedData;
00703       aIntermedData = ivData;
00704       ivData = aTemp;
00705     }
00706     // Upsample in y-direction
00707     delete[] ivData;
00708     int aDataSize = newWidth*newHeight;
00709     ivData = new float[aDataSize];
00710     if (newHeight > ivHeight) {
00711       for (int i = 0; i < aDataSize; i++)
00712         ivData[i] = 0.0;
00713       float factor = ((float)newHeight)/ivHeight;
00714       for (int x = 0; x < newWidth; x++) {
00715         int i = x;
00716         int j = x;
00717         int aLastI = ivHeight*newWidth;
00718         int aLastJ = newHeight*newWidth;
00719         float rest = factor;
00720         float part = 1.0;
00721         do {
00722           if (rest > 1.0) {
00723             ivData[j] += part*aIntermedData[i];
00724             rest -= part;
00725             part = 1.0;
00726             j += newWidth;
00727             if (rest <= 0.0) {
00728               rest = factor;
00729               i += newWidth;
00730             }
00731           }
00732           else {
00733             ivData[j] += rest*aIntermedData[i];
00734             part = 1.0-rest;
00735             rest = factor;
00736             i += newWidth;
00737           }
00738         }
00739         while (i < aLastI && j < aLastJ);
00740       }
00741     }
00742     else {
00743       float* aTemp = ivData;
00744       ivData = aIntermedData;
00745       aIntermedData = aTemp;
00746     }
00747     // Adapt size of matrix
00748     ivWidth = newWidth;
00749     ivHeight = newHeight;
00750     delete[] aIntermedData;
00751   }
00752 
00753   void Matrix::upsampleBilinear(int newWidth, int newHeight)
00754   {
00755     int newSize = newWidth*newHeight;
00756     float* newData = new float[newSize];
00757     float factorX = (float)(ivWidth)/(newWidth);
00758     float factorY = (float)(ivHeight)/(newHeight);
00759     for (int y = 0; y < newHeight; y++)
00760       for (int x = 0; x < newWidth; x++) {
00761         float ax = (x+0.5)*factorX-0.5;
00762         float ay = (y+0.5)*factorY-0.5;
00763         if (ax < 0) ax = 0.0;
00764         if (ay < 0) ay = 0.0;
00765         int x1 = (int)ax;
00766         int y1 = (int)ay;
00767         int x2 = x1+1;
00768         int y2 = y1+1;
00769         float alphaX = ax-x1;
00770         float alphaY = ay-y1;
00771         if (x1 < 0) x1 = 0;
00772         if (y1 < 0) y1 = 0;
00773         if (x2 >= ivWidth) x2 = ivWidth-1;
00774         if (y2 >= ivHeight) y2 = ivHeight-1;
00775         float a = (1.0-alphaX)*ivData[x1+y1*ivWidth]+alphaX*ivData[x2+y1*ivWidth];
00776         float b = (1.0-alphaX)*ivData[x1+y2*ivWidth]+alphaX*ivData[x2+y2*ivWidth];
00777         newData[x+y*newWidth] = (1.0-alphaY)*a+alphaY*b;
00778       }
00779     delete[] ivData;
00780     ivData = newData;
00781     ivWidth = newWidth;
00782     ivHeight = newHeight;
00783   }
00784 
00785   void Matrix::rescale(int newWidth, int newHeight)
00786   {
00787     if (ivWidth >= newWidth) {
00788       if (ivHeight >= newHeight) 
00789         downsample(newWidth,newHeight);
00790       else {
00791         downsample(newWidth,ivHeight);
00792         upsample(newWidth,newHeight);
00793       }
00794     }
00795     else {
00796       if (ivHeight >= newHeight) {
00797         downsample(ivWidth,newHeight);
00798         upsample(newWidth,newHeight);
00799       }
00800       else 
00801         upsample(newWidth,newHeight);
00802     }
00803   }
00804 
00805   void Matrix::fill(const float value)
00806   {
00807     int wholeSize = ivWidth*ivHeight;
00808     for (register int i = 0; i < wholeSize; i++)
00809       ivData[i] = value;
00810   }
00811 
00812   void Matrix::cut(Matrix& result,const int x1, const int y1, const int x2, const int y2)
00813   {
00814     result.ivWidth = x2-x1+1;
00815     result.ivHeight = y2-y1+1;
00816     delete[] result.ivData;
00817     result.ivData = new float[result.ivWidth*result.ivHeight];
00818     for (int y = y1; y <= y2; y++)
00819       for (int x = x1; x <= x2; x++)
00820         result(x-x1,y-y1) = operator()(x,y);
00821   }
00822 
00823   void Matrix::clip(float aMin, float aMax)
00824   {
00825     int aSize = size();
00826     for (int i = 0; i < aSize; i++)
00827       if (ivData[i] < aMin) 
00828         ivData[i] = aMin;
00829       else if (ivData[i] > aMax) 
00830         ivData[i] = aMax;
00831   }
00832 
00833   void Matrix::inv3()
00834   {
00835     if (ivWidth != ivHeight || ivWidth != 3) {
00836       std::cerr << "cannot invert non 3x3 matrices!" << std::endl;
00837       return;  
00838     }
00839   
00840     float a,b,c,d,e,f,g,h,k;
00841     a = ivData[0]; b = ivData[3]; c = ivData[6];
00842     d = ivData[1]; e = ivData[4]; f = ivData[7];
00843     g = ivData[2]; h = ivData[5]; k = ivData[8];
00844   
00845     float A = e*k - f*h;
00846     float B = f*g - d*k;
00847     float C = d*h - e*g;
00848     float D = c*h - b*k;
00849     float E = a*k - c*g;
00850     float F = g*b - a*h;
00851     float G = b*f - c*e;
00852     float H = c*d - a*f;
00853     float K = a*e - b*d;
00854   
00855     float det = a*A + b*B + c*C;
00856   
00857     ivData[0] = A/det; ivData[3] = D/det; ivData[6] = G/det;
00858     ivData[1] = B/det; ivData[4] = E/det; ivData[7] = H/det;
00859     ivData[2] = C/det; ivData[5] = F/det; ivData[8] = K/det;
00860 
00861   }
00862 
00863   void Matrix::drawLine(int x1, int y1, int x2, int y2, float value)
00864   {
00865     // vertical line
00866     if (x1 == x2) 
00867     {
00868       if (x1 < 0 || x1 >= ivWidth)   
00869         return;
00870       int x = x1;
00871       if (y1 < y2) 
00872       {
00873         for (int y = y1; y <= y2; y++)
00874           if (y >= 0 && y < ivHeight) 
00875             ivData[y*ivWidth + x] = value;
00876       } else {
00877         for (int y = y1; y >= y2; y--)
00878           if (y >= 0 && y < ivHeight) 
00879             ivData[y*ivWidth + x] = value;
00880       }
00881       return;
00882     }
00883     // horizontal line
00884     if (y1 == y2) 
00885     {
00886       if (y1 < 0 || y1 >= ivHeight)
00887         return;
00888       int y = y1;
00889       if (x1 < x2) 
00890       {
00891         for (int x = x1; x <= x2; x++)
00892           if (x >= 0 && x < ivWidth)
00893             ivData[y*ivWidth + x] = value;
00894       } else {
00895         for (int x = x1; x >= x2; x--)
00896           if (x >= 0 && x < ivWidth) 
00897             ivData[y*ivWidth + x] = value;
00898       }
00899       return;
00900     }
00901     float m = float(y1 - y2) / float(x1 - x2);
00902     float invm = 1.0/m;
00903     if (fabs(m) > 1.0) 
00904     {
00905       if (y2 > y1) 
00906       {
00907         for (int y = y1; y <= y2; y++) 
00908         {
00909           int x = (int)(0.5 + x1 + (y-y1)*invm);
00910           if (x >= 0 && x < ivWidth && y >= 0 && y < ivHeight)
00911             ivData[y*ivWidth + x] = value;
00912         }
00913       } else {
00914         for (int y = y1; y >= y2; y--) 
00915         {
00916           int x = (int)(0.5 + x1 + (y-y1)*invm);
00917           if (x >= 0 && x < ivWidth && y >= 0 && y < ivHeight)
00918             ivData[y*ivWidth + x] = value;
00919         }
00920       }
00921     } else {
00922       if (x2 > x1) 
00923       {
00924         for (int x = x1; x <= x2; x++) 
00925         {
00926           int y = (int)(0.5 + y1 + (x-x1)*m);
00927           if (x >= 0 && x < ivWidth && y >= 0 && y < ivHeight)
00928             ivData[y*ivWidth + x] = value;
00929         }
00930       } else {
00931         for (int x = x1; x >= x2; x--)
00932         {
00933           int y = (int)(0.5 + y1 + (x-x1)*m);
00934           if (x >= 0 && x < ivWidth && y >= 0 && y < ivHeight)
00935             ivData[y*ivWidth + x] = value;
00936         }
00937       }
00938     }
00939   }
00940 
00941   void Matrix::drawCross(int x, int y, int value, int crossSize)
00942   {
00943     if(x > crossSize && y > crossSize && x < ivWidth-crossSize && y < ivHeight-crossSize)
00944       for (int dx = -crossSize; dx <= crossSize; ++dx)
00945       {
00946         int oy = (y+dx)*ivWidth;
00947         ivData[oy+x+dx] = value;
00948         ivData[oy+x-dx] = value;
00949       }
00950   }
00951 
00952   void Matrix::drawBox(ObjectBox b, int value)
00953   {
00954     int x1 = round(b.x), x2 = round(b.x + b.width),
00955       y1 = round(b.y), y2 = round(b.y + b.height);
00956     if(x2 < 0 || y2 < 0 || x1 >= ivWidth || y1 >= ivHeight)
00957       return;
00958     if(y1 >= 0)
00959       for(int i = y1 * ivWidth + std::max(0, x1);
00960           i < y1 * ivWidth + std::min(ivWidth, x2); ++i)
00961         ivData[i] = value;
00962     if(y2 < ivHeight)
00963       for(int i = y2 * ivWidth + std::max(0, x1);
00964           i < y2 * ivWidth + std::min(ivWidth, x2); ++i)
00965         ivData[i] = value;
00966     if(x1 >= 0)
00967       for(int i = std::max(0, y1) * ivWidth + x1;
00968           i < std::min(ivHeight, y2) * ivWidth + x1; i += ivWidth)
00969         ivData[i] = value;
00970     if(x2 < ivWidth)
00971       for(int i = std::max(0, y1) * ivWidth + x2;
00972           i < std::min(ivHeight, y2) * ivWidth + x2; i += ivWidth)
00973         ivData[i] = value;
00974   }
00975 
00976   void Matrix::drawDashedBox(ObjectBox b, int value, int dashLength, bool dotted)
00977   {
00978     int x1 = round(b.x), x2 = round(b.x + b.width),
00979       y1 = round(b.y), y2 = round(b.y + b.height);
00980     if(x2 < 0 || y2 < 0 || x1 >= ivWidth || y1 >= ivHeight)
00981       return;
00982     for (int dx = 0; dx < b.width; ++dx)
00983     {
00984       int i1 = y1 * ivWidth + x1 + dx;
00985       int i2 = y2 * ivWidth + x1 + dx;
00986       if (0 <= i1 && i1 < ivWidth * ivHeight && ((dx%dashLength)>0)^dotted)
00987         ivData[i1] = value;
00988       if (0 <= i2 && i2 < ivWidth * ivHeight && ((dx%dashLength)>0)^dotted)
00989         ivData[i2] = value;
00990     }
00991     for (int dy = 0; dy < b.height; ++dy)
00992     {
00993       int i1 = (y1 + dy) * ivWidth + x1;
00994       int i2 = (y1 + dy) * ivWidth + x2;
00995       if (0 <= i1 && i1 < ivWidth * ivHeight && ((dy%dashLength)>0)^dotted)
00996         ivData[i1] = value;
00997       if (0 <= i2 && i2 < ivWidth * ivHeight && ((dy%dashLength)>0)^dotted)
00998         ivData[i2] = value;
00999     }
01000   }
01001 
01002   void Matrix::drawPatch(const Matrix& b, int x, int y, float avg)
01003   {
01004     for (int dx = 0; dx < b.ivWidth; ++dx)
01005       for (int dy = 0; dy < b.ivHeight; ++ dy)
01006         (*this)(x+dx,y+dy) = b(dx,dy) + avg;
01007   }
01008 
01009   void Matrix::drawHistogram(const float * histogram, int x, int y, int value, int nbins, int psize)
01010   {
01011     int binwidth = nbins > (psize>>1) ? 1 : 2;
01012     if(histogram == NULL)
01013       return;
01014     for (int n = 0; n < nbins; ++n)
01015     {
01016       int binheight = std::min(psize, std::max(0, (int)round(histogram[n] * psize)));
01017       for(int ix = 0; ix < binwidth; ++ix)
01018         for(int iy = 0; iy < binheight; ++iy)
01019           (*this)(x+ix+n*binwidth, y+psize-1-iy) = value;
01020     }
01021   }
01022 
01023   void Matrix::drawNumber(int x, int y, int n, int value)
01024   {
01025     bool chars[10][4*7] = {
01026       {0,1,1,0, 1,0,0,1, 1,0,0,1, 1,0,0,1, 1,0,0,1, 1,0,0,1, 0,1,1,0}, //0
01027       {0,1,1,0, 0,0,1,0, 0,0,1,0, 0,0,1,0, 0,0,1,0, 0,0,1,0, 0,1,1,1}, //1
01028       {0,1,1,0, 1,0,0,1, 0,0,0,1, 0,0,1,0, 0,1,0,0, 1,0,0,0, 1,1,1,1}, //2
01029       {0,1,1,0, 1,0,0,1, 0,0,0,1, 0,1,1,0, 0,0,0,1, 1,0,0,1, 1,1,1,0}, //3
01030       {0,0,1,0, 0,1,1,0, 1,0,1,0, 1,0,1,0, 1,1,1,1, 0,0,1,0, 0,0,1,0}, //4
01031       {1,1,1,1, 1,0,0,0, 1,0,0,0, 1,1,1,0, 0,0,0,1, 0,0,0,1, 1,1,1,0}, //5
01032       {0,1,1,1, 1,1,0,0, 1,0,0,0, 1,1,1,0, 1,0,0,1, 1,0,0,1, 0,1,1,0}, //6
01033       {1,1,1,1, 0,0,0,1, 0,0,0,1, 0,0,1,0, 0,0,1,0, 0,1,0,0, 0,1,0,0}, //7
01034       {0,1,1,0, 1,0,0,1, 1,0,0,1, 0,1,1,0, 1,0,0,1, 1,0,0,1, 0,1,1,0}, //8
01035       {0,1,1,0, 1,0,0,1, 1,0,0,1, 0,1,1,1, 0,0,0,1, 0,0,1,1, 1,1,1,0}}; //9
01036     int a = abs(n), tx = -4;
01037     do {
01038       // draw digits from right to left
01039       int c = a%10;
01040       for (int i = 0; i < 4*7; i++)
01041         if (chars[c][i])
01042         {
01043           int tmpx = x + tx + (i%4), tmpy = y + (i>>2);
01044           if (tmpx >= 0 && tmpy >= 0 && tmpx < ivWidth && tmpy < ivHeight)
01045             (*this)(tmpx, tmpy) = value;   
01046         }
01047       tx -= 5;
01048       a = a/10;
01049     } while(a > 0);
01050     if (n < 0)
01051       // draw a minus sign
01052       for (int i = 1; i < 4; i++){
01053         int tmpx = x + tx + i, tmpy = y + 3;
01054         if (tmpx >= 0 && tmpy >= 0 && tmpx < ivWidth && tmpy < ivHeight)
01055           (*this)(tmpx, tmpy) = value;   
01056       }
01057   }
01058 
01059   inline float& Matrix::operator()(const int ax, const int ay) const
01060   {
01061 #ifdef _DEBUG
01062     if (ax >= ivWidth || ay >= ivHeight || ax < 0 || ay < 0){
01063       std::cerr << "Exception EMatrixRangeOverflow: x = " << ax << ", y = " << ay << std::endl;
01064       return 0;
01065     }
01066 #endif
01067     return ivData[ivWidth*ay+ax];
01068   }
01069 
01070   inline Matrix& Matrix::operator=(const float value)
01071     {
01072       fill(value);
01073       return *this;
01074     }
01075 
01076   Matrix& Matrix::operator=(const Matrix& copyFrom)
01077     {
01078       if (this != &copyFrom) {
01079         if (ivData != 0) delete[] ivData;
01080         ivWidth = copyFrom.ivWidth;
01081         ivHeight = copyFrom.ivHeight;
01082         if (copyFrom.ivData == 0) ivData = 0;
01083         else {
01084           int wholeSize = ivWidth*ivHeight;
01085           ivData = new float[wholeSize];
01086           memcpy(ivData, copyFrom.ivData, wholeSize * sizeof(float));
01087           //for (register int i = 0; i < wholeSize; i++)
01088           //  ivData[i] = copyFrom.ivData[i];
01089         }
01090       }
01091       return *this;
01092     }
01093 
01094   Matrix& Matrix::operator+=(const float value)
01095   {
01096     int wholeSize = ivWidth*ivHeight;
01097     for (int i = 0; i < wholeSize; i++)
01098       ivData[i] += value;
01099     return *this;
01100   }
01101 
01102   Matrix& Matrix::operator*=(const float value)
01103   {
01104     int wholeSize = ivWidth*ivHeight;
01105     for (int i = 0; i < wholeSize; i++)
01106       ivData[i] *= value;
01107     return *this;
01108   }
01109 
01110   float Matrix::avg() const
01111   {
01112     float aAvg = 0;
01113     int aSize = ivWidth*ivHeight;
01114     for (int i = 0; i < aSize; i++)
01115       aAvg += ivData[i];
01116     return aAvg/aSize;
01117   }
01118 
01119   float Matrix::norm2() const
01120   {
01121     double sqSum = 0;
01122     int aSize = ivWidth*ivHeight;
01123     for (int i = 0; i < aSize; i++)
01124       sqSum += ivData[i]*ivData[i];
01125     return sqSum;
01126   }
01127 
01128   inline int Matrix::xSize() const {
01129     return ivWidth;
01130   }
01131 
01132   inline int Matrix::ySize() const {
01133     return ivHeight;
01134   }
01135 
01136   inline int Matrix::size() const {
01137     return ivWidth*ivHeight;
01138   }
01139 
01140   inline float* Matrix::data() const {
01141     return ivData;
01142   }
01143 
01144   Matrix operator*(const Matrix& m1, const Matrix& m2) {
01145     if (m1.xSize() != m2.ySize()){
01146       std::cerr << "cannot multiply incompatible matrices!" << std::endl;
01147       return Matrix();
01148     }
01149     
01150     Matrix result(m2.xSize(),m1.ySize(),0);
01151     for (int y = 0; y < result.ySize(); y++)
01152       for (int x = 0; x < result.xSize(); x++)
01153         for (int i = 0; i < m1.xSize(); i++)
01154           result(x,y) += m1(i,y)*m2(x,i);
01155     return result;
01156   }
01157 
01158   void writePPM(const char* filename, const Matrix& rMatrix, const Matrix& gMatrix, const Matrix& bMatrix)
01159   {
01160     FILE* outimage = fopen(filename, "wb");
01161     int width = rMatrix.xSize(), height = rMatrix.ySize();
01162     fprintf(outimage, "P6 \n");
01163     fprintf(outimage, "%d %d \n255\n", width, height);
01164     for (int y = 0; y < height; y++)
01165       for (int x = 0; x < width; x++)
01166       {
01167         unsigned char tmp = (unsigned char)rMatrix(x,y);
01168         fwrite (&tmp, sizeof(unsigned char), 1, outimage);
01169         tmp = (unsigned char)gMatrix(x,y);
01170         fwrite (&tmp, sizeof(unsigned char), 1, outimage);
01171         tmp = (unsigned char)bMatrix(x,y);
01172         fwrite (&tmp, sizeof(unsigned char), 1, outimage);
01173       }
01174     fclose(outimage);
01175   }
01176 
01177 /* ----------------------------------------------------------
01178  *           Stuff for (fast) Summed AreaTables             *
01179  * ---------------------------------------------------------*/
01180 
01181   inline float* Matrix::createSummedAreaTable() const
01182   {  
01183     int width = ivWidth + 1;
01184     int height = ivHeight + 1;
01185 
01186     float* sat = new float[width*height];
01187 
01188     for (int x = 0; x < width; ++x)
01189       sat[x] = 0;
01190 
01191     int n = 0;
01192     for (int y = 1; y < height; ++y)
01193     {
01194       int yoffset = y * width;
01195       sat[yoffset] = 0;
01196       for (int x = 1; x < width; ++x, ++n)
01197       {
01198         int offset = yoffset + x;
01199         sat[offset] = ivData[n] + sat[offset-1] + sat[offset-width] - sat[offset-width-1];
01200       }
01201     }
01202 
01203     return sat;
01204   }
01205 
01206   inline float** Matrix::createSummedAreaTable2() const
01207   {  
01208     int width = ivWidth + 1;
01209     int height = ivHeight + 1;
01210 
01211     float* sat = new float[width*height];
01212     float* sat2 = new float[width*height];
01213 
01214     for (int x = 0; x < width; ++x)
01215       sat[x] = sat2[x] = 0;
01216 
01217     int n = 0;
01218     for (int y = 1; y < height; ++y)
01219     {
01220       int yoffset = y * width;
01221       sat[yoffset] = sat2[yoffset] = 0;
01222       for (int x = 1; x < width; ++x, ++n)
01223       {
01224         int offset = yoffset + x;
01225         sat[offset] = ivData[n] + sat[offset-1] + sat[offset-width] - sat[offset-width-1];
01226         sat2[offset] = ivData[n]*ivData[n] + sat2[offset-1] + sat2[offset-width] - sat2[offset-width-1];
01227       }
01228     }
01229 
01230     float** result = new float*[2];
01231     result[0] = sat;
01232     result[1] = sat2;
01233     return result;
01234   }
01235 
01236   inline double summedTableArea(float* sat, int width, int x1, int y1, int x2, int y2)
01237   {
01238     ++width; ++x2; ++y2;
01239     return sat[y2*width+x2] - sat[y1*width+x2] - sat[y2*width+x1] + sat[y1*width+x1];
01240   }
01241 
01242   inline double summedTableArea(const float * const sat, int * indices)
01243   {
01244     return sat[indices[0]] - sat[indices[1]] - sat[indices[2]] + sat[indices[3]];
01245   }
01246 
01247   inline int* getSATIndices(int width, int x1, int y1, int x2, int y2)
01248   {
01249     ++width; ++x2; ++y2;
01250     int* result = new int[4];
01251     result[0] = y2*width+x2;
01252     result[1] = y1*width+x2;
01253     result[2] = y2*width+x1;
01254     result[3] = y1*width+x1;
01255     return result;
01256   }
01257 
01258   inline void getSATIndices(int * array, int width, int x1, int y1, int x2, int y2)
01259   {
01260     ++width; ++x2; ++y2;
01261     array[0] = y2*width+x2;
01262     array[1] = y1*width+x2;
01263     array[2] = y2*width+x1;
01264     array[3] = y1*width+x1;
01265   }
01266 
01267   inline int* getSATIndices(int width, int boxw, int boxh)
01268   {
01269     return getSATIndices(width,0,0,boxw-1,boxh-1);
01270   }
01271 
01272 /* ----------------------------------------------------------
01273  *                Stuff for affine warping                  *
01274  * ---------------------------------------------------------*/
01275 
01276   inline Matrix Matrix::affineWarp(const Matrix& t, const ObjectBox& b, const bool& preservear) const
01277   {
01278     float widthHalf = b.width / 2;
01279     float heightHalf = b.height / 2;
01280  
01281     // object space transformation
01282     Matrix ost(3,3);
01283     ost.ivData[0] = 1; ost.ivData[1] = 0; ost.ivData[2] = b.x + widthHalf - 0.5;
01284     ost.ivData[3] = 0; ost.ivData[4] = 1; ost.ivData[5] = b.y + heightHalf - 0.5;
01285     ost.ivData[6] = 0; ost.ivData[7] = 0; ost.ivData[8] = 1;
01286   
01287     Matrix ostinv = ost;
01288     ostinv.ivData[2] = - ostinv.ivData[2];
01289     ostinv.ivData[5] = - ostinv.ivData[5];
01290     Matrix tinv = t; tinv.inv3();
01291   
01292     Matrix trans = ost * tinv * ostinv;
01293   
01294     Matrix result(b.width, b.height);
01295     for (int dx = 0; dx <= b.width-1; ++dx)
01296     {
01297       for (int dy = 0; dy <= b.height-1; ++dy)
01298       { 
01299         Matrix v(1,3);
01300         float x = b.x + dx;
01301         float y = b.y + dy;
01302         v.ivData[0] = x; v.ivData[1] = y; v.ivData[2] = 1;
01303         v = trans * v;
01304       
01305         int x1 = MAX(0,MIN(ivWidth-1,floor(v.ivData[0]))); int x2 = MAX(0,MIN(ivWidth-1,ceil(v.ivData[0])));
01306         int y1 = MAX(0,MIN(ivHeight-1,floor(v.ivData[1]))); int y2 = MAX(0,MIN(ivHeight-1,ceil(v.ivData[1])));
01307         double dx1 = v.ivData[0] - x1; double dy1 = v.ivData[1] - y1;
01308       
01309         result(dx, dy) =
01310           (1-dx1) * ((1-dy1) * (*this)(x1, y1) + dy1 * (*this)(x1,y2))
01311           + dx1 * ((1-dy1) * (*this)(x2, y1) + dy1 * (*this)(x2,y2));
01312       }
01313     }  
01314     return result; 
01315   }
01316 
01317   inline Matrix Matrix::createWarpMatrix(const float& angle, const float& scale)
01318   {
01319     Matrix scm(3,3); 
01320     scm(0, 0) = scale; scm(1, 0) =     0; scm(2, 0) = 0;
01321     scm(0, 1) =     0; scm(1, 1) = scale; scm(2, 1) = 0;
01322     scm(0, 2) =     0; scm(1, 2) =     0; scm(2, 2) = 1;
01323     Matrix anm(3,3);
01324     float ca = cos(angle); float sa = sin(angle);
01325     anm(0, 0) =  ca; anm(1, 0) =  sa; anm(2, 0) = 0;
01326     anm(0, 1) = -sa; anm(1, 1) =  ca; anm(2, 1) = 0;
01327     anm(0, 2) =   0; anm(1, 2) =   0; anm(2, 2) = 1;
01328     Matrix wm = anm * scm;
01329     return wm;
01330   }
01331 
01332 /* ----------------------------------------------------------
01333  *                  box overlap checking                    *
01334  * ---------------------------------------------------------*/
01335 
01336   inline float rectangleOverlap( float minx1, float miny1,
01337                                  float maxx1, float maxy1, float minx2, float miny2,
01338                                  float maxx2, float maxy2 )
01339   {
01340     if (minx1 > maxx2 || maxx1 < minx2 || miny1 > maxy2 || maxy1 < miny2)
01341     {
01342       return 0.0f;
01343     }
01344     else
01345     {
01346       float dx = MIN(maxx2, maxx1)-MAX(minx2, minx1);
01347       float dy = MIN(maxy2, maxy1)-MAX(miny2, miny1);
01348       float area1 = (maxx1-minx1)*(maxy1-miny1);
01349       float area2 = (maxx2-minx2)*(maxy2-miny2);
01350       float avgarea = 0.5 * (area1+area2);
01351       float overlaparea = dx*dy;
01352       return overlaparea/avgarea;
01353     }
01354   }
01355 
01356   inline float rectangleOverlap(const ObjectBox& a, const ObjectBox& b)
01357   {
01358     return rectangleOverlap(a.x, a.y, a.x+a.width, a.y+a.height, 
01359                             b.x, b.y, b.x+b.width, b.y+b.height );
01360   }
01361 
01362 }
01363 
01364 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines


motld
Author(s): Jost Tobias Springenberg, Jan Wuelfing
autogenerated on Wed Dec 26 2012 16:24:49