Ik ben momenteel een programma aan het schrijven waarvoor ik 2 afbeeldingen moet vergelijken, en een getal teruggeven die de orde van gelijkenis uitdrukt (hoger = sterker gelijkend). Onderdeel van de fitness() functie van een GA 
Anyway, de afbeeldingen zijn Cairo surfaces, waarvan ik momenteel de raw data (unsigned char*) en die pixel voor pixel vergelijk. Elke pixel is 4 bytes in de reeks karakters (BGRA), waarvan ik voor elk kleur het verschil tussen beide kwadrateer, en per pixel die onder een wortel zet en bij een variabele optel (difference += sqrt( (red2-red1)² + (blue2-blue1)² + (green2-green1)²)). De uiteindelijke "resemblance" factor is dan 1 op die "difference" factor.
Ik ben hier op gekomen naar analogie van de gewone afstand tussen twee punten, maar ik weet niet in welke mate dit de beste methode is.
Nu heb ik al wat rondgezocht op internet, maar ik heb niet echt een algoritme gevonden dat echt gericht is op snelheid (of het moet een gewone memcpy geweest zijn, die te eenvoudig is in dit geval). Aangezien deze routine heel veel gecallt wordt (profiling maakt duidelijk dat ik >70% in deze functie vertoef) ben ik dus begonnen met het optimaliseren van de functie. Maar dat lukte ook niet echt, bitwise operators gaf geen snelheidsboost, en zelf OpenMP introduceren blijkt teveel overhead te geven (shared variable).
Momenteel ziet de code er al volgt uit:
Gprof:
Kan deze functie nog verder geoptimaliseerd worden? Of is het helemaal geen goede manier van afbeeldingen vergelijken, en bestaat er een beter/sneller alternatief?
Alvast bedankt
maleadt
Anyway, de afbeeldingen zijn Cairo surfaces, waarvan ik momenteel de raw data (unsigned char*) en die pixel voor pixel vergelijk. Elke pixel is 4 bytes in de reeks karakters (BGRA), waarvan ik voor elk kleur het verschil tussen beide kwadrateer, en per pixel die onder een wortel zet en bij een variabele optel (difference += sqrt( (red2-red1)² + (blue2-blue1)² + (green2-green1)²)). De uiteindelijke "resemblance" factor is dan 1 op die "difference" factor.
Ik ben hier op gekomen naar analogie van de gewone afstand tussen twee punten, maar ik weet niet in welke mate dit de beste methode is.
Nu heb ik al wat rondgezocht op internet, maar ik heb niet echt een algoritme gevonden dat echt gericht is op snelheid (of het moet een gewone memcpy geweest zijn, die te eenvoudig is in dit geval). Aangezien deze routine heel veel gecallt wordt (profiling maakt duidelijk dat ik >70% in deze functie vertoef) ben ik dus begonnen met het optimaliseren van de functie. Maar dat lukte ook niet echt, bitwise operators gaf geen snelheidsboost, en zelf OpenMP introduceren blijkt teveel overhead te geven (shared variable).
Momenteel ziet de code er al volgt uit:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| // Compare two images double compare(cairo_surface_t* inputSurface) const { // Get the raw data of the given surface unsigned char* tempData1 = dataInputRGB24; unsigned char* tempData2 = cairo_image_surface_get_data(inputSurface); // Compare them int i, db, dg, dr; long int difference = 0; #pragma omp parallel for private(dr, dg, db) reduction(+:difference) for (i = 0; i < dataInputWidth*dataInputHeight*4; i+=4) { // RGBa db = tempData1[i] - tempData2[i]; dg = tempData1[i+1] - tempData2[i+1]; dr = tempData1[i+2] - tempData2[i+2]; // Calculate difference difference += sqrt(dr*dr + dg*dg + db*db); } // Get resemblance double resemblance = dataInputWidth*dataInputHeight / double(difference); return resemblance; } |
Gprof:
code:
1
2
3
| 0.00 1.15 204/204 EnvImage::fitness(DNA const&) const [4] [5] 74.5 0.00 1.15 204 EnvImage::compare(_cairo_surface*) const [5] 1.15 0.00 204/205 EnvImage::~EnvImage() [3] |
Kan deze functie nog verder geoptimaliseerd worden? Of is het helemaal geen goede manier van afbeeldingen vergelijken, en bestaat er een beter/sneller alternatief?
Alvast bedankt
maleadt