AlbumShaper 1.0a3
EdgeDetect Class Reference

#include <edgeDetect.h>

Collaboration diagram for EdgeDetect:

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::EdgeDetect ( QImage * image)

Definition at line 195 of file edgeDetect.cpp.

196{
197 //load image
198 this->image = image;
199
200 //allocate and initialize objects used for edge detection
202
203 //fill lum map and lum histogram
205
206 //fill smoothed histogram
208
209 //compute edge magnitude and GSLC maps
211
212 //determine pixel clusters
214
216
218
220}
void fillLumMapAndLumHistogram()
void allocateAndInitObjects()
void computeClusterStatistics()
void computeClusterThresholds()
void findPixelClusters()
QImage * image
Definition edgeDetect.h:93
void constructEdgeImage()
void computeEdgeMagAndGSLCmaps()
void smoothLumHistogram()

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

◆ ~EdgeDetect()

EdgeDetect::~EdgeDetect ( )

Definition at line 222 of file edgeDetect.cpp.

223{
225}
void deallocateObjects()

References deallocateObjects().

Member Function Documentation

◆ allocateAndInitObjects()

void EdgeDetect::allocateAndInitObjects ( )
private

Definition at line 267 of file edgeDetect.cpp.

268{
269 //initialize:
270 //-luminosity histogram
271 //-smoothed luminosity histogram
272 //-identified peak regions
273 int i;
274 for(i=0; i<256; i++)
275 {
276 lumHist[i] = 0;
277 smoothLumHist[i] = 0;
278 clusterPeaks[i] = 0;
279 }
280
281 //allocate luminance map
282 lumMap = new int[image->width() * image->height()];
283
284 //allocate edge magnitude map
285 edgeMagMap = new float[image->width() * image->height()];
286
287 //allocate GSLC map
288 GSLCmap = new int[image->width() * image->height()];
289
290 //construct LUT
292}
int * lumMap
Definition edgeDetect.h:103
int smoothLumHist[256]
Definition edgeDetect.h:97
int clusterPeaks[256]
Definition edgeDetect.h:100
void constructGSLClut()
int lumHist[256]
luminosity and smooth luminosity histograms
Definition edgeDetect.h:96
float * edgeMagMap
Definition edgeDetect.h:106
int * GSLCmap
Definition edgeDetect.h:109

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

Referenced by EdgeDetect().

◆ computeClusterStatistics()

void EdgeDetect::computeClusterStatistics ( )
private

Definition at line 549 of file edgeDetect.cpp.

550{
551 //initialize cluster stats
552 int cluster;
553 for(cluster=0; cluster<numClusters; cluster++)
554 {
555 int i;
556 for(i=0; i<256; i++)
557 {
558 clusters[cluster].edgeMagHistogram[i] = 0;
559 }
560 clusters[cluster].totalEdgeMagnitude=0.0f;
561 clusters[cluster].numPixels = 0;
562 }
563
564 //iterate over all pixels
565 int i;
566 for(i=0; i<image->width()*image->height(); i++)
567 {
568 //skip pixels that don't belong to peaks
569 if( clusterPeaks[ lumMap[i] ] != 1)
570 continue;
571
572 //determine cluster pixel belongs to
573 int cluster;
574 for(cluster=0; cluster<numClusters; cluster++)
575 {
576 if( lumMap[i] >= clusters[cluster].minLuminance &&
577 lumMap[i] <= clusters[cluster].maxLuminance )
578 {
580 clusters[cluster].numPixels++;
581 clusters[cluster].edgeMagHistogram[ MIN( MAX( (int)edgeMagMap[i], 0), 255) ]++;
582 break;
583 }
584 } //cluster
585 } //pixel i
586
587 //iterate over clusters to determine min and max peak cluster sizes
590 for(cluster=1; cluster<numClusters; cluster++)
591 {
592 if(clusters[cluster].numPixels < minClusterSize)
594
595 if(clusters[cluster].numPixels > maxClusterSize)
597 }
598
599 //iterate over clusters one final time to deduce normalized inputs to fuzzy logic process
600 int JND = 255/50;
601 for(cluster=0; cluster<numClusters; cluster++)
602 {
603 clusters[cluster].meanMode = MIN( clusters[cluster].totalEdgeMagnitude / clusters[cluster].numPixels,
604 3*JND );
605
606 int i;
607 int mode = 0;
608 for(i=1; i<256; i++)
609 {
610 if( clusters[cluster].edgeMagHistogram[i] > clusters[cluster].edgeMagHistogram[ mode ] )
611 mode = i;
612 }
613 clusters[cluster].mode = MIN( mode, 2*JND );
614
615 clusters[cluster].pixelCount = ((float)(clusters[cluster].numPixels - minClusterSize)) /
617 }
618}
PixelCluster * clusters
Definition edgeDetect.h:113
int minClusterSize
Definition edgeDetect.h:116
int maxClusterSize
Definition edgeDetect.h:116
int numClusters
Definition edgeDetect.h:112
#define MIN(x, y)
Definition color.cpp:20
#define MAX(x, y)
Definition color.cpp:21
float totalEdgeMagnitude
Definition edgeDetect.h:32
float meanMode
Definition edgeDetect.h:36
int edgeMagHistogram[256]
Definition edgeDetect.h:31
float pixelCount
Definition edgeDetect.h:38

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

