AlbumShaper  1.0a3
Public Member Functions | Private Member Functions | Private Attributes
EdgeDetect Class Reference

#include <edgeDetect.h>

Collaboration diagram for EdgeDetect:
Collaboration graph
[legend]

List of all members.

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

Detailed Description

Definition at line 45 of file edgeDetect.h.


Constructor & Destructor Documentation

EdgeDetect::EdgeDetect ( QImage *  image)

Definition at line 192 of file edgeDetect.cpp.

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

{                     
  //load image
  this->image = image;

  //allocate and initialize objects used for edge detection
  allocateAndInitObjects();

  //fill lum map and lum histogram
  fillLumMapAndLumHistogram();
  
  //fill smoothed histogram
  smoothLumHistogram();
  
  //compute edge magnitude and GSLC maps
  computeEdgeMagAndGSLCmaps();
  
  //determine pixel clusters
  findPixelClusters();
  
  computeClusterStatistics();  
 
  computeClusterThresholds();
  
  constructEdgeImage();
}
EdgeDetect::~EdgeDetect ( )

Definition at line 219 of file edgeDetect.cpp.

References deallocateObjects().


Member Function Documentation

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().

{
  //initialize: 
  //-luminosity histogram
  //-smoothed luminosity histogram
  //-identified peak regions
  int i;
  for(i=0; i<256; i++)
  { 
    lumHist[i] = 0; 
    smoothLumHist[i] = 0;
    clusterPeaks[i] = 0;
  }
  
  //allocate luminance map
  lumMap = new int[image->width() * image->height()];
  
  //allocate edge magnitude map
  edgeMagMap = new float[image->width() * image->height()];
  
  //allocate GSLC map
  GSLCmap = new int[image->width() * image->height()];
  
  //construct LUT
  constructGSLClut();
}
void EdgeDetect::computeClusterStatistics ( ) [private]

Definition at line 546 of file edgeDetect.cpp.

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

Referenced by EdgeDetect().

{
  //initialize cluster stats
  int cluster;
  for(cluster=0; cluster<numClusters; cluster++)
  {
    int i;
    for(i=0; i<256; i++)
    {
      clusters[cluster].edgeMagHistogram[i] = 0;
    }
    clusters[cluster].totalEdgeMagnitude=0.0f;
    clusters[cluster].numPixels = 0;
  }
  
  //iterate over all pixels
  int i;
  for(i=0; i<image->width()*image->height(); i++)
  {
    //skip pixels that don't belong to peaks
    if( clusterPeaks[ lumMap[i] ] != 1)
      continue;
    
    //determine cluster pixel belongs to
    int cluster;
    for(cluster=0; cluster<numClusters; cluster++)
    {
      if( lumMap[i] >= clusters[cluster].minLuminance &&
          lumMap[i] <= clusters[cluster].maxLuminance )
      {      
        clusters[cluster].totalEdgeMagnitude+= edgeMagMap[i]; 
        clusters[cluster].numPixels++;
        clusters[cluster].edgeMagHistogram[ QMIN( QMAX( (int)edgeMagMap[i], 0), 255) ]++;
        break;
      }
    } //cluster
  } //pixel i
  
  //iterate over clusters to determine min and max peak cluster sizes
  minClusterSize = clusters[0].numPixels;
  maxClusterSize = clusters[0].numPixels;
  for(cluster=1; cluster<numClusters; cluster++)
  {
    if(clusters[cluster].numPixels < minClusterSize)
      minClusterSize = clusters[cluster].numPixels;

    if(clusters[cluster].numPixels > maxClusterSize)
      maxClusterSize = clusters[cluster].numPixels;
  }

  //iterate over clusters one final time to deduce normalized inputs to fuzzy logic process
  int JND = 255/50;
  for(cluster=0; cluster<numClusters; cluster++)
  {
    clusters[cluster].meanMode = QMIN( clusters[cluster].totalEdgeMagnitude / clusters[cluster].numPixels,
                                       3*JND );
    
    int i;
    int mode = 0;
    for(i=1; i<256; i++)
    {
      if( clusters[cluster].edgeMagHistogram[i] > clusters[cluster].edgeMagHistogram[ mode ] )
        mode = i;
    }
    clusters[cluster].mode = QMIN( mode, 2*JND );
        
    clusters[cluster].pixelCount = ((float)(clusters[cluster].numPixels - minClusterSize)) / 
                                   (maxClusterSize - minClusterSize);  
  }
}
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().

