00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
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
00132 Q_ASSERT( (value <= minVal) || (value >= maxVal) );
00133 Q_ASSERT( minVal <= maxVal );
00134
00135
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
00172
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
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
00200
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
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