Referenced by EdgeDetect().

◆ computeClusterThresholds()

void EdgeDetect::computeClusterThresholds ( )
private

Definition at line 621 of file edgeDetect.cpp.

622{
623 //iterate over each cluster
624 int cluster;
625 float S1,M1,L1;
626 float S2,M2,L2;
627 float S3,L3;
628 float outS, outM, outL;
629
630 int JND = 255/50;
631
632 for(cluster=0; cluster<numClusters; cluster++)
633 {
634 //----
635 //compute S,M, and L values for each input
636 //----
637 S1 = MAX( 1.0f - ((clusters[cluster].meanMode/JND) / 1.5f), 0 );
638
639 if( (clusters[cluster].meanMode/JND) <= 1.5f )
640 M1 = MAX( (clusters[cluster].meanMode/JND) - 0.5f, 0 );
641 else
642 M1 = MAX( 2.5f - (clusters[cluster].meanMode/JND), 0 );
643
644 L1 = MAX( ((clusters[cluster].meanMode/JND) - 1.5f) / 1.5f, 0 );
645 //----
646 S2 = MAX( 1.0f - (clusters[cluster].mode/JND), 0 );
647
648 if( (clusters[cluster].mode/JND) <= 1.0f )
649 M2 = MAX( -1.0f + 2*(clusters[cluster].mode/JND), 0 );
650 else
651 M2 = MAX( 3.0f - 2*(clusters[cluster].mode/JND), 0 );
652
653 L2 = MAX( (clusters[cluster].mode/JND) - 1.0, 0 );
654 //----
655 S3 = MAX( 1.0f - 2*clusters[cluster].pixelCount, 0 );
656 L3 = MAX( -1.0f + 2*clusters[cluster].pixelCount, 0 );
657 //----
658
659 //Compute M,L for outputs using set of 18 rules.
660 //outS is inherantly S given the ruleset provided
661 outS = 0.0f;
662 outM = 0.0f;
663 outL = 0.0f;
664 //Out 1
665 if( numClusters > 2 )
666 {
667 outM += S1*S2*S3; //rule 1
668
669 //rule 2
670 if( clusters[cluster].meanMode < clusters[cluster].mode )
671 outS += S1*S2*L3;
672 else
673 outM += S1*S2*L3;
674
675 outM += S1*M2*S3; //rule 3
676 outM += S1*M2*L3; //rule 4
677 outM += S1*L2*S3; //rule 5
678 outM += S1*L2*L3; //rule 6
679 outM += M1*S2*S3; //rule 7
680 outM += M1*S2*L3; //rule 8
681 outM += M1*M2*S3; //rule 9
682 outL += M1*M2*L3; //rule 10
683 outM += M1*L2*S3; //rule 11
684 outL += M1*L2*L3; //rule 12
685 outM += L1*S2*S3; //rule 13
686 outL += L1*S2*L3; //rule 14
687 outM += L1*M2*S3; //rule 15
688 outL += L1*M2*L3; //rule 16
689 outL += L1*L2*S3; //rule 17
690 outL += L1*L2*L3; //rule 18
691 }
692 //Out 2
693 else
694 {
695 outL += S1*S2*S3; //rule 1
696 outL += S1*S2*L3; //rule 2
697 outM += S1*M2*S3; //rule 3
698 outL += S1*M2*L3; //rule 4
699 outM += S1*L2*S3; //rule 5
700 outM += S1*L2*L3; //rule 6
701 outL += M1*S2*S3; //rule 7
702 outL += M1*S2*L3; //rule 8
703 outL += M1*M2*S3; //rule 9
704 outL += M1*M2*L3; //rule 10
705 outL += M1*L2*S3; //rule 11
706 outL += M1*L2*L3; //rule 12
707 outL += L1*S2*S3; //rule 13
708 outL += L1*S2*L3; //rule 14
709 outL += L1*M2*S3; //rule 15
710 outL += L1*M2*L3; //rule 16
711 outL += L1*L2*S3; //rule 17
712 outL += L1*L2*L3; //rule 18
713 }
714
715 //find centroid - Beta[k]
716 float A = outM + 0.5f;
717 float B = 2.5f - outM;
718 float C = 1.5f * (outL + 1);
719 float D = 1.5f * (outM + 1);
720 float E = 2.5f - outL;
721
722 //---------------------------------------------------------------
723 //Case 1: Both outM and outL are above intersection point of diagonals
724 if( outM > 0.5f && outL > 0.5f )
725 {
726 //find area of 7 subregions
727 float area1 = ((A-0.5f)*outM)/2;
728 float area2 = outM * (B-A);
729 float area3 = ((2.1f-B) * (outM - 0.5)) / 2;
730 float area4 = (2.1 - B) * 0.5f;
731 float area5 = ((C - 2.1f) * (outL - 0.5)) / 2;
732 float area6 = (C - 2.1f) * 0.5f;
733 float area7 = (3.0f - C) * outL;
734
735 //find half of total area
736 float halfArea = (area1 + area2 + area3 + area4 + area5 + area6 + area7) / 2;
737
738 //determine which region split will be within and resulting horizontal midpoint
739
740 //Within area 1
741 if( area1 > halfArea )
742 {
743 clusters[cluster].beta = 0.5f + (float)sqrt(2*halfArea);
744 }
745 //Within area 2
746 else if( area1 + area2 > halfArea )
747 {
748 clusters[cluster].beta = ((halfArea - area1) / outM) + A;
749 }
750 //Within area 3-4
751 else if( area1 + area2 + area3 + area4 > halfArea )
752 {
753 float a = -0.5f;
754 float b = 2.8f;
755 float c = area1 + area2 + area3 - halfArea - B/2 - 2.625f;
756 clusters[cluster].beta = (-b + (float)sqrt( b*b - 4*a*c )) / (2*a);
757 }
758 //Within area 5-6
759 else if( area1 + area2 + area3 + area4 + area5 + area6 > halfArea )
760 {
761 float a = 1.0f/3;
762 float b = -0.7f;
763 float c = area1 + area2 + area3 + area4 - halfArea;
764 clusters[cluster].beta = (-b + (float)sqrt( b*b - 4*a*c )) / (2*a);
765 }
766 //Within area 7
767 else
768 {
769 clusters[cluster].beta = ((halfArea - (area1 + area2 + area3 + area4 + area5 + area6) ) / outL) + C;
770 }
771 } //end case 1
772 //---------------------------------------------------------------
773 //Case 2
774 else if ( outM < 0.5f && outL > outM )
775 {
776 //find area of 5 subregions
777 float area1 = (outM*(A-0.5f)) / 2;
778 float area2 = (D-A) * outM;
779 float area3 = ((C-D) * (outL - outM)) / 2;
780 float area4 = (C-D) * outM;
781 float area5 = (3.0f - C) * outL;
782
783 //find half of total area
784 float halfArea = (area1 + area2 + area3 + area4 + area5) / 2;
785
786 //determine which region split will be within and resulting horizontal midpoint
787
788 //Within area 1
789 if( area1 > halfArea )
790 {
791 clusters[cluster].beta = 0.5f + (float)sqrt(2*halfArea);
792 }
793 //Within area 2
794 else if( area1 + area2 > halfArea )
795 {
796 clusters[cluster].beta = ((halfArea - area1) / outM) + A;
797 }
798 //Within area 3-4
799 else if( area1 + area2 + area3 + area4 > halfArea )
800 {
801 float a = 1.0f/3.0f;
802 float b = outM - 0.5f - D/3;
803 float c = area1 + area2 - D*outM + D/2 - halfArea;
804 clusters[cluster].beta = (-b + (float)sqrt( b*b - 4*a*c )) / (2*a);
805 }
806 //Within area5
807 else
808 {
809 clusters[cluster].beta = ((halfArea - (area1 + area2 + area3 + area4) ) / outL) + C;
810 }
811 } //end case 2
812 //---------------------------------------------------------------
813 //Case 3
814 else
815 {
816 //find area of 5 subregions
817 float area1 = (outM*(A-0.5f)) / 2;
818 float area2 = (B-A) * outM;
819 float area3 = ((E-B) * (outM - outL)) / 2;
820 float area4 = (E-B) * outL;
821 float area5 = (3.0f - E) * outL;
822
823 //find half of total area
824 float halfArea = (area1 + area2 + area3 + area4 + area5) / 2;
825
826 //determine which region split will be within and resulting horizontal midpoint
827
828 //Within area 1
829 if( area1 > halfArea )
830 {
831 clusters[cluster].beta = 0.5f + (float)sqrt(2*halfArea);
832 }
833 //Within area 2
834 else if( area1 + area2 > halfArea )
835 {
836 clusters[cluster].beta = ((halfArea - area1) / outM) + A;
837 }
838 //Within area 3-4
839 else if( area1 + area2 + area3 + area4 > halfArea )
840 {
841 float a = -0.5f;
842 float b = E/2 + 2.5f/2;
843 float c = area3 - 2.5f*E/2;
844 clusters[cluster].beta = (-b + (float)sqrt( b*b - 4*a*c )) / (2*a);
845 }
846 //Within area5
847 else
848 {
849 clusters[cluster].beta = ((halfArea - (area1 + area2 + area3 + area4) ) / outL) + E;
850 }
851 } //end case 3
852 //---------------------------------------------------------------
853
854 //Compute edge threshold
855 int lumJND = 255/50;
856 clusters[cluster].edgeThreshold = clusters[cluster].mode + clusters[cluster].beta*lumJND;
857
858 } //end for cluster
859
860}
float B
Definition blur.cpp:78
long b
float edgeThreshold
Definition edgeDetect.h:41

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