{
  //iterate over each cluster
  int cluster;
  float S1,M1,L1;
  float S2,M2,L2;
  float S3,L3;
  float outS, outM, outL;
  
  int JND = 255/50;
  
  for(cluster=0; cluster<numClusters; cluster++)
  {
    //----
    //compute S,M, and L values for each input
    //----
    S1 = QMAX( 1.0f - ((clusters[cluster].meanMode/JND) / 1.5f), 0 );

    if( (clusters[cluster].meanMode/JND) <= 1.5f )
      M1 = QMAX( (clusters[cluster].meanMode/JND) - 0.5f, 0 );
    else
      M1 = QMAX( 2.5f - (clusters[cluster].meanMode/JND), 0 );
    
    L1 = QMAX( ((clusters[cluster].meanMode/JND) - 1.5f) / 1.5f, 0 );
    //----
    S2 = QMAX( 1.0f - (clusters[cluster].mode/JND), 0 );
    
    if( (clusters[cluster].mode/JND) <= 1.0f )
      M2 = QMAX( -1.0f + 2*(clusters[cluster].mode/JND), 0 );
    else
      M2 = QMAX( 3.0f - 2*(clusters[cluster].mode/JND), 0 );
    
    L2 = QMAX( (clusters[cluster].mode/JND) - 1.0, 0 );
    //----
    S3 = QMAX( 1.0f - 2*clusters[cluster].pixelCount, 0 );
    L3 = QMAX( -1.0f + 2*clusters[cluster].pixelCount, 0 );
    //----
    
    //Compute M,L for outputs using set of 18 rules.
    //outS is inherantly S given the ruleset provided
    outS = 0.0f;
    outM = 0.0f;
    outL = 0.0f;
    //Out 1
    if( numClusters > 2 )
    {
      outM += S1*S2*S3;   //rule 1
      
      //rule 2
      if( clusters[cluster].meanMode < clusters[cluster].mode )
        outS += S1*S2*L3;   
      else
        outM += S1*S2*L3;

      outM += S1*M2*S3;   //rule 3
      outM += S1*M2*L3;   //rule 4
      outM += S1*L2*S3;   //rule 5
      outM += S1*L2*L3;   //rule 6
      outM += M1*S2*S3;   //rule 7
      outM += M1*S2*L3;   //rule 8
      outM += M1*M2*S3;   //rule 9
      outL += M1*M2*L3;   //rule 10
      outM += M1*L2*S3;   //rule 11
      outL += M1*L2*L3;   //rule 12
      outM += L1*S2*S3;   //rule 13
      outL += L1*S2*L3;   //rule 14
      outM += L1*M2*S3;   //rule 15
      outL += L1*M2*L3;   //rule 16
      outL += L1*L2*S3;   //rule 17
      outL += L1*L2*L3;   //rule 18
    }
    //Out 2
    else
    {
      outL += S1*S2*S3;   //rule 1
      outL += S1*S2*L3;   //rule 2
      outM += S1*M2*S3;   //rule 3
      outL += S1*M2*L3;   //rule 4
      outM += S1*L2*S3;   //rule 5
      outM += S1*L2*L3;   //rule 6
      outL += M1*S2*S3;   //rule 7
      outL += M1*S2*L3;   //rule 8
      outL += M1*M2*S3;   //rule 9
      outL += M1*M2*L3;   //rule 10
      outL += M1*L2*S3;   //rule 11
      outL += M1*L2*L3;   //rule 12
      outL += L1*S2*S3;   //rule 13
      outL += L1*S2*L3;   //rule 14
      outL += L1*M2*S3;   //rule 15
      outL += L1*M2*L3;   //rule 16
      outL += L1*L2*S3;   //rule 17
      outL += L1*L2*L3;   //rule 18
    }

    //find centroid - Beta[k]
    float A = outM + 0.5f;
    float B = 2.5f - outM;
    float C = 1.5f * (outL + 1);
    float D = 1.5f * (outM + 1);
    float E = 2.5f - outL;

    //---------------------------------------------------------------
    //Case 1: Both outM and outL are above intersection point of diagonals
    if( outM > 0.5f && outL > 0.5f )
    {
      //find area of 7 subregions
      float area1 = ((A-0.5f)*outM)/2;
      float area2 = outM * (B-A);
      float area3 = ((2.1f-B) * (outM - 0.5)) / 2;
      float area4 = (2.1 - B) * 0.5f;
      float area5 = ((C - 2.1f) * (outL - 0.5)) / 2;
      float area6 = (C - 2.1f) * 0.5f;
      float area7 = (3.0f - C) * outL;
     
      //find half of total area
      float halfArea = (area1 + area2 + area3 + area4 + area5 + area6 + area7) / 2;
      
      //determine which region split will be within and resulting horizontal midpoint
      
      //Within area 1
      if( area1 > halfArea )
      {
        clusters[cluster].beta = 0.5f + (float)sqrt(2*halfArea);       
      }
      //Within area 2
      else if( area1 + area2 > halfArea )
      {
        clusters[cluster].beta = ((halfArea - area1) / outM) + A;        
      }
      //Within area 3-4
      else if( area1 + area2 + area3 + area4 > halfArea )
      {
        float a = -0.5f;
        float b = 2.8f;
        float c = area1 + area2 + area3 - halfArea - B/2 - 2.625f;
        clusters[cluster].beta = (-b + (float)sqrt( b*b - 4*a*c )) / (2*a);
      }
      //Within area 5-6
      else if( area1 + area2 + area3 + area4 + area5 + area6 > halfArea )
      {
        float a = 1.0f/3;
        float b = -0.7f;
        float c = area1 + area2 + area3 + area4 - halfArea;
        clusters[cluster].beta = (-b + (float)sqrt( b*b - 4*a*c )) / (2*a);
      }
      //Within area 7
      else
      {
        clusters[cluster].beta = ((halfArea - (area1 + area2 + area3 + area4 + area5 + area6) ) / outL) + C;       
      }
    } //end case 1
    //---------------------------------------------------------------
    //Case 2
    else if ( outM < 0.5f && outL > outM )
    {
      //find area of 5 subregions
      float area1 = (outM*(A-0.5f)) / 2;
      float area2 = (D-A) * outM;
      float area3 = ((C-D) * (outL - outM)) / 2;
      float area4 = (C-D) * outM;
      float area5 = (3.0f - C) * outL;
      
      //find half of total area
      float halfArea = (area1 + area2 + area3 + area4 + area5) / 2;
      
      //determine which region split will be within and resulting horizontal midpoint

      //Within area 1
      if( area1 > halfArea )
      {
        clusters[cluster].beta = 0.5f + (float)sqrt(2*halfArea);
      }
      //Within area 2
      else if( area1 + area2 > halfArea )
      {
        clusters[cluster].beta = ((halfArea - area1) / outM) + A;
      }
      //Within area 3-4
      else if( area1 + area2 + area3 + area4 > halfArea )
      {
        float a = 1.0f/3.0f;
        float b = outM - 0.5f - D/3;
        float c = area1 + area2 - D*outM + D/2 - halfArea;
        clusters[cluster].beta = (-b + (float)sqrt( b*b - 4*a*c )) / (2*a);
      }
      //Within area5
      else
      {
        clusters[cluster].beta = ((halfArea - (area1 + area2 + area3 + area4) ) / outL) + C;
      }
    } //end case 2
    //---------------------------------------------------------------
    //Case 3
    else
    {
      //find area of 5 subregions
      float area1 = (outM*(A-0.5f)) / 2;
      float area2 = (B-A) * outM;
      float area3 = ((E-B) * (outM - outL)) / 2;
      float area4 = (E-B) * outL;
      float area5 = (3.0f - E) * outL;
      
      //find half of total area
      float halfArea = (area1 + area2 + area3 + area4 + area5) / 2;
      
      //determine which region split will be within and resulting horizontal midpoint
      
      //Within area 1
      if( area1 > halfArea )
      {
        clusters[cluster].beta = 0.5f + (float)sqrt(2*halfArea);
      }
      //Within area 2
      else if( area1 + area2 > halfArea )
      {
        clusters[cluster].beta = ((halfArea - area1) / outM) + A;
      }
      //Within area 3-4
      else if( area1 + area2 + area3 + area4 > halfArea )
      {
        float a = -0.5f;
        float b = E/2 + 2.5f/2; 
        float c = area3 - 2.5f*E/2;
        clusters[cluster].beta = (-b + (float)sqrt( b*b - 4*a*c )) / (2*a);
      }
      //Within area5
      else
      {
        clusters[cluster].beta = ((halfArea - (area1 + area2 + area3 + area4) ) / outL) + E;
      }
    } //end case 3
    //---------------------------------------------------------------
    
    //Compute edge threshold
    int lumJND = 255/50;
    clusters[cluster].edgeThreshold = clusters[cluster].mode + clusters[cluster].beta*lumJND;

  } //end for cluster
  
}
void EdgeDetect::computeEdgeMagAndGSLCmaps ( ) [private]

