Absolute Differenz von Bild berechnen



  • Hallo,
    ich möchte von einem 8*8 Ausschnitt eines Bildes die Sum Of Absolute Difference berechnen.

    Dazu habe ich die folgenden 2 defines geschrieben

    #define absDiff(a1,a2) (((a1)>(a2))?a1-a2:a2-a1)
    #define CalculateDifference(a,b) \
     absDiff(a[0*imSizeX+0],b[0*imSizeX+0])+absDiff(a[0*imSizeX+1],b[0*imSizeX+1])+absDiff(a[0*imSizeX+2],b[0*imSizeX+2])+absDiff(a[0*imSizeX+3],b[0*imSizeX+3])\
    +absDiff(a[0*imSizeX+4],b[0*imSizeX+4])+absDiff(a[0*imSizeX+5],b[0*imSizeX+5])+absDiff(a[0*imSizeX+6],b[0*imSizeX+6])+absDiff(a[0*imSizeX+7],b[0*imSizeX+7])\
    +absDiff(a[1*imSizeX+0],b[1*imSizeX+0])+absDiff(a[1*imSizeX+1],b[1*imSizeX+1])+absDiff(a[1*imSizeX+2],b[1*imSizeX+2])+absDiff(a[1*imSizeX+3],b[1*imSizeX+3])\
    +absDiff(a[1*imSizeX+4],b[1*imSizeX+4])+absDiff(a[1*imSizeX+5],b[1*imSizeX+5])+absDiff(a[1*imSizeX+6],b[1*imSizeX+6])+absDiff(a[1*imSizeX+7],b[1*imSizeX+7])\
    +absDiff(a[2*imSizeX+0],b[2*imSizeX+0])+absDiff(a[2*imSizeX+1],b[2*imSizeX+1])+absDiff(a[2*imSizeX+2],b[2*imSizeX+2])+absDiff(a[2*imSizeX+3],b[2*imSizeX+3])\
    +absDiff(a[2*imSizeX+4],b[2*imSizeX+4])+absDiff(a[2*imSizeX+5],b[2*imSizeX+5])+absDiff(a[2*imSizeX+6],b[2*imSizeX+6])+absDiff(a[2*imSizeX+7],b[2*imSizeX+7])\
    +absDiff(a[3*imSizeX+0],b[3*imSizeX+0])+absDiff(a[3*imSizeX+1],b[3*imSizeX+1])+absDiff(a[3*imSizeX+2],b[3*imSizeX+2])+absDiff(a[3*imSizeX+3],b[3*imSizeX+3])\
    +absDiff(a[3*imSizeX+4],b[3*imSizeX+4])+absDiff(a[3*imSizeX+5],b[3*imSizeX+5])+absDiff(a[3*imSizeX+6],b[3*imSizeX+6])+absDiff(a[3*imSizeX+7],b[3*imSizeX+7])\
    +absDiff(a[4*imSizeX+0],b[4*imSizeX+0])+absDiff(a[4*imSizeX+1],b[4*imSizeX+1])+absDiff(a[4*imSizeX+2],b[4*imSizeX+2])+absDiff(a[4*imSizeX+3],b[4*imSizeX+3])\
    +absDiff(a[4*imSizeX+4],b[4*imSizeX+4])+absDiff(a[4*imSizeX+5],b[4*imSizeX+5])+absDiff(a[4*imSizeX+6],b[4*imSizeX+6])+absDiff(a[4*imSizeX+7],b[4*imSizeX+7])\
    +absDiff(a[5*imSizeX+0],b[5*imSizeX+0])+absDiff(a[5*imSizeX+1],b[5*imSizeX+1])+absDiff(a[5*imSizeX+2],b[5*imSizeX+2])+absDiff(a[5*imSizeX+3],b[5*imSizeX+3])\
    +absDiff(a[5*imSizeX+4],b[5*imSizeX+4])+absDiff(a[5*imSizeX+5],b[5*imSizeX+5])+absDiff(a[5*imSizeX+6],b[5*imSizeX+6])+absDiff(a[5*imSizeX+7],b[5*imSizeX+7])\
    +absDiff(a[6*imSizeX+0],b[6*imSizeX+0])+absDiff(a[6*imSizeX+1],b[6*imSizeX+1])+absDiff(a[6*imSizeX+2],b[6*imSizeX+2])+absDiff(a[6*imSizeX+3],b[6*imSizeX+3])\
    +absDiff(a[6*imSizeX+4],b[6*imSizeX+4])+absDiff(a[6*imSizeX+5],b[6*imSizeX+5])+absDiff(a[6*imSizeX+6],b[6*imSizeX+6])+absDiff(a[6*imSizeX+7],b[6*imSizeX+7])\
    +absDiff(a[7*imSizeX+0],b[7*imSizeX+0])+absDiff(a[7*imSizeX+1],b[7*imSizeX+1])+absDiff(a[7*imSizeX+2],b[7*imSizeX+2])+absDiff(a[7*imSizeX+3],b[7*imSizeX+3])\
    +absDiff(a[7*imSizeX+4],b[7*imSizeX+4])+absDiff(a[7*imSizeX+5],b[7*imSizeX+5])+absDiff(a[7*imSizeX+6],b[7*imSizeX+6])+absDiff(a[7*imSizeX+7],b[7*imSizeX+7])\
    

    also ich glaube die Namensgebung ist klar. imSizeX ist ist die Bildgröße und da das Bild in einem 1D Array gespeichert ist springe ich immer durch y*imSizeX in die nächste Zeile.

    Leider ist das ziemlich langsam. ich bin davon ausgegangen das der Compiler die Berechnung von y*imSizeX+x im Vorhinein macht das müßte doch so sein. Kann ich das irgendwo nachschauen. Außerdem was haltet ihr von meinem Define absDiff sollte ich das nehmen oder abs(a-b). Ich hatte gelesen das es besser ist das so zu schreiben wie ich damit der Compiler das optimieren kann.

    Ich freue mich über Meinungen

    dankeschön

    p.s. Äh ich meine natürlich ich ich möchte die Sum of Absolute Difference von zwei Bildern berechnen. Also Array a ist von Bild1 und Array b ist von Bild2



  • define ? Du benutzt vermutlich auch eine Steinaxt.



  • Hast du schon mal was von Schleifen und von Funktionen gehört?

    Warum programmierst du abs überhaupt selber und nimmst nicht std::abs?

    Fragen über Fragen...



  • Schon mal was von Schleifen gehört?



  • ja schon klar aber ich dachte wenn ich die Schleife rauslasse gehts schneller weil das Program dann nich zur laufzeit rechnen muss

    uint32_t diff=0;
    for(uint16_t iy=0; iy<8*imsSizeX; iy+=imSizeX){
           for(uint16_t ix=0; ix<8; ix++){
                diff+=std::abs(image1[ix+iy]-image2[ix+iy]);
    }
    }
    

    also ihr meint sowas geht schneller?



  • Ich bin mal so frei und behaupte, dass es mit einer Schleife u.U. sogar schneller ist, weil der Compiler das als SIMD-Pattern erkennen kann.



  • Ich gebe gleich mal das Ergebnis ich lass ihn gerade Testen mit gprof



  • also meine Veriante mit
    #define abs(a-b)
    #define das große...

    Each sample counts as 0.01 seconds.
      %   cumulative   self              self     total           
     time   seconds   seconds    calls  us/call  us/call  name    
     79.02    111.41   111.41                             FilterFlow_BrutForc_
    

    -> das sind auf eine Kachelberechnugn runter gebrochen 1.9us pro 8*8 Kachel



  • mit #define absDiff(a1,a2) (((a1)>(a2))?a1-a2:a2-a1)

    Each sample counts as 0.01 seconds.
      %   cumulative   self              self     total           
     time   seconds   seconds    calls  us/call  us/call  name    
     84.74    167.09   167.09
    

    -> 3 us

    Mist!



  • Vergleich mal mit einer Inline-Funktion und Schleife...



  • bin ich gerade dabei.
    Ist ein Embedded Arm der hat zwar 1Ghz dauert aber trotzdem 😉



  • mit der for-schleife ist es das Selbe wie beim Ersten.Hab die auch mal als #define gemacht nicht schön aber ging am schnellsten zu Implmentieren. ich hoffe das hat die selbe Wirkung wie Inline

    Each sample counts as 0.01 seconds.
      %   cumulative   self              self     total           
     time   seconds   seconds    calls  us/call  us/call  name    
     79.11    112.53   112.53                             FilterFlow_BrutForc
    
    #define CalculateDifference(a,b)\
    	uint32_t ergebniss=0;\
    	for(uint16_t iy=0; iy<8*imSizeX; iy+=imSizeX) { \
    		for(uint16_t ix=0; ix<8; ix++) { \
    			ergebniss+=std::abs(a[ix+iy]-b[ix+iy]);\
    		}\
    	}\
    

  • Mod

    Um sicher zu sein: Du benutzt ein optimiertes Compilat?



  • ja
    das habe ich mir als Makefile geschrieben. Ist das in Ordnung?

    CC=g++
    CFLAGS=-c -DRELEASE -UDEBUG  -Wall -g -pg -O3
    LDFLAGS=-g -pg  -lgsl -lgslcblas
    SOURCES=main.cpp debugOwn.cpp FeatGSLMest.cpp FilterFeature_Diff_follow.cpp \
     FilterFlow_BrutForc_follow2.cpp  FlowConstDef.cpp \
    global.cpp LogModul.cpp  mathFunctions.cpp netTcp.cpp \
    VideoDevice_Load.cpp VideoDevice_Caspa.cpp BaseClasses/FeatureCalcGSLBase.cpp \
    BaseClasses/FeatureCalcBase.cpp
    
    OBJECTS=$(SOURCES:.cpp=.o)
    EXECUTABLE=hello
    
    all: $(SOURCES) $(EXECUTABLE)
    
    $(EXECUTABLE): $(OBJECTS)
    	$(CC) $(LDFLAGS) $(OBJECTS) -o $@
    
    .cpp.o:
    	$(CC) $(CFLAGS) $< -o $@
    
    clean:
    	rm -rf *o hello
    
    totalclean:
    
    	rm -rf *o BaseClasses/*o hello
    


  • flexbex schrieb:

    Kann ich das irgendwo nachschauen.

    Guck dir die Disassembly an. Dann weisst du was für Code entsteht.

    Falls kein SIMD Code draus wird, und dein Compiler SIMD-Intrinsics hat, dann kannst du mit denen vermutlich nochmal ordentlich was rausholen.



  • Kannst du mir dabei helfen. Weisst du wie ich mir die von der Commandline ausgeben lassen kann. Aber das finde ich zur not noch raus.

    Aber wie geht das mit SIMD ich habs beim googlen nur überflogen. Also für Arm Prozessoren sollte das ja grundsätzlich funktionieren. Vielleicht kannst du mir auch ne gute stelle zum nachschauen gebn.
    thx



  • Wozu das -g Compilerflag?


  • Mod

    Mit march=dein_prozessortyp kann (nicht muss) eventuell noch mehr rausgeholt werden. Kann sich auch negativ auswirken.
    http://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html

    Nexus schrieb:

    Wozu das -g Compilerflag?

    Ist doch ganz nuetzlich fuer den Profiler. Debugsymbole != Debugcode



  • 😉 genau das hab ich auch gerade gelesen. Ich nehm die mal raus
    Die war noch vom debuggen drin



  • flexbex schrieb:

    Kannst du mir dabei helfen. Weisst du wie ...

    Nö, sorry.
    Ich bin ein Windows-Mann. Bei MSVC kann ich dir das alles ausm Stegreif erklären. GCC, GDB etc. = kein Plan. Da hab' ich inetwa nen Überblick was der so kann, aber wie man es genau anstellt müsste ich mir selbst ergoogeln.
    Ebenso was ARM angeht.

    Als Tip kann ich dir nur geben: möglicherweise findest du SIMD Code für verschiedene Compiler/Architekturen für sehr ähnliche oder sogar identische Sachen in der OpenCV. Oder sonstigen Bildberabeitungs-Libraries. Und wenn du ganz viel Glück hast ist die Kombination GCC/ARM dabei 😉


Anmelden zum Antworten