Referenced by EdgeDetect().

◆ computeEdgeMagAndGSLCmaps()

void EdgeDetect::computeEdgeMagAndGSLCmaps ( )
private

Definition at line 344 of file edgeDetect.cpp.

345{
346 int x, y;
347 int idealPattern[9];
348 int pixelLums[9];
349
350 //-------
351 //iterate over all pixels
352 for( y=0; y<image->height(); y++)
353 {
354 for( x=0; x<image->width(); x++)
355 {
356 //compute pixel luminances for entire grid
357 pixelLums[0] = pixelLum(x-1,y-1);
358 pixelLums[1] = pixelLum(x ,y-1);
359 pixelLums[2] = pixelLum(x+1,y-1);
360 pixelLums[3] = pixelLum(x-1,y );
361 pixelLums[4] = pixelLum(x ,y );
362 pixelLums[5] = pixelLum(x+1,y );
363 pixelLums[6] = pixelLum(x-1,y+1);
364 pixelLums[7] = pixelLum(x ,y+1);
365 pixelLums[8] = pixelLum(x+1,y+1);
366
367 //compute average
368 float avg = 0;
369 int i;
370 for(i=0; i<=8; i++)
371 {
372 avg+= pixelLums[i];
373 }
374 avg = avg / 9;
375
376 //determine ideal pattern and I0 and I1 averages
377 int centerPixelLum = pixelLums[4];
378 float centerDiff = centerPixelLum - avg;
379
380 float I0avg = 0;
381 int I0count = 0;
382
383 float I1avg = 0;
384 int I1count = 0;
385
386 for(i=0; i<=8; i++)
387 {
388 if( centerDiff * (pixelLums[i]-avg) >=0 )
389 {
390 I1avg+=pixelLums[i];
391 I1count++;
392 idealPattern[i] = 1;
393 }
394 else
395 {
396 I0avg+=pixelLums[i];
397 I0count++;
398 idealPattern[i] = 0;
399 }
400 }
401
402 //compute and store edge magnitude
403 if(I0count > 0) I0avg = I0avg/I0count;
404 if(I1count > 0) I1avg = I1avg/I1count;
405 edgeMagMap[x + y*image->width()] = QABS( I1avg - I0avg );
406
407 //compute and store GSLC
408 int GSLC=0;
409 int weight = 1;
410 for(i=0; i<9; i++)
411 {
412 //skip center
413 if(i == 4) continue;
414
415 if(idealPattern[i] == 1)
416 { GSLC+=weight; }
417
418 weight = weight*2;
419 }
420 GSLCmap[x + y*image->width()] = GSLC;
421 } //x
422 } //y
423}
int pixelLum(int x, int y)

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