Definition at line 341 of file edgeDetect.cpp.

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

Referenced by EdgeDetect().

{
  int x, y;
  int idealPattern[9];
  int pixelLums[9];
  
  //-------  
  //iterate over all pixels
  for( y=0; y<image->height(); y++)
  {   
    for( x=0; x<image->width(); x++)
    {
      //compute pixel luminances for entire grid
      pixelLums[0] = pixelLum(x-1,y-1);
      pixelLums[1] = pixelLum(x  ,y-1);
      pixelLums[2] = pixelLum(x+1,y-1);
      pixelLums[3] = pixelLum(x-1,y  );
      pixelLums[4] = pixelLum(x  ,y  );
      pixelLums[5] = pixelLum(x+1,y  );
      pixelLums[6] = pixelLum(x-1,y+1);
      pixelLums[7] = pixelLum(x  ,y+1);
      pixelLums[8] = pixelLum(x+1,y+1);
      
      //compute average
      float avg = 0;
      int i;
      for(i=0; i<=8; i++)
      {
        avg+= pixelLums[i];
      }
      avg = avg / 9;
      
      //determine ideal pattern and I0 and I1 averages
      int centerPixelLum = pixelLums[4];
      float centerDiff = centerPixelLum - avg;
      
      float I0avg = 0;
      int I0count = 0;
      
      float I1avg = 0;
      int I1count = 0;
      
      for(i=0; i<=8; i++)
      {
        if( centerDiff * (pixelLums[i]-avg) >=0 )
        { 
          I1avg+=pixelLums[i];
          I1count++;
          idealPattern[i] = 1; 
        }
        else 
        { 
          I0avg+=pixelLums[i];
          I0count++;
          idealPattern[i] = 0; 
        }
      }

      //compute and store edge magnitude
      if(I0count > 0) I0avg = I0avg/I0count;
      if(I1count > 0) I1avg = I1avg/I1count;     
      edgeMagMap[x + y*image->width()] = QABS( I1avg - I0avg );
      
      //compute and store GSLC
      int GSLC=0;
      int weight = 1;
      for(i=0; i<9; i++)
      {
        //skip center
        if(i == 4) continue;
        
        if(idealPattern[i] == 1)
        { GSLC+=weight; }
        
        weight = weight*2;
      }
      GSLCmap[x + y*image->width()] = GSLC;
    } //x
  } //y
}
void EdgeDetect::constructEdgeImage ( ) [private]

