EdgeDetect Class Reference

#include <edgeDetect.h>

Collaboration diagram for EdgeDetect:

[legend]
List of all members.

Detailed Description

Definition at line 45 of file edgeDetect.h.

Public Member Functions

 EdgeDetect (QImage *image)
 ~EdgeDetect ()
int getNumClusters ()
PixelClustergetClusters ()
int * getSmoothHist ()
int * getPeaks ()
QImage * getEdgeImage ()
int * getClusterMap ()

Private Member Functions

void allocateAndInitObjects ()
void constructGSLClut ()
void fillLumMapAndLumHistogram ()
void smoothLumHistogram ()
void computeEdgeMagAndGSLCmaps ()
int pixelLum (int x, int y)
void findPixelClusters ()
void computeClusterStatistics ()
void computeClusterThresholds ()
void constructEdgeImage ()
void deallocateObjects ()

Private Attributes

LUTentry LUT [256]
QImage * image
int lumHist [256]
 luminosity and smooth luminosity histograms
int smoothLumHist [256]
int clusterPeaks [256]
int * lumMap
float * edgeMagMap
int * GSLCmap
int numClusters
PixelClusterclusters
int minClusterSize
int maxClusterSize


Constructor & Destructor Documentation

EdgeDetect::EdgeDetect ( QImage *  image  ) 

Definition at line 192 of file edgeDetect.cpp.

References allocateAndInitObjects(), computeClusterStatistics(), computeClusterThresholds(), computeEdgeMagAndGSLCmaps(), constructEdgeImage(), fillLumMapAndLumHistogram(), findPixelClusters(), and smoothLumHistogram().

00193 {                     
00194   //load image
00195   this->image = image;
00196 
00197   //allocate and initialize objects used for edge detection
00198   allocateAndInitObjects();
00199 
00200   //fill lum map and lum histogram
00201   fillLumMapAndLumHistogram();
00202   
00203   //fill smoothed histogram
00204   smoothLumHistogram();
00205   
00206   //compute edge magnitude and GSLC maps
00207   computeEdgeMagAndGSLCmaps();
00208   
00209   //determine pixel clusters
00210   findPixelClusters();
00211   
00212   computeClusterStatistics();  
00213  
00214   computeClusterThresholds();
00215   
00216   constructEdgeImage();
00217 }

EdgeDetect::~EdgeDetect (  ) 

Definition at line 219 of file edgeDetect.cpp.

References deallocateObjects().

00220 {
00221   deallocateObjects();
00222 }


Member Function Documentation

int EdgeDetect::getNumClusters (  ) 

Definition at line 224 of file edgeDetect.cpp.

References numClusters.

Referenced by GrainEditor::GrainEditor().

00225 { return numClusters; }

PixelCluster * EdgeDetect::getClusters (  ) 

Definition at line 227 of file edgeDetect.cpp.

References clusters.

00228 { return clusters; }

int * EdgeDetect::getSmoothHist (  ) 

Definition at line 233 of file edgeDetect.cpp.

References smoothLumHist.

00234 { return smoothLumHist; }

int * EdgeDetect::getPeaks (  ) 

Definition at line 230 of file edgeDetect.cpp.

References clusterPeaks.

00231 { return clusterPeaks; }

QImage * EdgeDetect::getEdgeImage (  ) 

Definition at line 236 of file edgeDetect.cpp.

References image.

00237 {
00238   return image; 
00239 }

int * EdgeDetect::getClusterMap (  ) 

Definition at line 241 of file edgeDetect.cpp.

References clusters, image, lumMap, and numClusters.

Referenced by GrainEditor::GrainEditor().

00242 {
00243   //construct map
00244   int* clusterMap = new int[image->width() * image->height()];
00245   
00246   //iterate over all pixels, determine cluster each pixel belongs to
00247   int i, cluster;
00248   for(i=0; i<image->width()*image->height(); i++)
00249   {
00250     for(cluster=0; cluster<numClusters; cluster++)
00251     {
00252       if( lumMap[i] >= clusters[cluster].minLuminance &&
00253           lumMap[i] <= clusters[cluster].maxLuminance )
00254       {
00255         clusterMap[i] = cluster;
00256         break;
00257       }
00258     } //cluster
00259   } //pixel
00260 
00261   return clusterMap;
00262 }

void EdgeDetect::allocateAndInitObjects (  )  [private]

Definition at line 264 of file edgeDetect.cpp.

References clusterPeaks, constructGSLClut(), edgeMagMap, GSLCmap, image, lumHist, lumMap, and smoothLumHist.

Referenced by EdgeDetect().

00265 {
00266   //initialize: 
00267   //-luminosity histogram
00268   //-smoothed luminosity histogram
00269   //-identified peak regions
00270   int i;
00271   for(i=0; i<256; i++)
00272   { 
00273     lumHist[i] = 0; 
00274     smoothLumHist[i] = 0;
00275     clusterPeaks[i] = 0;
00276   }
00277   
00278   //allocate luminance map
00279   lumMap = new int[image->width() * image->height()];
00280   
00281   //allocate edge magnitude map
00282   edgeMagMap = new float[image->width() * image->height()];
00283   
00284   //allocate GSLC map
00285   GSLCmap = new int[image->width() * image->height()];
00286   
00287   //construct LUT
00288   constructGSLClut();
00289 }