Referenced by EdgeDetect().

◆ constructEdgeImage()

void EdgeDetect::constructEdgeImage ( )
private

Definition at line 862 of file edgeDetect.cpp.

863{
864 int x, y;
865 QRgb* rgb;
866
867 uchar* scanLine;
868 for( y=0; y<image->height(); y++)
869 {
870 scanLine = image->scanLine(y);
871 for( x=0; x<image->width(); x++)
872 {
873 //initialize pixel to black
874 rgb = ((QRgb*)scanLine+x);
875 *rgb = qRgb( 0, 0, 0 );
876
877 //lookup ESF for this pixel
878 float ESF = LUT[ GSLCmap[x + y*image->width()] ].ESF;
879
880 //If ESF value for this pixel is 0 skip
881 if( ESF == 0.0f ) continue;
882
883 //lookup edge magnitude threshold
884 float lum = lumMap[x + y*image->width()];
885 float edgeMagThresh = -1.0f;
886 int cluster;
887 for(cluster=0; cluster<numClusters; cluster++)
888 {
889 if(lum >= clusters[cluster].minLuminance &&
890 lum <= clusters[cluster].maxLuminance)
891 {
892 edgeMagThresh = clusters[cluster].edgeThreshold;
893 break;
894 }
895 }
896
897 //if cluster not found bail
898 if( cluster >= numClusters )
899 {
900// cout << "Error! Could not find cluster pixel belonged to!\n";
901 continue;
902 }
903
904 //if edge mag below thresh then skip
905 if( edgeMagMap[x + y*image->width()] < edgeMagThresh ) continue;
906
907 //ok, last checks implement NMS (non-maximum supression)
908 int direction = LUT[ GSLCmap[x + y*image->width()] ].direction;
909 int neighborIndex1 = -1;
910 int neighborIndex2 = -1;
911
912 if( direction == 0)
913 {
914 if( x > 0)
915 neighborIndex1 = x-1 + y*image->width();
916 if( x < image->width() - 1 )
917 neighborIndex2 = x+1 + y*image->width();
918 }
919 else if(direction == 1)
920 {
921 if( x > 0 && y < image->height() - 1 )
922 neighborIndex1 = x-1 + (y+1)*image->width();
923 if( x < image->width() - 1 && y > 0 )
924 neighborIndex2 = x+1 + (y-1)*image->width();
925 }
926 else if(direction == 2)
927 {
928 if( y < image->height() - 1 )
929 neighborIndex1 = x + (y+1)*image->width();
930 if( y > 0)
931 neighborIndex2 = x + (y-1)*image->width();
932 }
933 else if(direction == 3)
934 {
935 if( x < image->width() - 1 && y < image->height() - 1 )
936 neighborIndex1 = x+1 + (y+1)*image->width();
937 if( x > 0 && y > 0 )
938 neighborIndex2 = x-1 + (y-1)*image->width();
939 }
940
941 //neighbor 1 has higher confidence, skip!
942 if( neighborIndex1 != -1 &&
943 LUT[ GSLCmap[neighborIndex1] ].ESF * edgeMagMap[neighborIndex1] >
944 ESF * edgeMagMap[x + y*image->width()] )
945 continue;
946
947 //neighbor 2 has higher confidence, skip!
948 if( neighborIndex2 != -1 &&
949 LUT[ GSLCmap[neighborIndex2] ].ESF * edgeMagMap[neighborIndex2] >
950 ESF * edgeMagMap[x + y*image->width()] )
951 continue;
952
953 //All tests passed! Mark edge!
954 *rgb = qRgb( 255, 255, 255 );
955 } //x
956 } //y
957
958 //blur image - all of it
959 blurImage( *image, 2.0f );
960
961 //normalize image
963
964}
int width
Definition blur.cpp:79
int height
Definition blur.cpp:79
void blurImage(QImage &image, float sigma)
Definition blur.cpp:94
LUTentry LUT[256]
Definition edgeDetect.h:90
QImage * enhanceImageContrast(QString filename, StatusWidget *status)
Definition contrast.cpp:88
float ESF
Definition edgeDetect.h:22
int direction
Definition edgeDetect.h:23

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