Definition at line 859 of file edgeDetect.cpp.

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

Referenced by EdgeDetect().

{
  int x, y;
  QRgb* rgb;
  
  uchar* scanLine;
  for( y=0; y<image->height(); y++)
  {   
    scanLine = image->scanLine(y);
    for( x=0; x<image->width(); x++)
    {
      //initialize pixel to black 
      rgb = ((QRgb*)scanLine+x);
      *rgb = qRgb( 0, 0, 0 );
      
      //lookup ESF for this pixel
      float ESF = LUT[ GSLCmap[x + y*image->width()] ].ESF;

      //If ESF value for this pixel is 0 skip
      if( ESF == 0.0f ) continue;

      //lookup edge magnitude threshold
      float lum = lumMap[x + y*image->width()];
      float edgeMagThresh = -1.0f;
      int cluster;
      for(cluster=0; cluster<numClusters; cluster++)
      {
        if(lum >= clusters[cluster].minLuminance &&
           lum <= clusters[cluster].maxLuminance)
        {
          edgeMagThresh = clusters[cluster].edgeThreshold;
          break;
        }
      }

      //if cluster not found bail
      if( cluster >= numClusters )
      {
//        cout << "Error! Could not find cluster pixel belonged to!\n";
        continue;
      }
      
      //if edge mag below thresh then skip
      if( edgeMagMap[x + y*image->width()] < edgeMagThresh ) continue;
        
      //ok, last checks implement NMS (non-maximum supression)
      int direction = LUT[ GSLCmap[x + y*image->width()] ].direction;
      int neighborIndex1 = -1;
      int neighborIndex2 = -1;

      if( direction == 0)
      {
        if( x > 0) 
          neighborIndex1 = x-1 + y*image->width();
        if( x < image->width() - 1 ) 
          neighborIndex2 = x+1 + y*image->width();
      }
      else if(direction == 1)
      {
        if( x > 0 && y < image->height() - 1 )
          neighborIndex1 = x-1 + (y+1)*image->width();
        if( x < image->width() - 1 && y > 0 )
          neighborIndex2 = x+1 + (y-1)*image->width();
      }
      else if(direction == 2)
      {
        if( y < image->height() - 1 ) 
          neighborIndex1 = x + (y+1)*image->width();
        if( y > 0) 
          neighborIndex2 = x + (y-1)*image->width();
      }
      else if(direction == 3)
      {
        if( x < image->width() - 1 && y < image->height() - 1 )
          neighborIndex1 = x+1 + (y+1)*image->width();
        if( x > 0 && y > 0 )
          neighborIndex2 = x-1 + (y-1)*image->width();
      }

      //neighbor 1 has higher confidence, skip!
      if( neighborIndex1 != -1 &&
          LUT[ GSLCmap[neighborIndex1] ].ESF * edgeMagMap[neighborIndex1] >
          ESF * edgeMagMap[x + y*image->width()] )
        continue;
      
      //neighbor 2 has higher confidence, skip!
      if( neighborIndex2 != -1 &&
          LUT[ GSLCmap[neighborIndex2] ].ESF * edgeMagMap[neighborIndex2] >
          ESF * edgeMagMap[x + y*image->width()] )
        continue;
      
      //All tests passed! Mark edge!
      *rgb = qRgb( 255, 255, 255 );
    } //x
  } //y
  
  //blur image - all of it
  blurImage( *image, 2.0f );

  //normalize image
  enhanceImageContrast( image );
  
}
void EdgeDetect::constructGSLClut ( ) [private]