void EdgeDetect::constructGSLClut (  )  [private]

Definition at line 971 of file edgeDetect.cpp.

References LUTentry::direction, LUTentry::ESF, and LUT.

Referenced by allocateAndInitObjects().

00972 {
00973   //----------------------
00974   //First fill entire table with 0 ESF's and invalid directions
00975   int i;
00976   for(i=0; i<256; i++)
00977   {
00978     LUT[i].ESF = 0.0f;
00979     LUT[i].direction = -1;
00980   }
00981   //----------------------
00982   //Next code in all pattern that are highly 
00983   //likely to be on edges as described in the paper
00984   //----------------------
00985   //Pattern (a)
00986 
00987   // ###
00988   // ##.
00989   // ...
00990   LUT[15].ESF = 0.179f;
00991   LUT[15].direction = 3;
00992 
00993   // ...
00994   // .##
00995   // ###
00996   LUT[240].ESF = 0.179f;
00997   LUT[240].direction = 3;
00998 
00999   // ###
01000   // .##
01001   // ...
01002   LUT[23].ESF = 0.179f;
01003   LUT[23].direction = 1;
01004   
01005   // ...
01006   // ##.
01007   // ###
01008   LUT[232].ESF = 0.179f;
01009   LUT[232].direction = 1;
01010    
01011   // ##.
01012   // ##.
01013   // #..
01014   LUT[43].ESF = 0.179f;
01015   LUT[43].direction = 3;
01016   
01017   // ..#
01018   // .##
01019   // .##
01020   LUT[212].ESF = 0.179f;
01021   LUT[212].direction = 3;
01022 
01023   // #..
01024   // ##.
01025   // ##.
01026   LUT[105].ESF = 0.179f;
01027   LUT[105].direction = 1;
01028 
01029   // .##
01030   // .##
01031   // ..#
01032   LUT[150].ESF = 0.179f;
01033   LUT[150].direction = 1;
01034   //----------------------
01035   //Pattern (b)
01036 
01037   // ###
01038   // ###
01039   // ...
01040   LUT[31].ESF = 0.137f;
01041   LUT[31].direction = 2;
01042 
01043   // ...
01044   // ###
01045   // ###
01046   LUT[248].ESF = 0.137f;
01047   LUT[248].direction = 2;
01048   
01049   // ##.
01050   // ##.
01051   // ##.
01052   LUT[107].ESF = 0.137f;
01053   LUT[107].direction = 0;
01054   
01055   // .##
01056   // .##
01057   // .##
01058   LUT[214].ESF = 0.137f;
01059   LUT[214].direction = 0;
01060   //----------------------
01061   //Pattern (c)
01062   
01063   // ###
01064   // .#.
01065   // ...
01066   LUT[7].ESF = 0.126f;
01067   LUT[7].direction = 2;
01068   
01069   // ...
01070   // .#.
01071   // ###
01072   LUT[224].ESF = 0.126f;
01073   LUT[224].direction = 2;
01074 
01075   // #..
01076   // ##.
01077   // #..
01078   LUT[41].ESF = 0.126f;
01079   LUT[41].direction = 0; 
01080   
01081   // ..#
01082   // .##
01083   // ..#
01084   LUT[148].ESF = 0.126f;
01085   LUT[148].direction = 0;
01086   //----------------------
01087   //Pattern (d)
01088   
01089   // ###
01090   // ##.
01091   // #..
01092   LUT[47].ESF = 0.10f;
01093   LUT[47].direction = 3;
01094    
01095   // ..#
01096   // .##
01097   // ###
01098   LUT[244].ESF = 0.10f;
01099   LUT[244].direction = 3;
01100 
01101   // ###
01102   // .##
01103   // ..#
01104   LUT[151].ESF = 0.10f;
01105   LUT[151].direction = 1;
01106 
01107   // #..
01108   // ##.
01109   // ###
01110   LUT[233].ESF = 0.10f;
01111   LUT[233].direction = 1;
01112   //----------------------
01113   //Pattern (e)
01114   
01115   // ##.
01116   // ##.
01117   // ...
01118   LUT[11].ESF = 0.10f;
01119   LUT[11].direction = 3;
01120   
01121   // ...
01122   // .##
01123   // .##
01124   LUT[208].ESF = 0.10f;
01125   LUT[208].direction = 3;
01126 
01127   // .##
01128   // .##
01129   // ...
01130   LUT[22].ESF = 0.10f;
01131   LUT[22].direction = 1;
01132   
01133   // ...
01134   // ##.
01135   // ##.
01136   LUT[104].ESF = 0.10f;
01137   LUT[104].direction = 1; 
01138   //----------------------    
01139 }

void EdgeDetect::fillLumMapAndLumHistogram (  )  [private]

Definition at line 291 of file edgeDetect.cpp.

References image, lumHist, and lumMap.

Referenced by EdgeDetect().