Referenced by EdgeDetect().

◆ constructGSLClut()

void EdgeDetect::constructGSLClut ( )
private

Definition at line 974 of file edgeDetect.cpp.

975{
976 //----------------------
977 //First fill entire table with 0 ESF's and invalid directions
978 int i;
979 for(i=0; i<256; i++)
980 {
981 LUT[i].ESF = 0.0f;
982 LUT[i].direction = -1;
983 }
984 //----------------------
985 //Next code in all pattern that are highly
986 //likely to be on edges as described in the paper
987 //----------------------
988 //Pattern (a)
989
990 // ###
991 // ##.
992 // ...
993 LUT[15].ESF = 0.179f;
994 LUT[15].direction = 3;
995
996 // ...
997 // .##
998 // ###
999 LUT[240].ESF = 0.179f;
1000 LUT[240].direction = 3;
1001
1002 // ###
1003 // .##
1004 // ...
1005 LUT[23].ESF = 0.179f;
1006 LUT[23].direction = 1;
1007
1008 // ...
1009 // ##.
1010 // ###
1011 LUT[232].ESF = 0.179f;
1012 LUT[232].direction = 1;
1013
1014 // ##.
1015 // ##.
1016 // #..
1017 LUT[43].ESF = 0.179f;
1018 LUT[43].direction = 3;
1019
1020 // ..#
1021 // .##
1022 // .##
1023 LUT[212].ESF = 0.179f;
1024 LUT[212].direction = 3;
1025
1026 // #..
1027 // ##.
1028 // ##.
1029 LUT[105].ESF = 0.179f;
1030 LUT[105].direction = 1;
1031
1032 // .##
1033 // .##
1034 // ..#
1035 LUT[150].ESF = 0.179f;
1036 LUT[150].direction = 1;
1037 //----------------------
1038 //Pattern (b)
1039
1040 // ###
1041 // ###
1042 // ...
1043 LUT[31].ESF = 0.137f;
1044 LUT[31].direction = 2;
1045
1046 // ...
1047 // ###
1048 // ###
1049 LUT[248].ESF = 0.137f;
1050 LUT[248].direction = 2;
1051
1052 // ##.
1053 // ##.
1054 // ##.
1055 LUT[107].ESF = 0.137f;
1056 LUT[107].direction = 0;
1057
1058 // .##
1059 // .##
1060 // .##
1061 LUT[214].ESF = 0.137f;
1062 LUT[214].direction = 0;
1063 //----------------------
1064 //Pattern (c)
1065
1066 // ###
1067 // .#.
1068 // ...
1069 LUT[7].ESF = 0.126f;
1070 LUT[7].direction = 2;
1071
1072 // ...
1073 // .#.
1074 // ###
1075 LUT[224].ESF = 0.126f;
1076 LUT[224].direction = 2;
1077
1078 // #..
1079 // ##.
1080 // #..
1081 LUT[41].ESF = 0.126f;
1082 LUT[41].direction = 0;
1083
1084 // ..#
1085 // .##
1086 // ..#
1087 LUT[148].ESF = 0.126f;
1088 LUT[148].direction = 0;
1089 //----------------------
1090 //Pattern (d)
1091
1092 // ###
1093 // ##.
1094 // #..
1095 LUT[47].ESF = 0.10f;
1096 LUT[47].direction = 3;
1097
1098 // ..#
1099 // .##
1100 // ###
1101 LUT[244].ESF = 0.10f;
1102 LUT[244].direction = 3;
1103
1104 // ###
1105 // .##
1106 // ..#
1107 LUT[151].ESF = 0.10f;
1108 LUT[151].direction = 1;
1109
1110 // #..
1111 // ##.
1112 // ###
1113 LUT[233].ESF = 0.10f;
1114 LUT[233].direction = 1;
1115 //----------------------
1116 //Pattern (e)
1117
1118 // ##.
1119 // ##.
1120 // ...
1121 LUT[11].ESF = 0.10f;
1122 LUT[11].direction = 3;
1123
1124 // ...
1125 // .##
1126 // .##
1127 LUT[208].ESF = 0.10f;
1128 LUT[208].direction = 3;
1129
1130 // .##
1131 // .##
1132 // ...
1133 LUT[22].ESF = 0.10f;
1134 LUT[22].direction = 1;
1135
1136 // ...
1137 // ##.
1138 // ##.
1139 LUT[104].ESF = 0.10f;
1140 LUT[104].direction = 1;
1141 //----------------------
1142}

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