Definition at line 971 of file edgeDetect.cpp.

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

Referenced by allocateAndInitObjects().

{
  //----------------------
  //First fill entire table with 0 ESF's and invalid directions
  int i;
  for(i=0; i<256; i++)
  {
    LUT[i].ESF = 0.0f;
    LUT[i].direction = -1;
  }
  //----------------------
  //Next code in all pattern that are highly 
  //likely to be on edges as described in the paper
  //----------------------
  //Pattern (a)

  // ###
  // ##.
  // ...
  LUT[15].ESF = 0.179f;
  LUT[15].direction = 3;

  // ...
  // .##
  // ###
  LUT[240].ESF = 0.179f;
  LUT[240].direction = 3;

  // ###
  // .##
  // ...
  LUT[23].ESF = 0.179f;
  LUT[23].direction = 1;
  
  // ...
  // ##.
  // ###
  LUT[232].ESF = 0.179f;
  LUT[232].direction = 1;
   
  // ##.
  // ##.
  // #..
  LUT[43].ESF = 0.179f;
  LUT[43].direction = 3;
  
  // ..#
  // .##
  // .##
  LUT[212].ESF = 0.179f;
  LUT[212].direction = 3;

  // #..
  // ##.
  // ##.
  LUT[105].ESF = 0.179f;
  LUT[105].direction = 1;

  // .##
  // .##
  // ..#
  LUT[150].ESF = 0.179f;
  LUT[150].direction = 1;
  //----------------------
  //Pattern (b)

  // ###
  // ###
  // ...
  LUT[31].ESF = 0.137f;
  LUT[31].direction = 2;

  // ...
  // ###
  // ###
  LUT[248].ESF = 0.137f;
  LUT[248].direction = 2;
  
  // ##.
  // ##.
  // ##.
  LUT[107].ESF = 0.137f;
  LUT[107].direction = 0;
  
  // .##
  // .##
  // .##
  LUT[214].ESF = 0.137f;
  LUT[214].direction = 0;
  //----------------------
  //Pattern (c)
  
  // ###
  // .#.
  // ...
  LUT[7].ESF = 0.126f;
  LUT[7].direction = 2;
  
  // ...
  // .#.
  // ###
  LUT[224].ESF = 0.126f;
  LUT[224].direction = 2;

  // #..
  // ##.
  // #..
  LUT[41].ESF = 0.126f;
  LUT[41].direction = 0; 
  
  // ..#
  // .##
  // ..#
  LUT[148].ESF = 0.126f;
  LUT[148].direction = 0;
  //----------------------
  //Pattern (d)
  
  // ###
  // ##.
  // #..
  LUT[47].ESF = 0.10f;
  LUT[47].direction = 3;
   
  // ..#
  // .##
  // ###
  LUT[244].ESF = 0.10f;
  LUT[244].direction = 3;

  // ###
  // .##
  // ..#
  LUT[151].ESF = 0.10f;
  LUT[151].direction = 1;

  // #..
  // ##.
  // ###
  LUT[233].ESF = 0.10f;
  LUT[233].direction = 1;
  //----------------------
  //Pattern (e)
  
  // ##.
  // ##.
  // ...
  LUT[11].ESF = 0.10f;
  LUT[11].direction = 3;
  
  // ...
  // .##
  // .##
  LUT[208].ESF = 0.10f;
  LUT[208].direction = 3;

  // .##
  // .##
  // ...
  LUT[22].ESF = 0.10f;
  LUT[22].direction = 1;
  
  // ...
  // ##.
  // ##.
  LUT[104].ESF = 0.10f;
  LUT[104].direction = 1; 
  //----------------------    
}
void EdgeDetect::deallocateObjects ( ) [private]