00292 {
00293   int x, y;
00294   QRgb* rgb;
00295   uchar* scanLine;
00296   int lumVal;
00297   for( y=0; y<image->height(); y++)
00298   {   
00299     scanLine = image->scanLine(y);
00300     for( x=0; x<image->width(); x++)
00301     {
00302       //get lum value for this pixel
00303       rgb = ((QRgb*)scanLine+x);
00304       lumVal = qGray(*rgb);
00305       
00306       //store in lum map
00307       lumMap[x + y*image->width()] = lumVal;
00308       
00309       //update lum histogram
00310       lumHist[ lumVal ]++;
00311     }
00312   }
00313 }

void EdgeDetect::smoothLumHistogram (  )  [private]

Definition at line 315 of file edgeDetect.cpp.

References FILTER_SIZE, lumHist, and smoothLumHist.

Referenced by EdgeDetect().

00316 {
00317   #define FILTER_SIZE 5
00318   int filter[FILTER_SIZE] = {2, 5, 8, 5, 2};
00319   
00320   int i,j;
00321   int filterIndex, sum, total;
00322   for(i = 0; i<256; i++)
00323   {
00324     sum = 0;
00325     total = 0;
00326     
00327     for( j= -FILTER_SIZE/2; j <= FILTER_SIZE/2; j++)
00328     {
00329       if( i+j > 0 && i+j < 256 )
00330       {
00331         filterIndex = j+ FILTER_SIZE/2;
00332         total+= filter[filterIndex] * lumHist[i+j];
00333         sum  += filter[filterIndex];
00334       }
00335     }
00336     
00337     smoothLumHist[i] = total / sum;
00338   }
00339 }

void EdgeDetect::computeEdgeMagAndGSLCmaps (  )  [private]

Definition at line 341 of file edgeDetect.cpp.

References edgeMagMap, GSLCmap, image, and pixelLum().

Referenced by EdgeDetect().

00342 {
00343   int x, y;
00344   int idealPattern[9];
00345   int pixelLums[9];
00346   
00347   //-------  
00348   //iterate over all pixels
00349   for( y=0; y<image->height(); y++)
00350   {   
00351     for( x=0; x<image->width(); x++)
00352     {
00353       //compute pixel luminances for entire grid
00354       pixelLums[0] = pixelLum(x-1,y-1);
00355       pixelLums[1] = pixelLum(x  ,y-1);
00356       pixelLums[2] = pixelLum(x+1,y-1);
00357       pixelLums[3] = pixelLum(x-1,y  );
00358       pixelLums[4] = pixelLum(x  ,y  );
00359       pixelLums[5] = pixelLum(x+1,y  );
00360       pixelLums[6] = pixelLum(x-1,y+1);
00361       pixelLums[7] = pixelLum(x  ,y+1);
00362       pixelLums[8] = pixelLum(x+1,y+1);
00363       
00364       //compute average
00365       float avg = 0;
00366       int i;
00367       for(i=0; i<=8; i++)
00368       {
00369         avg+= pixelLums[i];
00370       }
00371       avg = avg / 9;
00372       
00373       //determine ideal pattern and I0 and I1 averages
00374       int centerPixelLum = pixelLums[4];
00375       float centerDiff = centerPixelLum - avg;
00376       
00377       float I0avg = 0;
00378       int I0count = 0;
00379       
00380       float I1avg = 0;
00381       int I1count = 0;
00382       
00383       for(i=0; i<=8; i++)
00384       {
00385         if( centerDiff * (pixelLums[i]-avg) >=0 )
00386         { 
00387           I1avg+=pixelLums[i];
00388           I1count++;
00389           idealPattern[i] = 1; 
00390         }
00391         else 
00392         { 
00393           I0avg+=pixelLums[i];
00394           I0count++;
00395           idealPattern[i] = 0; 
00396         }
00397       }
00398 
00399       //compute and store edge magnitude
00400       if(I0count > 0) I0avg = I0avg/I0count;
00401       if(I1count > 0) I1avg = I1avg/I1count;     
00402       edgeMagMap[x + y*image->width()] = QABS( I1avg - I0avg );
00403       
00404       //compute and store GSLC
00405       int GSLC=0;
00406       int weight = 1;
00407       for(i=0; i<9; i++)
00408       {
00409         //skip center
00410         if(i == 4) continue;
00411         
00412         if(idealPattern[i] == 1)
00413         { GSLC+=weight; }
00414         
00415         weight = weight*2;
00416       }
00417       GSLCmap[x + y*image->width()] = GSLC;
00418     } //x
00419   } //y
00420 }

int EdgeDetect::pixelLum ( int  x,
int  y 
) [private]

Definition at line 422 of file edgeDetect.cpp.

References image, and lumMap.

Referenced by computeEdgeMagAndGSLCmaps().

00423 {
00424   int clampedX = QMAX( QMIN( x, image->width()-1), 0);
00425   int clampedY = QMAX( QMIN( y, image->height()-1), 0);
00426   return lumMap[ clampedX + clampedY * image->width() ];
00427 }

void EdgeDetect::findPixelClusters (  )  [private]

Definition at line 429 of file edgeDetect.cpp.