Referenced by allocateAndInitObjects().

◆ deallocateObjects()

void EdgeDetect::deallocateObjects ( )
private

Definition at line 966 of file edgeDetect.cpp.

967{
968 delete[] lumMap; lumMap = NULL;
969 delete[] edgeMagMap; edgeMagMap = NULL;
970 delete[] GSLCmap; GSLCmap = NULL;
971 delete[] clusters; clusters = NULL;
972}

References clusters, edgeMagMap, GSLCmap, and lumMap.

Referenced by ~EdgeDetect().

◆ fillLumMapAndLumHistogram()

void EdgeDetect::fillLumMapAndLumHistogram ( )
private

Definition at line 294 of file edgeDetect.cpp.

295{
296 int x, y;
297 QRgb* rgb;
298 uchar* scanLine;
299 int lumVal;
300 for( y=0; y<image->height(); y++)
301 {
302 scanLine = image->scanLine(y);
303 for( x=0; x<image->width(); x++)
304 {
305 //get lum value for this pixel
306 rgb = ((QRgb*)scanLine+x);
307 lumVal = qGray(*rgb);
308
309 //store in lum map
310 lumMap[x + y*image->width()] = lumVal;
311
312 //update lum histogram
313 lumHist[ lumVal ]++;
314 }
315 }
316}

