00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00024
00025 #include <qvltmser/qvltmser.h>
00026 #include <qvip.h>
00027 #include <qvipp.h>
00028 #include <qvltmser/qvltmser_ds.h>
00029
00030
00031
00032 void processStack(QVLtmserComponentStack &theQVLtmserComponentStack, uInt levelGreyBoundary)
00033 {
00034 int top;
00035 int greyLevel2;
00036 QVLtmserComponent *theComponentTop, *theComponent2;
00037 while(true) {
00038 top = theQVLtmserComponentStack.getPosTop();
00039 if(top != 0)
00040 theComponent2 = (*theQVLtmserComponentStack.components)[top-1];
00041 else {
00042
00043 theComponentTop = (*theQVLtmserComponentStack.components)[top];
00044 theComponentTop->upGreyLevel(levelGreyBoundary);
00045 break;
00046 }
00047 greyLevel2 = theComponent2->greyLevel;
00048 theComponentTop = (*theQVLtmserComponentStack.components)[top];
00049 if (levelGreyBoundary < (uInt)greyLevel2) {
00050 theComponentTop->upGreyLevel(levelGreyBoundary);
00051 break;
00052 } else {
00053 theComponent2->addComponent(*theComponentTop,levelGreyBoundary);
00054 theQVLtmserComponentStack.popComponent();
00055 if (levelGreyBoundary == (uInt)greyLevel2)
00056 break;
00057 }
00058 }
00059 }
00060
00061
00062 QList<QVMSER> getLTMSER(QVImage< uChar > &input_image,
00063 const int minArea, const int maxArea, const int delta,
00064 const float delta_threshold, const unsigned int downscaling)
00065 {
00066 static QVLtmserBoundary *theQVLtmserBoundary = NULL;
00067 static QVLtmserComponentStack *theQVLtmserComponentStack = NULL;
00068 static uInt former_width = 0, former_height = 0;
00069 static const uInt greyLevels=256;
00070 uChar valueOfPixel;
00071 bool visited;
00072 uInt currentGreyLevel, greyLevelNeighbor, indexNeighbor;
00073 int levelGreyBoundary, col = 0, row = 0, cPixel_x, cPixel_y;
00074 uInt currentPixel, neighbor, pixelBoundary;
00075 QVLtmserComponent *theComponentTop;
00076 QVPolyline aContour;
00077 QVImage<uChar> image;
00078 int minAreaScaled=minArea, maxAreaScaled=maxArea;
00079
00080 if(downscaling != 1) {
00081 QVImage<uChar> resized(input_image.getCols()/downscaling,input_image.getRows()/downscaling);
00082 Resize(input_image,resized);
00083 image = resized;
00084 minAreaScaled = minArea/(downscaling*downscaling);
00085 maxAreaScaled = maxArea/(downscaling*downscaling);
00086 } else {
00087 image = input_image;
00088 }
00089
00090 const uInt cols = image.getCols(), rows = image.getRows();
00091
00092 if(cols != former_width or rows != former_height) {
00093
00094 if (theQVLtmserBoundary != NULL)
00095 delete theQVLtmserBoundary;
00096 theQVLtmserBoundary = new QVLtmserBoundary(cols, rows, greyLevels);
00097 if (theQVLtmserComponentStack != NULL)
00098 delete theQVLtmserComponentStack;
00099 theQVLtmserComponentStack = new QVLtmserComponentStack(greyLevels);
00100 former_width = cols;
00101 former_height = rows;
00102 }
00103
00104 theQVLtmserComponentStack->initComponents();
00105
00106
00107 QVLtmserComponent::theSeedList = QHash<QPoint,QVMSER>();
00108 QVLtmserComponent::minArea = minAreaScaled;
00109 QVLtmserComponent::maxArea = maxAreaScaled;
00110 QVLtmserComponent::delta = delta;
00111 QVLtmserComponent::delta_threshold = delta_threshold;
00112
00113 uChar *pimage = image.getWriteData();
00114
00115
00116 AndC(image,0xFE,image);
00117
00118 int imageStep = image.getStep();
00119
00120
00121 QVector< int > histogram = HistogramRange(image);
00122 theQVLtmserBoundary->initHeap(histogram);
00123
00124
00125 currentGreyLevel = pimage[0] & 0xFE;
00126 currentPixel = 0;
00127 valueOfPixel = pimage[0];
00128 pimage[0] = valueOfPixel | 0x01;
00129
00130 theQVLtmserComponentStack->pushComponent(currentGreyLevel,0,0);
00131 while(true) {
00132 cPixel_y = (int)(currentPixel / cols);
00133 cPixel_x = currentPixel - (cPixel_y * cols);
00134
00135 char nn = -1;
00136 while (nn != 3) {
00137
00138 if (nn == -1)
00139 nn = 0;
00140 else
00141 nn++;
00142 switch(nn) {
00143 case 0: row = cPixel_y-1; col = cPixel_x; break;
00144 case 1: row = cPixel_y; col = cPixel_x+1; break;
00145 case 2: row = cPixel_y+1; col = cPixel_x; break;
00146 case 3: row = cPixel_y; col = cPixel_x-1; break;
00147 }
00148 if (row < 0 || col < 0 || static_cast<uInt>(row) >= rows || static_cast<uInt>(col) >= cols)
00149 continue;
00150 indexNeighbor = (row*imageStep) + col;
00151 valueOfPixel = pimage[indexNeighbor];
00152 visited = valueOfPixel & 0x01;
00153 if (visited)
00154 continue;
00155 else {
00156 greyLevelNeighbor = pimage[indexNeighbor] & 0xFE;
00157 valueOfPixel = pimage[indexNeighbor];
00158 pimage[indexNeighbor] = valueOfPixel | 0x01;
00159 if (greyLevelNeighbor >= currentGreyLevel) {
00160
00161 neighbor = (row * cols) + col;
00162 theQVLtmserBoundary->pushPixel(greyLevelNeighbor, neighbor);
00163 } else {
00164
00165
00166
00167 theQVLtmserBoundary->pushPixel(currentGreyLevel, currentPixel);
00168 currentPixel = (row * cols) + col;
00169 cPixel_y = row;
00170 cPixel_x = col;
00171 currentGreyLevel = greyLevelNeighbor;
00172 theQVLtmserComponentStack->pushComponent(currentGreyLevel,row,col);
00173 nn = -1;
00174 }
00175 }
00176 }
00177
00178
00179 theComponentTop = (*theQVLtmserComponentStack->components)[theQVLtmserComponentStack->getPosTop()];
00180 theComponentTop->addPixel(currentGreyLevel);
00181
00182 levelGreyBoundary = theQVLtmserBoundary->maxStackPr;
00183 if (levelGreyBoundary == -1 or not theQVLtmserBoundary->popPixel(levelGreyBoundary, pixelBoundary)) {
00184 int acum=0;
00185 for(uInt i=theComponentTop->greyLevelMin;i<=theComponentTop->greyLevel;i++) {
00186 acum += (*theComponentTop->history)[i];
00187 }
00188
00189 theQVLtmserComponentStack->popComponent();
00190 break;
00191 }
00192
00193
00194 if (levelGreyBoundary > (int)currentGreyLevel)
00195 processStack(*theQVLtmserComponentStack, levelGreyBoundary);
00196 currentPixel = pixelBoundary;
00197 currentGreyLevel = levelGreyBoundary;
00198 }
00199
00200 QList<QVMSER> mser_list;
00201 if(downscaling != 1) {
00202 foreach(QVMSER mser, QVLtmserComponent::theSeedList.values()) {
00203 int tx=downscaling*mser.seed.x(), ty=downscaling*mser.seed.y();
00204 int minvalue = input_image(tx,ty);
00205 for(unsigned int i=0;i<downscaling;i++) {
00206 for(unsigned int j=0;j<downscaling;j++) {
00207 if(tx+i>=input_image.getCols() or ty+j>=input_image.getRows())
00208 continue;
00209 if(input_image(tx+i,ty+j)<minvalue) {
00210 minvalue = input_image(tx+i,ty+j);
00211 tx = tx+i;
00212 ty = ty+j;
00213 }
00214 }
00215 }
00216 mser_list.append(QVMSER(tx,ty,mser.threshold,mser.merit,
00217 mser.area*downscaling*downscaling));
00218 }
00219 } else {
00220 mser_list = QVLtmserComponent::theSeedList.values();
00221 }
00222
00223
00224 return mser_list;
00225 }
00226
00227
00228 QList<QVPolyline> getLTMSERContours(QVImage< uChar > &input_image,QList<QVMSER> mser_list)
00229 {
00230 QVImage< uChar > not_image;
00231
00232 Not(input_image,not_image);
00233 QList<QVPolyline> output_contours;
00234 foreach (QVMSER mser, mser_list) {
00235 QVPolyline polyline = getConnectedSetBorderContourThreshold(not_image,mser.seed, 255-mser.threshold);
00236 output_contours.append(polyline);
00237 }
00238 return output_contours;
00239 }
00240
00241
00242 QList<QVPolyline> getLTMSERContours(QVImage< uChar > &input_image,
00243 const int minArea, const int maxArea, const int delta,
00244 const float delta_threshold,
00245 unsigned int downscaling)
00246 {
00247 QList<QVMSER> mser_list;
00248
00249 mser_list = getLTMSER(input_image,minArea,maxArea,delta,delta_threshold,downscaling);
00250
00251 return getLTMSERContours(input_image,mser_list);
00252 }
00253
00254
00255
00256
00257