References clusterPeaks, clusters, PixelCluster::maxLuminance, PixelCluster::minLuminance, numClusters, and smoothLumHist.

Referenced by EdgeDetect().

00430 {
00431   //find max count
00432   int maxCount = 0;
00433   int i;
00434   for(i=0; i<256; i++)
00435   {
00436     if(smoothLumHist[i] > maxCount)
00437       maxCount = smoothLumHist[i];
00438   }
00439 
00440   //compute JND for histogram (2% of total spread)
00441   int histJND = maxCount/50;
00442 
00443   //construct temporary array for valley locations
00444   //1's will indicate a valley midpoint
00445   int tmpValleyArray[256];
00446   for(i=0; i<256; i++) { tmpValleyArray[i] = 0; }
00447   
00448   //move across histogram finding valley midpoints
00449   int curTrackedMin = smoothLumHist[0];
00450   
00451   //first and last indices tracked min was observed
00452   int firstMinIndex = 0;
00453   int lastMinIndex = 0;
00454   
00455   //only add valley midpoint if finished tracking a descent
00456   bool slopeNeg = false;
00457   
00458   for(i = 1; i<256; i++ )
00459   {
00460     if( smoothLumHist[i] < curTrackedMin - histJND )
00461     {
00462       //found a descent!
00463       slopeNeg = true;
00464       curTrackedMin = smoothLumHist[i];
00465       firstMinIndex = i;
00466     }
00467     //starting to go up again, add last min to list
00468     else if( smoothLumHist[i] > curTrackedMin + histJND )
00469     {
00470       //if finished tracing a negative slope find midpoint and set location to true
00471       if(slopeNeg)
00472       {
00473         tmpValleyArray[ (firstMinIndex + lastMinIndex)/2 ] = 1;
00474       }
00475       
00476       curTrackedMin = smoothLumHist[i];
00477       slopeNeg = false;
00478     }
00479     else
00480     {
00481       //still tracking a min, update the right 
00482       //hand index. center of valley is found
00483       //by averaging first and last min index
00484       lastMinIndex = i;
00485     }
00486   }
00487   
00488   //count valleys
00489   int numValleys = 0;
00490   for(i=0; i<256; i++)
00491   {
00492     if(tmpValleyArray[i] == 1 ) numValleys++;
00493   }
00494 
00495   //determine number of clusters
00496   numClusters = numValleys-1;
00497   if(tmpValleyArray[0] != 1)
00498     numClusters++;
00499   if(tmpValleyArray[255] != 1)
00500     numClusters++;
00501   
00502   //allocate clusters
00503   clusters = new PixelCluster[numClusters];
00504   
00505   //automatically start first cluster
00506   int cluster=0;
00507   clusters[cluster].minLuminance = 0;
00508   
00509   //initialize left and right boundaries of all clusters
00510   for(i=1; i<256; i++)
00511   {
00512     //reached next valley, end cluster
00513     if( tmpValleyArray[i] == 1)
00514     {
00515       clusters[cluster].maxLuminance = i-1;
00516       cluster++;
00517       clusters[cluster].minLuminance = i;
00518     }
00519     //end last cluster automatically at end
00520     else if(i == 255)
00521     {
00522       clusters[cluster].maxLuminance = i;
00523     }
00524   }
00525   
00526   //determine cluster peaks
00527   for(cluster=0; cluster<numClusters; cluster++)
00528   {
00529     //find max for current cluster
00530     int maxIndex = clusters[cluster].minLuminance;
00531     for(i=clusters[cluster].minLuminance; i<=clusters[cluster].maxLuminance; i++)
00532     {
00533       if(smoothLumHist[i] > smoothLumHist[maxIndex])
00534          maxIndex = i;
00535     }
00536     
00537     //mark peaks  
00538     int lumJND = 255/50;
00539     for(i=QMAX(0, maxIndex-lumJND); i<QMIN(256, maxIndex+lumJND); i++)
00540     { 
00541       clusterPeaks[i] = 1; 
00542     }
00543   }
00544 }

void EdgeDetect::computeClusterStatistics (  )  [private]

Definition at line 546 of file edgeDetect.cpp.

References clusterPeaks, clusters, PixelCluster::edgeMagHistogram, edgeMagMap, image, lumMap, maxClusterSize, minClusterSize, PixelCluster::mode, numClusters, PixelCluster::numPixels, PixelCluster::pixelCount, and PixelCluster::totalEdgeMagnitude.

Referenced by EdgeDetect().