References image, lumHist, and lumMap.

Referenced by EdgeDetect().

◆ findPixelClusters()

void EdgeDetect::findPixelClusters ( )
private

Definition at line 432 of file edgeDetect.cpp.

433{
434 //find max count
435 int maxCount = 0;
436 int i;
437 for(i=0; i<256; i++)
438 {
439 if(smoothLumHist[i] > maxCount)
440 maxCount = smoothLumHist[i];
441 }
442
443 //compute JND for histogram (2% of total spread)
444 int histJND = maxCount/50;
445
446 //construct temporary array for valley locations
447 //1's will indicate a valley midpoint
448 int tmpValleyArray[256];
449 for(i=0; i<256; i++) { tmpValleyArray[i] = 0; }
450
451 //move across histogram finding valley midpoints
452 int curTrackedMin = smoothLumHist[0];
453
454 //first and last indices tracked min was observed
455 int firstMinIndex = 0;
456 int lastMinIndex = 0;
457
458 //only add valley midpoint if finished tracking a descent
459 bool slopeNeg = false;
460
461 for(i = 1; i<256; i++ )
462 {
463 if( smoothLumHist[i] < curTrackedMin - histJND )
464 {
465 //found a descent!
466 slopeNeg = true;
467 curTrackedMin = smoothLumHist[i];
468 firstMinIndex = i;
469 }
470 //starting to go up again, add last min to list
471 else if( smoothLumHist[i] > curTrackedMin + histJND )
472 {
473 //if finished tracing a negative slope find midpoint and set location to true
474 if(slopeNeg)
475 {
476 tmpValleyArray[ (firstMinIndex + lastMinIndex)/2 ] = 1;
477 }
478
479 curTrackedMin = smoothLumHist[i];
480 slopeNeg = false;
481 }
482 else
483 {
484 //still tracking a min, update the right
485 //hand index. center of valley is found
486 //by averaging first and last min index
487 lastMinIndex = i;
488 }
489 }
490
491 //count valleys
492 int numValleys = 0;
493 for(i=0; i<256; i++)
494 {
495 if(tmpValleyArray[i] == 1 ) numValleys++;
496 }
497
498 //determine number of clusters
499 numClusters = numValleys-1;
500 if(tmpValleyArray[0] != 1)
501 numClusters++;
502 if(tmpValleyArray[255] != 1)
503 numClusters++;
504
505 //allocate clusters
507
508 //automatically start first cluster
509 int cluster=0;
510 clusters[cluster].minLuminance = 0;
511
512 //initialize left and right boundaries of all clusters
513 for(i=1; i<256; i++)
514 {
515 //reached next valley, end cluster
516 if( tmpValleyArray[i] == 1)
517 {
518 clusters[cluster].maxLuminance = i-1;
519 cluster++;
520 clusters[cluster].minLuminance = i;
521 }
522 //end last cluster automatically at end
523 else if(i == 255)
524 {
525 clusters[cluster].maxLuminance = i;
526 }
527 }
528
529 //determine cluster peaks
530 for(cluster=0; cluster<numClusters; cluster++)
531 {
532 //find max for current cluster
533 int maxIndex = clusters[cluster].minLuminance;
534 for(i=clusters[cluster].minLuminance; i<=clusters[cluster].maxLuminance; i++)
535 {
536 if(smoothLumHist[i] > smoothLumHist[maxIndex])
537 maxIndex = i;
538 }
539
540 //mark peaks
541 int lumJND = 255/50;
542 for(i=MAX(0, maxIndex-lumJND); i<MIN(256, maxIndex+lumJND); i++)
543 {
544 clusterPeaks[i] = 1;
545 }
546 }
547}

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