Definition at line 963 of file edgeDetect.cpp.

References clusters, edgeMagMap, GSLCmap, and lumMap.

Referenced by ~EdgeDetect().

{
  delete[] lumMap;      lumMap = NULL;
  delete[] edgeMagMap;  edgeMagMap = NULL;
  delete[] GSLCmap;     GSLCmap = NULL;
  delete[] clusters;    clusters = NULL;
}
void EdgeDetect::fillLumMapAndLumHistogram ( ) [private]

Definition at line 291 of file edgeDetect.cpp.

References image, lumHist, and lumMap.

Referenced by EdgeDetect().

{
  int x, y;
  QRgb* rgb;
  uchar* scanLine;
  int lumVal;
  for( y=0; y<image->height(); y++)
  {   
    scanLine = image->scanLine(y);
    for( x=0; x<image->width(); x++)
    {
      //get lum value for this pixel
      rgb = ((QRgb*)scanLine+x);
      lumVal = qGray(*rgb);
      
      //store in lum map
      lumMap[x + y*image->width()] = lumVal;
      
      //update lum histogram
      lumHist[ lumVal ]++;
    }
  }
}
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().

{
  //find max count
  int maxCount = 0;
  int i;
  for(i=0; i<256; i++)
  {
    if(smoothLumHist[i] > maxCount)
      maxCount = smoothLumHist[i];
  }

  //compute JND for histogram (2% of total spread)
  int histJND = maxCount/50;

  //construct temporary array for valley locations
  //1's will indicate a valley midpoint
  int tmpValleyArray[256];
  for(i=0; i<256; i++) { tmpValleyArray[i] = 0; }
  
  //move across histogram finding valley midpoints
  int curTrackedMin = smoothLumHist[0];
  
  //first and last indices tracked min was observed
  int firstMinIndex = 0;
  int lastMinIndex = 0;
  
  //only add valley midpoint if finished tracking a descent
  bool slopeNeg = false;
  
  for(i = 1; i<256; i++ )
  {
    if( smoothLumHist[i] < curTrackedMin - histJND )
    {
      //found a descent!
      slopeNeg = true;
      curTrackedMin = smoothLumHist[i];
      firstMinIndex = i;
    }
    //starting to go up again, add last min to list
    else if( smoothLumHist[i] > curTrackedMin + histJND )
    {
      //if finished tracing a negative slope find midpoint and set location to true
      if(slopeNeg)
      {
        tmpValleyArray[ (firstMinIndex + lastMinIndex)/2 ] = 1;
      }
      
      curTrackedMin = smoothLumHist[i];
      slopeNeg = false;
    }
    else
    {
      //still tracking a min, update the right 
      //hand index. center of valley is found
      //by averaging first and last min index
      lastMinIndex = i;
    }
  }
  
  //count valleys
  int numValleys = 0;
  for(i=0; i<256; i++)
  {
    if(tmpValleyArray[i] == 1 ) numValleys++;
  }

  //determine number of clusters
  numClusters = numValleys-1;
  if(tmpValleyArray[0] != 1)
    numClusters++;
  if(tmpValleyArray[255] != 1)
    numClusters++;
  
  //allocate clusters
  clusters = new PixelCluster[numClusters];
  
  //automatically start first cluster
  int cluster=0;
  clusters[cluster].minLuminance = 0;
  
  //initialize left and right boundaries of all clusters
  for(i=1; i<256; i++)
  {
    //reached next valley, end cluster
    if( tmpValleyArray[i] == 1)
    {
      clusters[cluster].maxLuminance = i-1;
      cluster++;
      clusters[cluster].minLuminance = i;
    }
    //end last cluster automatically at end
    else if(i == 255)
    {
      clusters[cluster].maxLuminance = i;
    }
  }
  
  //determine cluster peaks
  for(cluster=0; cluster<numClusters; cluster++)
  {
    //find max for current cluster
    int maxIndex = clusters[cluster].minLuminance;
    for(i=clusters[cluster].minLuminance; i<=clusters[cluster].maxLuminance; i++)
    {
      if(smoothLumHist[i] > smoothLumHist[maxIndex])
         maxIndex = i;
    }
    
    //mark peaks  
    int lumJND = 255/50;
    for(i=QMAX(0, maxIndex-lumJND); i<QMIN(256, maxIndex+lumJND); i++)
    { 
      clusterPeaks[i] = 1; 
    }
  }
}
int * EdgeDetect::getClusterMap ( )