00547 {
00548   //initialize cluster stats
00549   int cluster;
00550   for(cluster=0; cluster<numClusters; cluster++)
00551   {
00552     int i;
00553     for(i=0; i<256; i++)
00554     {
00555       clusters[cluster].edgeMagHistogram[i] = 0;
00556     }
00557     clusters[cluster].totalEdgeMagnitude=0.0f;
00558     clusters[cluster].numPixels = 0;
00559   }
00560   
00561   //iterate over all pixels
00562   int i;
00563   for(i=0; i<image->width()*image->height(); i++)
00564   {
00565     //skip pixels that don't belong to peaks
00566     if( clusterPeaks[ lumMap[i] ] != 1)
00567       continue;
00568     
00569     //determine cluster pixel belongs to
00570     int cluster;
00571     for(cluster=0; cluster<numClusters; cluster++)
00572     {
00573       if( lumMap[i] >= clusters[cluster].minLuminance &&
00574           lumMap[i] <= clusters[cluster].maxLuminance )
00575       {      
00576         clusters[cluster].totalEdgeMagnitude+= edgeMagMap[i]; 
00577         clusters[cluster].numPixels++;
00578         clusters[cluster].edgeMagHistogram[ QMIN( QMAX( (int)edgeMagMap[i], 0), 255) ]++;
00579         break;
00580       }
00581     } //cluster
00582   } //pixel i
00583   
00584   //iterate over clusters to determine min and max peak cluster sizes
00585   minClusterSize = clusters[0].numPixels;
00586   maxClusterSize = clusters[0].numPixels;
00587   for(cluster=1; cluster<numClusters; cluster++)
00588   {
00589     if(clusters[cluster].numPixels < minClusterSize)
00590       minClusterSize = clusters[cluster].numPixels;
00591 
00592     if(clusters[cluster].numPixels > maxClusterSize)
00593       maxClusterSize = clusters[cluster].numPixels;
00594   }
00595 
00596   //iterate over clusters one final time to deduce normalized inputs to fuzzy logic process
00597   int JND = 255/50;
00598   for(cluster=0; cluster<numClusters; cluster++)
00599   {
00600     clusters[cluster].meanMode = QMIN( clusters[cluster].totalEdgeMagnitude / clusters[cluster].numPixels,
00601                                        3*JND );
00602     
00603     int i;
00604     int mode = 0;
00605     for(i=1; i<256; i++)
00606     {
00607       if( clusters[cluster].edgeMagHistogram[i] > clusters[cluster].edgeMagHistogram[ mode ] )
00608         mode = i;
00609     }
00610     clusters[cluster].mode = QMIN( mode, 2*JND );
00611         
00612     clusters[cluster].pixelCount = ((float)(clusters[cluster].numPixels - minClusterSize)) / 
00613                                    (maxClusterSize - minClusterSize);  
00614   }
00615 }

void EdgeDetect::computeClusterThresholds (  )  [private]

Definition at line 618 of file edgeDetect.cpp.

References b, B, PixelCluster::beta, clusters, PixelCluster::edgeThreshold, PixelCluster::mode, and numClusters.

Referenced by EdgeDetect().