Referenced by EdgeDetect().

◆ getClusterMap()

int * EdgeDetect::getClusterMap ( )

Definition at line 244 of file edgeDetect.cpp.

245{
246 //construct map
247 int* clusterMap = new int[image->width() * image->height()];
248
249 //iterate over all pixels, determine cluster each pixel belongs to
250 int i, cluster;
251 for(i=0; i<image->width()*image->height(); i++)
252 {
253 for(cluster=0; cluster<numClusters; cluster++)
254 {
255 if( lumMap[i] >= clusters[cluster].minLuminance &&
256 lumMap[i] <= clusters[cluster].maxLuminance )
257 {
258 clusterMap[i] = cluster;
259 break;
260 }
261 } //cluster
262 } //pixel
263
264 return clusterMap;
265}

References clusters, image, lumMap, and numClusters.

Referenced by GrainEditor::GrainEditor().

◆ getClusters()

PixelCluster * EdgeDetect::getClusters ( )

Definition at line 230 of file edgeDetect.cpp.

231{ return clusters; }

References clusters.

◆ getEdgeImage()

QImage * EdgeDetect::getEdgeImage ( )

Definition at line 239 of file edgeDetect.cpp.

240{
241 return image;
242}

References image.

◆ getNumClusters()

int EdgeDetect::getNumClusters ( )

Definition at line 227 of file edgeDetect.cpp.

228{ return numClusters; }

References numClusters.

Referenced by GrainEditor::GrainEditor().

◆ getPeaks()

int * EdgeDetect::getPeaks ( )

Definition at line 233 of file edgeDetect.cpp.

234{ return clusterPeaks; }

References clusterPeaks.

◆ getSmoothHist()

int * EdgeDetect::getSmoothHist ( )

Definition at line 236 of file edgeDetect.cpp.

237{ return smoothLumHist; }

References smoothLumHist.

◆ pixelLum()

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

Definition at line 425 of file edgeDetect.cpp.

426{
427 int clampedX = MAX( MIN( x, image->width()-1), 0);
428 int clampedY = MAX( MIN( y, image->height()-1), 0);
429 return lumMap[ clampedX + clampedY * image->width() ];
430}

References image, lumMap, MAX, and MIN.

Referenced by computeEdgeMagAndGSLCmaps().

◆ smoothLumHistogram()

void EdgeDetect::smoothLumHistogram ( )
private

Definition at line 318 of file edgeDetect.cpp.

319{
320 #define FILTER_SIZE 5
321 int filter[FILTER_SIZE] = {2, 5, 8, 5, 2};
322
323 int i,j;
324 int filterIndex, sum, total;
325 for(i = 0; i<256; i++)
326 {
327 sum = 0;
328 total = 0;
329
330 for( j= -FILTER_SIZE/2; j <= FILTER_SIZE/2; j++)
331 {
332 if( i+j > 0 && i+j < 256 )
333 {
334 filterIndex = j+ FILTER_SIZE/2;
335 total+= filter[filterIndex] * lumHist[i+j];
336 sum += filter[filterIndex];
337 }
338 }
339
340 smoothLumHist[i] = total / sum;
341 }
342}
#define FILTER_SIZE

References FILTER_SIZE, lumHist, and smoothLumHist.

Referenced by EdgeDetect().

Member Data Documentation

◆ clusterPeaks

int EdgeDetect::clusterPeaks[256]
private

◆ clusters

◆ edgeMagMap

float* EdgeDetect::edgeMagMap
private

◆ GSLCmap

int* EdgeDetect::GSLCmap
private

◆ image

◆ lumHist

int EdgeDetect::lumHist[256]
private

luminosity and smooth luminosity histograms

Definition at line 96 of file edgeDetect.h.

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

◆ lumMap

◆ LUT

LUTentry EdgeDetect::LUT[256]
private

Definition at line 90 of file edgeDetect.h.

Referenced by constructEdgeImage(), and constructGSLClut().

◆ maxClusterSize

int EdgeDetect::maxClusterSize
private

Definition at line 116 of file edgeDetect.h.

Referenced by computeClusterStatistics().

◆ minClusterSize

int EdgeDetect::minClusterSize
private

Definition at line 116 of file edgeDetect.h.

Referenced by computeClusterStatistics().

◆ numClusters

int EdgeDetect::numClusters
private

◆ smoothLumHist

int EdgeDetect::smoothLumHist[256]
private

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