src/qvip/qvip.cpp

Go to the documentation of this file.
00001 /*
00002  *      Copyright (C) 2007. PARP Research Group.
00003  *      <http://perception.inf.um.es>
00004  *      University of Murcia, Spain.
00005  *
00006  *      This file is part of the QVision library.
00007  *
00008  *      QVision is free software: you can redistribute it and/or modify
00009  *      it under the terms of the GNU Lesser General Public License as
00010  *      published by the Free Software Foundation, version 3 of the License.
00011  *
00012  *      QVision is distributed in the hope that it will be useful,
00013  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  *      GNU Lesser General Public License for more details.
00016  *
00017  *      You should have received a copy of the GNU Lesser General Public
00018  *      License along with QVision. If not, see <http://www.gnu.org/licenses/>.
00019  */
00020 
00024 
00025 #include <qvip/qvipp/qvipp.h>
00026 #include <qvip/qvip.h>
00027 
00028 #include <stdio.h>
00029 #include <stdlib.h>
00030 #include <iostream>
00031 
00032 void FilterLocalMax(const QVImage<sFloat> &src, QVImage<uChar> &dest, uInt colMaskSize, uInt rowMaskSize, sFloat threshold)
00033         {
00034         const int cols = src.getCols(), rows = src.getRows();
00035         Set(dest,0);
00036         sFloat actual;
00037         QVIMAGE_INIT_READ(sFloat,src);
00038         QVIMAGE_INIT_WRITE(uChar,dest);
00039         for(int row = rowMaskSize; row < rows-rowMaskSize; row++)
00040                 for(int col = colMaskSize; col < cols-colMaskSize; col++)
00041                         {
00042                         actual = QVIMAGE_PIXEL(src, col, row,0);
00043                         if (actual >= threshold)
00044                                 {
00045                                 QVIMAGE_PIXEL(dest, col, row, 0) = IPP_MAX_8U;
00046                                 for (int j = row-rowMaskSize; (j < row+rowMaskSize) && (QVIMAGE_PIXEL(dest, col, row, 0) > 0); j++)
00047                                         for (int i = col-colMaskSize; i < col+colMaskSize; i++)
00048                                                 if ( ((i != col) || (j != row)) && (actual <= QVIMAGE_PIXEL(src, i, j, 0)) )
00049                                                         {
00050                                                         QVIMAGE_PIXEL(dest, col, row, 0) = 0;
00051                                                         break;
00052                                                         }
00053                                 }
00054                         }
00055         }
00056 
00057 void FilterHarrisCornerResponseImage(const QVImage<uChar> &image, QVImage<sFloat> &result)
00058         {
00059         const uInt rows = image.getRows(), cols = image.getCols();
00060         QVImage<uChar> buffer;
00061         MinEigenValGetBufferSize(image, buffer);
00062         QVImage<sFloat> eigval(cols, rows);
00063 
00064         MinEigenVal(image, eigval, buffer);
00065 
00066         result = QVImage<sFloat>(cols, rows);
00067 
00068         FilterEqualizeHistogram(eigval, result);
00069         }
00070 
00071 void FilterDoG(const QVImage<uChar> &image, QVImage<sFloat> &result)
00072         {
00073         const uInt rows = image.getRows(), cols = image.getCols();
00074         QVImage<uChar> gauss3x3(cols, rows), gauss5x5(cols, rows);
00075         
00076         FilterGauss(image, gauss3x3, 3);
00077         FilterGauss(image, gauss5x5, 5);
00078 
00079         result = QVImage<sFloat>(cols, rows);
00080         AbsDiff(gauss3x3, gauss5x5, result);    
00081         }
00082 
00083 void SobelCornerResponseImage(const QVImage<sFloat> &image, QVImage<sFloat> &result)
00084         {
00085         std::cerr << "WARNING: SobelCornerResponseImage is deprecated. Use FilterHessianCornerResponseImage instead." << std::endl;
00086         FilterHessianCornerResponseImage(image, result);
00087         }
00088 
00089 void FilterHessianCornerResponseImage(const QVImage<sFloat> &image, QVImage<sFloat> &result)
00090         {
00091         const uInt      cols = image.getCols(), rows = image.getRows();
00092         //const QVImage<sFloat> imageSFloat = image;
00093 
00094         QVImage<sFloat> Gx(cols, rows), Gy(cols, rows), Gxx(cols, rows),
00095                         Gxy(cols, rows), Gyx(cols, rows), Gyy(cols, rows);
00096 
00097         FilterSobelHorizMask(image,Gx);
00098         FilterSobelVertMask(image,Gy);
00099 
00100         FilterSobelHorizMask(Gx,Gxx);
00101         FilterSobelVertMask(Gy,Gyy);
00102 
00103         FilterSobelHorizMask(Gy,Gyx);
00104         FilterSobelVertMask(Gx,Gxy);
00105 
00106         QVImage<sFloat> GxyGyx(cols, rows), GxxGyy(cols, rows);
00107 
00108         Mul(Gxy, Gyx, GxyGyx);
00109         Mul(Gxx, Gyy, GxxGyy);
00110 
00111         QVImage<sFloat> diffGxyGyx_GxxGyy(cols, rows);
00112 
00113         diffGxyGyx_GxxGyy.setAnchor(4,4);
00114 
00115         Sub(GxyGyx, GxxGyy, diffGxyGyx_GxxGyy);
00116 
00117         QVIMAGE_INIT_WRITE(sFloat,diffGxyGyx_GxxGyy);
00118         for (uInt col = 0; col < cols; col++)
00119                 for(uInt row = 0; row < rows; row++)
00120                         if (QVIMAGE_PIXEL(diffGxyGyx_GxxGyy, col, row, 0) <= 0)
00121                                 QVIMAGE_PIXEL(diffGxyGyx_GxxGyy, col, row, 0) = 0;
00122 
00123         result = QVImage<sFloat>(cols, rows);
00124 
00125         FilterEqualizeHistogram(diffGxyGyx_GxxGyy, result);
00126         }
00127 
00128 
00129 int myFloodFill(QVImage<uChar> &image, uInt x, uInt y, uInt value, uInt minVal, uInt maxVal)
00130         {
00131         // Value should be inside range [minVal, maxVal]
00132         Q_ASSERT( (value <= minVal) || (value >= maxVal) );
00133         Q_ASSERT( minVal <= maxVal );
00134 
00135         // Coordinates should be inside the image.
00136         if ( (x >= image.getCols()) || (y >= image.getRows()))
00137                 return 0;
00138 
00139         if ( (image(x,y) < minVal) || (image(x,y) > maxVal) )
00140                 return 0;
00141 
00142         image(x,y) = value;
00143 
00144         int val = 1;
00145         val += myFloodFill(image, x-1, y, value, minVal, maxVal);
00146         val += myFloodFill(image, x, y-1, value, minVal, maxVal);
00147         val += myFloodFill(image, x+1, y, value, minVal, maxVal);
00148         val += myFloodFill(image, x, y+1, value, minVal, maxVal);
00149 
00150         val += myFloodFill(image, x-1, y-1, value, minVal, maxVal);
00151         val += myFloodFill(image, x-1, y+1, value, minVal, maxVal);
00152         val += myFloodFill(image, x+1, y-1, value, minVal, maxVal);
00153         val += myFloodFill(image, x+1, y+1, value, minVal, maxVal);
00154 
00155         return val;
00156         }
00157 
00159 
00160 #include <qvip/qvimagefeatures/qvcomponenttree.h>
00161 
00162 void pruneLowComponentTreeAux(QVImage<uChar> &image, QVComponentTree &componentTree, uInt minArea, uInt node, uInt validThreshold)
00163         {
00164         Q_ASSERT(componentTree.area(node)[componentTree.firstThreshold(node)] != 0);
00165         Q_ASSERT(componentTree.area(node)[componentTree.lastThreshold(node)] != 0);
00166         Q_ASSERT(validThreshold >= componentTree.lastThreshold(node));
00167 
00168         bool prune = false;
00169         int lastValidThreshold = validThreshold;
00170 
00171         // Here we decide if this node should be directly pruned
00172         // or if there's any sub-node we should prune
00173         for (int threshold = componentTree.lastThreshold(node); threshold >= componentTree.firstThreshold(node) && !prune; threshold--)
00174                 if (componentTree.area(node)[threshold] > 0)
00175                         {
00176                         if (componentTree.area(node)[threshold] < minArea)
00177                                 prune = true;
00178                         else
00179                                 lastValidThreshold = threshold;
00180                         }
00181 
00182         // We prune node, or get on with it's childrens
00183         if (prune)
00184                 myFloodFill(image, componentTree.seedX(node), componentTree.seedY(node), lastValidThreshold, 0, lastValidThreshold-1);
00185         else
00186                 for (uInt child = componentTree.firstChild(node); child != NULL_NODE; child = componentTree.nextSibling(child))
00187                         pruneLowComponentTreeAux(image, componentTree, minArea, child, lastValidThreshold);
00188         }
00189 
00190 void pruneHighComponentTreeAux(QVImage<uChar> &image, QVComponentTree &componentTree, uInt minArea, uInt node, uInt validThreshold)
00191         {
00192         Q_ASSERT(componentTree.area(node)[componentTree.firstThreshold(node)] != 0);
00193         Q_ASSERT(componentTree.area(node)[componentTree.lastThreshold(node)] != 0);
00194         Q_ASSERT(validThreshold >= componentTree.lastThreshold(node));
00195 
00196         bool prune = false;
00197         int lastValidThreshold = validThreshold;
00198 
00199         // Here we decide if this node should be directly pruned
00200         // or if there's any sub-node we should prune
00201         for (int threshold = componentTree.lastThreshold(node); threshold >= componentTree.firstThreshold(node) && !prune; threshold--)
00202                 if (componentTree.area(node)[threshold] > 0)
00203                         {
00204                         if (componentTree.area(node)[threshold] < minArea)
00205                                 prune = true;
00206                         else
00207                                 lastValidThreshold = threshold;
00208                         }
00209 
00210         // We prune node, or get on with it's childrens
00211         if (prune)
00212                 myFloodFill(image, componentTree.seedX(node), componentTree.seedY(node), 255-lastValidThreshold, 255-lastValidThreshold+1, 255-0);
00213         else
00214                 for (uInt child = componentTree.firstChild(node); child != NULL_NODE; child = componentTree.nextSibling(child))
00215                         pruneHighComponentTreeAux(image, componentTree, minArea, child, lastValidThreshold);
00216         }
00217 
00218 void FilterPruneComponentTreeSmallRegions(QVImage<uChar> &image, QVComponentTree &componentTree, uInt minArea)
00219         {
00220         qDebug() << "pruneRegions()";
00221         if (componentTree.isInverseTree())
00222                 {
00223                 if(componentTree.area(componentTree.rootNode())[componentTree.lastThreshold(componentTree.rootNode())] > minArea)
00224                         pruneHighComponentTreeAux(image, componentTree, minArea, componentTree.rootNode(), componentTree.lastThreshold(componentTree.rootNode()));
00225                 }
00226         else    {
00227                 if(componentTree.area(componentTree.rootNode())[componentTree.lastThreshold(componentTree.rootNode())] > minArea)
00228                         pruneLowComponentTreeAux(image, componentTree, minArea, componentTree.rootNode(), componentTree.lastThreshold(componentTree.rootNode()));
00229                 }
00230 
00231         qDebug() << "pruneRegions() <~ return";
00232         }
00233 
00235 
00236 #define DEFINE_QVDTA_FUNCTION_EQUALIZE_HISTOGRAM(TYPE, C)                               \
00237 void FilterEqualizeHistogram(const QVImage<TYPE,C> &image, QVImage<TYPE,C> &equalized)  \
00238         {                                                                               \
00239         uInt    rows = image.getRows(), cols = image.getCols();                         \
00240         TYPE    maxVal, minVal;                                                         \
00241                                                                                         \
00242         Max(image,maxVal);                                                              \
00243         Min(image,minVal);                                                              \
00244                                                                                         \
00245         QVImage<TYPE,C> temp(cols, rows), result(cols, rows);                           \
00246         SubC(image, temp, minVal);                                                      \
00247         MulC(temp, result, 255/(maxVal-minVal));                                        \
00248         equalized = result;                                                             \
00249         }
00250 
00251 DEFINE_QVDTA_FUNCTION_EQUALIZE_HISTOGRAM(uChar,1);
00252 DEFINE_QVDTA_FUNCTION_EQUALIZE_HISTOGRAM(sFloat,1);
00253 
00254 
00255 

Generated on Thu Jul 17 17:23:28 2008 for QVision by  doxygen 1.5.3