Definition at line 241 of file edgeDetect.cpp.

References clusters, image, lumMap, and numClusters.

Referenced by GrainEditor::GrainEditor().

{
  //construct map
  int* clusterMap = new int[image->width() * image->height()];
  
  //iterate over all pixels, determine cluster each pixel belongs to
  int i, cluster;
  for(i=0; i<image->width()*image->height(); i++)
  {
    for(cluster=0; cluster<numClusters; cluster++)
    {
      if( lumMap[i] >= clusters[cluster].minLuminance &&
          lumMap[i] <= clusters[cluster].maxLuminance )
      {
        clusterMap[i] = cluster;
        break;
      }
    } //cluster
  } //pixel

  return clusterMap;
}
PixelCluster * EdgeDetect::getClusters ( )

Definition at line 227 of file edgeDetect.cpp.

References clusters.

{ return clusters; }
QImage * EdgeDetect::getEdgeImage ( )

Definition at line 236 of file edgeDetect.cpp.

References image.

{
  return image; 
}
int EdgeDetect::getNumClusters ( )

Definition at line 224 of file edgeDetect.cpp.

References numClusters.

Referenced by GrainEditor::GrainEditor().

{ return numClusters; }
int * EdgeDetect::getPeaks ( )

Definition at line 230 of file edgeDetect.cpp.

