00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00024
00025 #include <QVImageCanvas>
00026 #include <qvltmser/qvltmser_ds.h>
00027
00028 QVLtmserBoundary::QVLtmserBoundary(uInt pWidth, uInt pHeight, uInt pGreyLevels)
00029 {
00030 width = pWidth;
00031 height = pHeight;
00032 greyLevels = pGreyLevels;
00033 if (greyLevels == 0)
00034 greyLevels = 256;
00035 if (greyLevels > 0 && width >0 && height > 0)
00036 numPixels = width * height;
00037 else
00038 numPixels = 0;
00039 maxStackPr = 9999;
00040 heap = QVector<uInt>(numPixels,0);
00041 stackLength = QVector<int>(greyLevels,0);
00042 stackStart = QVector<int>(greyLevels,-1);
00043 }
00044
00045 void QVLtmserBoundary::initHeap(QVector<int> &histogram)
00046 {
00047 int index = 0;
00048
00049
00050 for (uInt i = 0; i < greyLevels; i++) {
00051 if (histogram[i] > 0) {
00052 stackStart[i] = index;
00053 index = index + histogram[i];
00054 } else
00055 stackStart[i] = -1;
00056 stackLength[i] = 0;
00057 }
00058 maxStackPr = 9999;
00059 }
00060
00061 void QVLtmserBoundary::pushPixel(uInt greyLevel, uInt pixel)
00062 {
00063 heap[stackStart[greyLevel] + stackLength[greyLevel]] = pixel;
00064 stackLength[greyLevel]++;
00065 if (greyLevel < (uInt)maxStackPr)
00066 maxStackPr = greyLevel;
00067 }
00068
00069 bool QVLtmserBoundary::popPixel(uInt greyLevel, uInt &pixel)
00070 {
00071 if (stackLength[greyLevel] > 0) {
00072 stackLength[greyLevel]--;
00073 pixel = heap[stackStart[greyLevel] + stackLength[greyLevel]];
00074 if (stackLength[greyLevel] == 0)
00075 maxStackPr = getMaxStackPr();
00076 return true;
00077 } else
00078 return false;
00079 }
00080
00081 int QVLtmserBoundary::getMaxStackPr()
00082 {
00083 int resp = -1;
00084 for (uInt i=0; i < greyLevels; i++) {
00085 if (stackLength[i] > 0) {
00086 resp = i;
00087 break;
00088 }
00089 }
00090 return resp;
00091 }
00092
00093 QHash<QPoint,QVMSER> QVLtmserComponent::theSeedList;
00094 uInt QVLtmserComponent::minArea;
00095 uInt QVLtmserComponent::maxArea;
00096 uChar QVLtmserComponent::delta;
00097 float QVLtmserComponent::delta_threshold;
00098
00099 QVLtmserComponent::QVLtmserComponent(uInt pGreyLevel)
00100 {
00101 greyLevel = pGreyLevel;
00102 greyLevelMin = greyLevel;
00103 numPixels = 0;
00104 history = new QVector<uInt>(256,0);
00105 countRefsHistory = 1;
00106 }
00107
00108 QVLtmserComponent::~QVLtmserComponent()
00109 {
00110 countRefsHistory--;
00111 if(countRefsHistory == 0) {
00112 testMSER();
00113 delete history;
00114 }
00115 }
00116
00117 void QVLtmserComponent::setSeed(uInt r, uInt c)
00118 {
00119 seedX = c;
00120 seedY = r;
00121 }
00122
00123 void QVLtmserComponent::addPixel(uChar pGreyLevel)
00124 {
00125 numPixels++;
00126 greyLevel = pGreyLevel;
00127 (*history)[greyLevel]++;
00128 }
00129
00130 void QVLtmserComponent::testMSER()
00131 {
00132 uInt hist_acum[256],acum=0,val;
00133 float merit[256];
00134
00135
00136 for(uChar i=greyLevelMin;i<=greyLevel;i++) {
00137 if ((val=(*history)[i]) != 0)
00138 acum += val;
00139 hist_acum[i] = acum;
00140 }
00141
00142
00143 float min = 1E10;
00144 int indmin = -1;
00145 for(uChar i=greyLevelMin+delta;i<=greyLevel-delta;i++) {
00146 merit[i] = ((float)hist_acum[i+delta] - (float)hist_acum[i-delta]) / (float)hist_acum[i];
00147 if(merit[i]<min) {
00148 min = merit[i];
00149 indmin = i;
00150 }
00151 }
00152
00153 if(indmin == -1)
00154 return;
00155
00156 if (min <= delta_threshold) {
00157 uInt area_mser = hist_acum[indmin];
00158 if(area_mser >= minArea and area_mser <= maxArea) {
00159 if(theSeedList.contains(QPoint(seedX,seedY)))
00160 if(theSeedList[QPoint(seedX,seedY)].merit < min)
00161 return;
00162 theSeedList[QPoint(seedX,seedY)] = QVMSER(seedX,seedY,indmin,min,area_mser);
00163 }
00164 }
00165 }
00166
00167 void QVLtmserComponent::upGreyLevel(uInt newGreyLevel)
00168 {
00169 greyLevel = newGreyLevel;
00170 };
00171
00172 void QVLtmserComponent::addComponent(QVLtmserComponent &otherComponent, uInt newlevel)
00173 {
00174 for(int i=otherComponent.greyLevelMin;i<=otherComponent.greyLevel;i++) {
00175 (*history)[i] += (*otherComponent.history)[i];
00176 }
00177
00178
00179 otherComponent.greyLevel = greyLevel-1;
00180
00181
00182 numPixels += otherComponent.numPixels;
00183 if (otherComponent.greyLevelMin < greyLevelMin) {
00184 greyLevelMin = otherComponent.greyLevelMin;
00185 seedX = otherComponent.seedX;
00186 seedY = otherComponent.seedY;
00187 }
00188
00189 greyLevel = newlevel;
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227 };
00228
00229 QVLtmserComponentStack::QVLtmserComponentStack(uInt pGreyLevels)
00230 {
00231 greyLevels = pGreyLevels;
00232 posTop = -1;
00233 components = new QVector< QVLtmserComponent *>(greyLevels,NULL);
00234 }
00235
00236 QVLtmserComponentStack::~QVLtmserComponentStack()
00237 {
00238 (*components).clear();
00239 delete components;
00240 }
00241
00242 void QVLtmserComponentStack::initComponents()
00243 {
00244 for (uInt i = 0; i < greyLevels; i++)
00245 if ((*components)[i] != NULL) {
00246 delete (*components)[i];
00247 (*components)[i] = NULL;
00248 }
00249 posTop = -1;
00250 }
00251
00252 void QVLtmserComponentStack::pushComponent(uInt aGreyLevel, int r, int c)
00253 {
00254 QVLtmserComponent *aComponent;
00255 if (posTop != -1)
00256 if(aGreyLevel >= (*components)[posTop]-> greyLevel) {
00257 qFatal("Error in QVLtmserComponentStack::pushComponent");
00258 }
00259 aComponent = new QVLtmserComponent(aGreyLevel);
00260 aComponent->setSeed(r,c);
00261 posTop++;
00262 (*components)[posTop] = aComponent;
00263 }
00264
00265 void QVLtmserComponentStack::popComponent()
00266 {
00267 if (posTop == -1)
00268 qFatal("Error in QVLtmserComponentStack::popComponent");
00269 QVLtmserComponent *component = (*components)[posTop];
00270 (*components)[posTop] = NULL;
00271 posTop--;
00272 delete component;
00273 }
00274
00275 int QVLtmserComponentStack::getPosTop()
00276 {
00277 return posTop;
00278 };