00619 {
00620   //iterate over each cluster
00621   int cluster;
00622   float S1,M1,L1;
00623   float S2,M2,L2;
00624   float S3,L3;
00625   float outS, outM, outL;
00626   
00627   int JND = 255/50;
00628   
00629   for(cluster=0; cluster<numClusters; cluster++)
00630   {
00631     //----
00632     //compute S,M, and L values for each input
00633     //----
00634     S1 = QMAX( 1.0f - ((clusters[cluster].meanMode/JND) / 1.5f), 0 );
00635 
00636     if( (clusters[cluster].meanMode/JND) <= 1.5f )
00637       M1 = QMAX( (clusters[cluster].meanMode/JND) - 0.5f, 0 );
00638     else
00639       M1 = QMAX( 2.5f - (clusters[cluster].meanMode/JND), 0 );
00640     
00641     L1 = QMAX( ((clusters[cluster].meanMode/JND) - 1.5f) / 1.5f, 0 );
00642     //----
00643     S2 = QMAX( 1.0f - (clusters[cluster].mode/JND), 0 );
00644     
00645     if( (clusters[cluster].mode/JND) <= 1.0f )
00646       M2 = QMAX( -1.0f + 2*(clusters[cluster].mode/JND), 0 );
00647     else
00648       M2 = QMAX( 3.0f - 2*(clusters[cluster].mode/JND), 0 );
00649     
00650     L2 = QMAX( (clusters[cluster].mode/JND) - 1.0, 0 );
00651     //----
00652     S3 = QMAX( 1.0f - 2*clusters[cluster].pixelCount, 0 );
00653     L3 = QMAX( -1.0f + 2*clusters[cluster].pixelCount, 0 );
00654     //----
00655     
00656     //Compute M,L for outputs using set of 18 rules.
00657     //outS is inherantly S given the ruleset provided
00658     outS = 0.0f;
00659     outM = 0.0f;
00660     outL = 0.0f;
00661     //Out 1
00662     if( numClusters > 2 )
00663     {
00664       outM += S1*S2*S3;   //rule 1
00665       
00666       //rule 2
00667       if( clusters[cluster].meanMode < clusters[cluster].mode )
00668         outS += S1*S2*L3;   
00669       else
00670         outM += S1*S2*L3;
00671 
00672       outM += S1*M2*S3;   //rule 3
00673       outM += S1*M2*L3;   //rule 4
00674       outM += S1*L2*S3;   //rule 5
00675       outM += S1*L2*L3;   //rule 6
00676       outM += M1*S2*S3;   //rule 7
00677       outM += M1*S2*L3;   //rule 8
00678       outM += M1*M2*S3;   //rule 9
00679       outL += M1*M2*L3;   //rule 10
00680       outM += M1*L2*S3;   //rule 11
00681       outL += M1*L2*L3;   //rule 12
00682       outM += L1*S2*S3;   //rule 13
00683       outL += L1*S2*L3;   //rule 14
00684       outM += L1*M2*S3;   //rule 15
00685       outL += L1*M2*L3;   //rule 16
00686       outL += L1*L2*S3;   //rule 17
00687       outL += L1*L2*L3;   //rule 18
00688     }
00689     //Out 2
00690     else
00691     {
00692       outL += S1*S2*S3;   //rule 1
00693       outL += S1*S2*L3;   //rule 2
00694       outM += S1*M2*S3;   //rule 3
00695       outL += S1*M2*L3;   //rule 4
00696       outM += S1*L2*S3;   //rule 5
00697       outM += S1*L2*L3;   //rule 6
00698       outL += M1*S2*S3;   //rule 7
00699       outL += M1*S2*L3;   //rule 8
00700       outL += M1*M2*S3;   //rule 9
00701       outL += M1*M2*L3;   //rule 10
00702       outL += M1*L2*S3;   //rule 11
00703       outL += M1*L2*L3;   //rule 12
00704       outL += L1*S2*S3;   //rule 13
00705       outL += L1*S2*L3;   //rule 14
00706       outL += L1*M2*S3;   //rule 15
00707       outL += L1*M2*L3;   //rule 16
00708       outL += L1*L2*S3;   //rule 17
00709       outL += L1*L2*L3;   //rule 18
00710     }
00711 
00712     //find centroid - Beta[k]
00713     float A = outM + 0.5f;
00714     float B = 2.5f - outM;
00715     float C = 1.5f * (outL + 1);
00716     float D = 1.5f * (outM + 1);
00717     float E = 2.5f - outL;
00718 
00719     //---------------------------------------------------------------
00720     //Case 1: Both outM and outL are above intersection point of diagonals
00721     if( outM > 0.5f && outL > 0.5f )
00722     {
00723       //find area of 7 subregions
00724       float area1 = ((A-0.5f)*outM)/2;
00725       float area2 = outM * (B-A);
00726       float area3 = ((2.1f-B) * (outM - 0.5)) / 2;
00727       float area4 = (2.1 - B) * 0.5f;
00728       float area5 = ((C - 2.1f) * (outL - 0.5)) / 2;
00729       float area6 = (C - 2.1f) * 0.5f;
00730       float area7 = (3.0f - C) * outL;
00731      
00732       //find half of total area
00733       float halfArea = (area1 + area2 + area3 + area4 + area5 + area6 + area7) / 2;
00734       
00735       //determine which region split will be within and resulting horizontal midpoint
00736       
00737       //Within area 1
00738       if( area1 > halfArea )
00739       {
00740         clusters[cluster].beta = 0.5f + (float)sqrt(2*halfArea);       
00741       }
00742       //Within area 2
00743       else if( area1 + area2 > halfArea )
00744       {
00745         clusters[cluster].beta = ((halfArea - area1) / outM) + A;        
00746       }
00747       //Within area 3-4
00748       else if( area1 + area2 + area3 + area4 > halfArea )
00749       {
00750         float a = -0.5f;
00751         float b = 2.8f;
00752         float c = area1 + area2 + area3 - halfArea - B/2 - 2.625f;
00753         clusters[cluster].beta = (-b + (float)sqrt( b*b - 4*a*c )) / (2*a);
00754       }
00755       //Within area 5-6
00756       else if( area1 + area2 + area3 + area4 + area5 + area6 > halfArea )
00757       {
00758         float a = 1.0f/3;
00759         float b = -0.7f;
00760         float c = area1 + area2 + area3 + area4 - halfArea;
00761         clusters[cluster].beta = (-b + (float)sqrt( b*b - 4*a*c )) / (2*a);
00762       }
00763       //Within area 7
00764       else
00765       {
00766         clusters[cluster].beta = ((halfArea - (area1 + area2 + area3 + area4 + area5 + area6) ) / outL) + C;       
00767       }
00768     } //end case 1
00769     //---------------------------------------------------------------
00770     //Case 2
00771     else if ( outM < 0.5f && outL > outM )
00772     {
00773       //find area of 5 subregions
00774       float area1 = (outM*(A-0.5f)) / 2;
00775       float area2 = (D-A) * outM;
00776       float area3 = ((C-D) * (outL - outM)) / 2;
00777       float area4 = (C-D) * outM;
00778       float area5 = (3.0f - C) * outL;
00779       
00780       //find half of total area
00781       float halfArea = (area1 + area2 + area3 + area4 + area5) / 2;
00782       
00783       //determine which region split will be within and resulting horizontal midpoint
00784 
00785       //Within area 1
00786       if( area1 > halfArea )
00787       {
00788         clusters[cluster].beta = 0.5f + (float)sqrt(2*halfArea);
00789       }
00790       //Within area 2
00791       else if( area1 + area2 > halfArea )
00792       {
00793         clusters[cluster].beta = ((halfArea - area1) / outM) + A;
00794       }
00795       //Within area 3-4
00796       else if( area1 + area2 + area3 + area4 > halfArea )
00797       {
00798         float a = 1.0f/3.0f;
00799         float b = outM - 0.5f - D/3;
00800         float c = area1 + area2 - D*outM + D/2 - halfArea;
00801         clusters[cluster].beta = (-b + (float)sqrt( b*b - 4*a*c )) / (2*a);
00802       }
00803       //Within area5
00804       else
00805       {
00806         clusters[cluster].beta = ((halfArea - (area1 + area2 + area3 + area4) ) / outL) + C;
00807       }
00808     } //end case 2
00809     //---------------------------------------------------------------
00810     //Case 3
00811     else
00812     {
00813       //find area of 5 subregions
00814       float area1 = (outM*(A-0.5f)) / 2;
00815       float area2 = (B-A) * outM;
00816       float area3 = ((E-B) * (outM - outL)) / 2;
00817       float area4 = (E-B) * outL;
00818       float area5 = (3.0f - E) * outL;
00819       
00820       //find half of total area
00821       float halfArea = (area1 + area2 + area3 + area4 + area5) / 2;
00822       
00823       //determine which region split will be within and resulting horizontal midpoint
00824       
00825       //Within area 1
00826       if( area1 > halfArea )
00827       {
00828         clusters[cluster].beta = 0.5f + (float)sqrt(2*halfArea);
00829       }
00830       //Within area 2
00831       else if( area1 + area2 > halfArea )
00832       {
00833         clusters[cluster].beta = ((halfArea - area1) / outM) + A;
00834       }
00835       //Within area 3-4
00836       else if( area1 + area2 + area3 + area4 > halfArea )
00837       {
00838         float a = -0.5f;
00839         float b = E/2 + 2.5f/2; 
00840         float c = area3 - 2.5f*E/2;
00841         clusters[cluster].beta = (-b + (float)sqrt( b*b - 4*a*c )) / (2*a);
00842       }
00843       //Within area5
00844       else
00845       {
00846         clusters[cluster].beta = ((halfArea - (area1 + area2 + area3 + area4) ) / outL) + E;
00847       }
00848     } //end case 3
00849     //---------------------------------------------------------------
00850     
00851     //Compute edge threshold
00852     int lumJND = 255/50;
00853     clusters[cluster].edgeThreshold = clusters[cluster].mode + clusters[cluster].beta*lumJND;
00854 
00855   } //end for cluster
00856   
00857 }

void EdgeDetect::constructEdgeImage (  )  [private]

Definition at line 859 of file edgeDetect.cpp.

References blurImage(), clusters, LUTentry::direction, edgeMagMap, enhanceImageContrast(), LUTentry::ESF, GSLCmap, height, image, lumMap, LUT, numClusters, and width.

Referenced by EdgeDetect().

00860 {
00861   int x, y;
00862   QRgb* rgb;
00863   
00864   uchar* scanLine;
00865   for( y=0; y<image->height(); y++)
00866   {   
00867     scanLine = image->scanLine(y);
00868     for( x=0; x<image->width(); x++)
00869     {
00870       //initialize pixel to black 
00871       rgb = ((QRgb*)scanLine+x);
00872       *rgb = qRgb( 0, 0, 0 );
00873       
00874       //lookup ESF for this pixel
00875       float ESF = LUT[ GSLCmap[x + y*image->width()] ].ESF;
00876 
00877       //If ESF value for this pixel is 0 skip
00878       if( ESF == 0.0f ) continue;
00879 
00880       //lookup edge magnitude threshold
00881       float lum = lumMap[x + y*image->width()];
00882       float edgeMagThresh = -1.0f;
00883       int cluster;
00884       for(cluster=0; cluster<numClusters; cluster++)
00885       {
00886         if(lum >= clusters[cluster].minLuminance &&
00887            lum <= clusters[cluster].maxLuminance)
00888         {
00889           edgeMagThresh = clusters[cluster].edgeThreshold;
00890           break;
00891         }
00892       }
00893 
00894       //if cluster not found bail
00895       if( cluster >= numClusters )
00896       {
00897 //        cout << "Error! Could not find cluster pixel belonged to!\n";
00898         continue;
00899       }
00900       
00901       //if edge mag below thresh then skip
00902       if( edgeMagMap[x + y*image->width()] < edgeMagThresh ) continue;
00903         
00904       //ok, last checks implement NMS (non-maximum supression)
00905       int direction = LUT[ GSLCmap[x + y*image->width()] ].direction;
00906       int neighborIndex1 = -1;
00907       int neighborIndex2 = -1;
00908 
00909       if( direction == 0)
00910       {
00911         if( x > 0) 
00912           neighborIndex1 = x-1 + y*image->width();
00913         if( x < image->width() - 1 ) 
00914           neighborIndex2 = x+1 + y*image->width();
00915       }
00916       else if(direction == 1)
00917       {
00918         if( x > 0 && y < image->height() - 1 )
00919           neighborIndex1 = x-1 + (y+1)*image->width();
00920         if( x < image->width() - 1 && y > 0 )
00921           neighborIndex2 = x+1 + (y-1)*image->width();
00922       }
00923       else if(direction == 2)
00924       {
00925         if( y < image->height() - 1 ) 
00926           neighborIndex1 = x + (y+1)*image->width();
00927         if( y > 0) 
00928           neighborIndex2 = x + (y-1)*image->width();
00929       }
00930       else if(direction == 3)
00931       {
00932         if( x < image->width() - 1 && y < image->height() - 1 )
00933           neighborIndex1 = x+1 + (y+1)*image->width();
00934         if( x > 0 && y > 0 )
00935           neighborIndex2 = x-1 + (y-1)*image->width();
00936       }
00937 
00938       //neighbor 1 has higher confidence, skip!
00939       if( neighborIndex1 != -1 &&
00940           LUT[ GSLCmap[neighborIndex1] ].ESF * edgeMagMap[neighborIndex1] >
00941           ESF * edgeMagMap[x + y*image->width()] )
00942         continue;
00943       
00944       //neighbor 2 has higher confidence, skip!
00945       if( neighborIndex2 != -1 &&
00946           LUT[ GSLCmap[neighborIndex2] ].ESF * edgeMagMap[neighborIndex2] >
00947           ESF * edgeMagMap[x + y*image->width()] )
00948         continue;
00949       
00950       //All tests passed! Mark edge!
00951       *rgb = qRgb( 255, 255, 255 );
00952     } //x
00953   } //y
00954   
00955   //blur image - all of it
00956   blurImage( *image, 2.0f );
00957 
00958   //normalize image
00959   enhanceImageContrast( image );
00960   
00961 }

void EdgeDetect::deallocateObjects (  )  [private]

Definition at line 963 of file edgeDetect.cpp.

References clusters, edgeMagMap, GSLCmap, and lumMap.

Referenced by ~EdgeDetect().

00964 {
00965   delete[] lumMap;      lumMap = NULL;
00966   delete[] edgeMagMap;  edgeMagMap = NULL;
00967   delete[] GSLCmap;     GSLCmap = NULL;
00968   delete[] clusters;    clusters = NULL;
00969 }


Member Data Documentation

LUTentry EdgeDetect::LUT[256] [private]

Definition at line 90 of file edgeDetect.h.

Referenced by constructEdgeImage(), and constructGSLClut().

QImage* EdgeDetect::image [private]

Definition at line 93 of file edgeDetect.h.

Referenced by allocateAndInitObjects(), computeClusterStatistics(), computeEdgeMagAndGSLCmaps(), constructEdgeImage(), fillLumMapAndLumHistogram(), getClusterMap(), getEdgeImage(), and pixelLum().

int EdgeDetect::lumHist[256] [private]

luminosity and smooth luminosity histograms

Definition at line 96 of file edgeDetect.h.

Referenced by allocateAndInitObjects(), fillLumMapAndLumHistogram(), and smoothLumHistogram().

int EdgeDetect::smoothLumHist[256] [private]

Definition at line 97 of file edgeDetect.h.

Referenced by allocateAndInitObjects(), findPixelClusters(), getSmoothHist(), and smoothLumHistogram().

int EdgeDetect::clusterPeaks[256] [private]

Definition at line 100 of file edgeDetect.h.

Referenced by allocateAndInitObjects(), computeClusterStatistics(), findPixelClusters(), and getPeaks().

int* EdgeDetect::lumMap [private]

Definition at line 103 of file edgeDetect.h.

Referenced by allocateAndInitObjects(), computeClusterStatistics(), constructEdgeImage(), deallocateObjects(), fillLumMapAndLumHistogram(), getClusterMap(), and pixelLum().

float* EdgeDetect::edgeMagMap [private]

Definition at line 106 of file edgeDetect.h.

Referenced by allocateAndInitObjects(), computeClusterStatistics(), computeEdgeMagAndGSLCmaps(), constructEdgeImage(), and deallocateObjects().

int* EdgeDetect::GSLCmap [private]

Definition at line 109 of file edgeDetect.h.

Referenced by allocateAndInitObjects(), computeEdgeMagAndGSLCmaps(), constructEdgeImage(), and deallocateObjects().

int EdgeDetect::numClusters [private]

Definition at line 112 of file edgeDetect.h.

Referenced by computeClusterStatistics(), computeClusterThresholds(), constructEdgeImage(), findPixelClusters(), getClusterMap(), and getNumClusters().

PixelCluster* EdgeDetect::clusters [private]

Definition at line 113 of file edgeDetect.h.

Referenced by computeClusterStatistics(), computeClusterThresholds(), constructEdgeImage(), deallocateObjects(), findPixelClusters(), getClusterMap(), and getClusters().

int EdgeDetect::minClusterSize [private]

Definition at line 116 of file edgeDetect.h.

Referenced by computeClusterStatistics().

int EdgeDetect::maxClusterSize [private]

Definition at line 116 of file edgeDetect.h.

Referenced by computeClusterStatistics().


The documentation for this class was generated from the following files:
Generated on Wed Jan 24 05:38:09 2007 for AlbumShaper by  doxygen 1.5.1