References clusterPeaks.

{ return clusterPeaks; }
int * EdgeDetect::getSmoothHist ( )

Definition at line 233 of file edgeDetect.cpp.

References smoothLumHist.

{ return smoothLumHist; }
int EdgeDetect::pixelLum ( int  x,
int  y 
) [private]

Definition at line 422 of file edgeDetect.cpp.

References image, and lumMap.

Referenced by computeEdgeMagAndGSLCmaps().

{
  int clampedX = QMAX( QMIN( x, image->width()-1), 0);
  int clampedY = QMAX( QMIN( y, image->height()-1), 0);
  return lumMap[ clampedX + clampedY * image->width() ];
}
void EdgeDetect::smoothLumHistogram ( ) [private]

Definition at line 315 of file edgeDetect.cpp.

References FILTER_SIZE, lumHist, and smoothLumHist.

Referenced by EdgeDetect().

{
  #define FILTER_SIZE 5
  int filter[FILTER_SIZE] = {2, 5, 8, 5, 2};
  
  int i,j;
  int filterIndex, sum, total;
  for(i = 0; i<256; i++)
  {
    sum = 0;
    total = 0;
    
    for( j= -FILTER_SIZE/2; j <= FILTER_SIZE/2; j++)
    {
      if( i+j > 0 && i+j < 256 )
      {
        filterIndex = j+ FILTER_SIZE/2;
        total+= filter[filterIndex] * lumHist[i+j];
        sum  += filter[filterIndex];
      }
    }
    
    smoothLumHist[i] = total / sum;
  }
}

Member Data Documentation

int EdgeDetect::clusterPeaks[256] [private]
float* EdgeDetect::edgeMagMap [private]
int* EdgeDetect::GSLCmap [private]
QImage* EdgeDetect::image [private]
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::lumMap [private]
LUTentry EdgeDetect::LUT[256] [private]

Definition at line 90 of file edgeDetect.h.

Referenced by constructEdgeImage(), and constructGSLClut().

Definition at line 116 of file edgeDetect.h.

Referenced by computeClusterStatistics().

Definition at line 116 of file edgeDetect.h.

Referenced by computeClusterStatistics().

int EdgeDetect::numClusters [private]
int EdgeDetect::smoothLumHist[256] [private]

The documentation for this class was generated from the following files: