Colorcount

Übersicht BlitzBasic Allgemein

Neue Antwort erstellen

Triton

Betreff: Colorcount

BeitragSo, Jul 11, 2004 23:33
Antworten mit Zitat
Benutzer-Profile anzeigen
Also ich hab ein kleines Toolchen zum zählen der Farben in bildern gecodet. NIchts besonderes, war auch nicht sonderlich schwer.

Allerdings ist es so wie es ist auch nicht sonderlich schnell, ein 800x600
bild hatte bei mir 1 min gedauert.

Irgendwo ist ne gewaltige Bremse drin, vermutlich beim Array-handling.
Aber irgendwie fällt mir da nichts ein, was da falsch ist - wie auch, funktioniert ja Rolling Eyes

Code: [AUSKLAPPEN]

;** Minitool zum Farben-Zählen von Bildern
;** 2004, by Triton
Graphics 800,600,32,2
bild = LoadImage("test.bmp")
breite=ImageWidth(bild)
hoehe=ImageHeight(bild)
Dim farbe(breite*hoehe)


SetBuffer ImageBuffer(bild)
LockBuffer ImageBuffer(bild)
For scanX = 1 To breite
   For scanY = 1 To hoehe
      farbe1 = ReadPixelFast(scanX,scanY)
      If farbenanzahl = 0 Then farbe(0) = farbe1:farbenanzahl = 1
      For suchen = 0 To farbenanzahl
         If farbe1 = farbe(suchen) Then a=1:Exit
      Next
      If a=0 Then farbenanzahl = farbenanzahl + 1:farbe(farbenanzahl) = farbe1
      a=0
   Next
Next
UnlockBuffer ImageBuffer(bild)

SetBuffer FrontBuffer()
DrawBlock bild, 0,0
Color 0,0,0
Rect 0,0,300,15,1
Color 255,255,255
Text 0,0,"Dieses Bild enthält "+farbenanzahl+" Farben"

WaitKey
End

(ja, der code ist weder schön noch toll Wink)

Irgendwelche Speed-Ideen also?
  • Zuletzt bearbeitet von Triton am Mo, Jul 12, 2004 14:52, insgesamt 2-mal bearbeitet

Lord_Vader

BeitragSo, Jul 11, 2004 23:37
Antworten mit Zitat
Benutzer-Profile anzeigen
JA! Wirklich komisch, nunja. Bei dem Texturfarbenändercode, den ich gepostet habe geht das schneller. Son 500x500 bild in 1 sekunde :\
Und er schreibt ja manche pixel neu Smile

Is wahrscheinlich nur der zugriff auf den speicher. Trotzdem noch lang, bei Photoshop oder sowas macht der das auch immer sehr schnell, nunja Smile

Edit: Ganz vergessen :\ Gute arbeit ^^, ich meine ok is net wirklich schwer aber für leute, die was lernen wollen, oder für die die kein Bock haben das zu proggen Smile
 

Blitzkrieg Bop

BeitragSo, Jul 11, 2004 23:45
Antworten mit Zitat
Benutzer-Profile anzeigen
Hm, gute Arbeit(wie immer)Triton.
Nur ne kleinigkeit: Ich hab das mit nem weißen Bild getestet und da stimmt was mit dem schwarzen Balken net, wo steht wieviele Farben im Bild sind, weiß auf weiß gesellt nicht gern Wink
~ Hey Ho Let's Go ~

Triton

BeitragMo, Jul 12, 2004 0:05
Antworten mit Zitat
Benutzer-Profile anzeigen
Schreib beim Rect statt 150, 300 hin...

Wegen sowas hab ich aber nicht das Topic eröffnet - ich brauche Speed Wink
 

hot-bit

Gast

BeitragMo, Jul 12, 2004 0:14
Antworten mit Zitat
Hoi,

hab mir das noch nicht angesehen, aber beim ersten hingucken, ist mir gleich ein grober Fehler aufgefallen.

Drawblock bild, 0, 0

Und dann läßt du von x=1 und y=1 erst die Farbwerte lesen.

Also das Ergebnis wird so nie korrekt sein.

<Edit>
Habe mir das nun angeguckt.
640*480 jpg-Bild braucht über 20 Sekunden bei 32 Bit Farb-tiefe.
Mit 16 Bit nur mehr 3 Sekunden.
Die gezählten Farben sind dann aber nicht identisch.

Toni

Vertex

BeitragMo, Jul 12, 2004 0:44
Antworten mit Zitat
Benutzer-Profile anzeigen
Hi!
Erstmal liest du das Bild falsch ein.
For scanX = 0 To breite-1
sowie
For scanY = 0 To hoehe-1
muss es heißen.

Ja zu dem eigentlich Problem:
Ersteinmal https://www.blitzforum.de/viewtopic.php?t=4364
Hier kommst du bei ReadPixelFast voll auf deine Kosten genauer gesagt hier sogar um 33 mal schneller.

Weiter könntest du mal versuchen QuickSort auf die Bank anzuwenden, dann per For - Next immer 2 Werte hinterienander prüfen und gegebenenfalls den Counter hochsetzen. Wobei ich nicht wirklich denke, das dies etwas bringt.

mfg olli

Travis

BeitragMo, Jul 12, 2004 0:58
Antworten mit Zitat
Benutzer-Profile anzeigen
Ähm. Irgendwie nicht dein Tag heute Triton, oder?

Was soll das denn bewirken? Erst das Bild laden und dann in den ImageBuffer zeichnen? Wink

Code: [AUSKLAPPEN]

Bild = LoadImage("test.bmp")
[...]
SetBuffer ImageBuffer(Bild)
DrawBlock Bild, 0,0


Naja, egal. Ich konnte keine Speedbremse finden, aber viellecht war es ja nur dein Debugger? Bei mir dauerte ein 1024x768 Pixel Bild nur 3,7 Sekunden (ohne Debug, natürlich)

Ich habe dem Code mal was hinzugefügt. Jetzt werden auch die Anteile der einzelnen Farbwerte bestimmt (in Prozent).

Code: [AUSKLAPPEN]

;** Minitool zum Farben-Zählen von Bildern
;** 2004, by Triton

InputFile$ = "Test3.bmp"

Graphics 800,600,32,2
Bild = LoadImage(InputFile$)
Breite = ImageWidth(Bild)
Hoehe = ImageHeight(Bild)
Dim Farbe(Breite*Hoehe)


SetBuffer ImageBuffer(Bild)
DrawBlock Bild, 0,0

Start = MilliSecs()
LockBuffer ImageBuffer(Bild)
 For ScanX = 0 To Breite
  For ScanY = 0 To Hoehe
 
   Farbe1 = ReadPixelFast(ScanX,ScanY,ImageBuffer(Bild))
   If Farbenanzahl = 0 Then Farbe(0) = Farbe1: Farbenanzahl = 1
 
   r# = r + (Farbe1 And $FF0000)/$10000
   g# = g + (Farbe1 And $FF00)/$100
   b# = b + (Farbe1 And $FF)

   For suchen = 0 To Farbenanzahl
    If Farbe1 = Farbe(suchen) Then a=1:Exit
   Next

   If a=0 Then Farbenanzahl = Farbenanzahl + 1:Farbe(Farbenanzahl) = Farbe1
   a=0

  Next
 Next
UnlockBuffer ImageBuffer(Bild)

AppTitle Inputfile +  " ("+Breite+"x"+Hoehe+")"
SetBuffer FrontBuffer()
DrawBlock Bild, 10,80
Color 0,0,0
Rect 0,0,300,15,1
Color 255,255,255

Text 0,0,"Dieses Bild enthält "+Farbenanzahl+" Farben"

gesRGB = r+g+b
Text 0,20,"Rotanteil:  " + (r / gesRGB) * 100 + "%"
Text 0,30,"Grünanteil: " + (g / gesRGB) * 100 + "%"
Text 0,40,"Blauanteil: " + (b / gesRGB) * 100 + "%"
Text 0,60,"Zeit: " + (MilliSecs() - Start) + " ms"

WaitKey
End
www.funforge.org

Ich hasse WASD-Steuerung.

Man kann alles sagen, man muss es nur vernünftig begründen können.

Triton

BeitragMo, Jul 12, 2004 1:33
Antworten mit Zitat
Benutzer-Profile anzeigen
Zitat:
Drawblock bild, 0, 0

Und dann läßt du von x=1 und y=1 erst die Farbwerte lesen.

Ups - ändert bei den meisten Bildern aber das Ergebnis nur um paar Farben Rolling Eyes

Zitat:
Mit 16 Bit nur mehr 3 Sekunden.
Die gezählten Farben sind dann aber nicht identisch.

Das ist klar - schließlich ist nur 24/32 bit Farbtiefe "truecolor".

Zitat:
Was soll das denn bewirken? Erst das Bild laden und dann in den ImageBuffer zeichnen?


Es war spät und ich hab fanatisch nach Speedbremsen gesucht Wink
Aber jetzt ist es noch später - erklär mir bitte den Fehler Oo
Soll ich erst zeichnen und dann laden? ^^

edit--
jaja, jetzt ist es Mittags - schon klar. Vergiss es ^^
  • Zuletzt bearbeitet von Triton am Mo, Jul 12, 2004 14:53, insgesamt einmal bearbeitet

BladeRunner

Moderator

BeitragMo, Jul 12, 2004 7:50
Antworten mit Zitat
Benutzer-Profile anzeigen
Jo... ist klar dass das sehr langsam läuft. Du gehst ja immer wieder das komplette Farbfeld durch obs die Farbe denn schon gibt. Damit ist deine Routine nur dann wirklich schnell, wenn ein Bild die häufigsten Farben zu Beginn der Bitmap enthält (und selbst dann fressen die ganzen if noch ne Menge Zeit).
Hab mir mal erlaubt das Ganze auf ne Bank umzustellen. Geprüft werden nur die 24 Farben-Bit, die 8 Bit Transparenz sind aussen vor (sie wären leicht einzubauen, allerdings hätte die Bank dann die stolze Größe von 512 Mb im Vergleich zu 2Mb bei 24 Bit. Wer genug Speicher hat möge es ausführen...)
"Vorteil" ist hier auch dass die Routine bei gleicher Bildgröße immer etwa gleich lange braucht, da Bild als auch Bank nur jeweils einmal durchlaufen werden.

Testdurchlauf1: 800*600 Pixel, das Bild hatte 92499 Farben:

Triton: 131,08 Sekunden
Triton @24 Bit (mit AND $FFFFFF maskiert): 129,072 Sekunden
BladeRunner: 5,196 Sekunden
Tritons Routine ermittelete zudem eine Farbe zu wenig (wurde mit verschiedenen Bitmaps kontrolliert, nur 1 Farbe wird korrekt ermittelt, ab 2 Farben ist das Ergebnis eins zu niedrig.)

Testdurchlauf2: 800*600 Pixel, das Bild hatte 4 Farben:
Triton: 0,311 Sekunden
Triton@24 bit: 0,322 Sekunden
BladeRunner: 5,04 Sekunden
Hier ist eine direkte Farbenzählung natürlich absolut im Vorteil.


Und der Code:
Code: [AUSKLAPPEN]
;** Minitool zum Farben-Zählen von Bildern
;** 2004, by Triton
;** VERSION 2 mit Bank by BladeRunner
Graphics 800,600,32,2
bild = LoadImage("test.bmp")
breite=ImageWidth(bild)
hoehe=ImageHeight(bild)
farbfeld=CreateBank(2097152)



SetBuffer ImageBuffer(bild)

LockBuffer ImageBuffer(bild)
start=MilliSecs()
For scanX = 0 To breite-1
   For scanY = 0 To hoehe-1
       farbe1# = ReadPixelFast(scanX,scanY) And $FFFFFF
       byte#=Floor(farbe1/8)
      bit#=farbe1 Mod 8
      altwert=PeekByte(farbfeld,byte)
      PokeByte farbfeld,byte,(altwert Or (2^bit))
   Next
Next
UnlockBuffer ImageBuffer(bild)
For schleife = 0 To 2097151
   wert=PeekByte(farbfeld,schleife)
   For zaehl=0 To 7
      If (wert And 2^zaehl) Then
         farbzahl= farbzahl+1
      End If
   Next
Next
endzeit#=MilliSecs()-start
SetBuffer FrontBuffer()
DrawBlock bild, 0,0
Color 0,0,0
Rect 0,0,300,35,1
Color 255,255,255
Text 0,0,"Dieses Bild enthält "+farbzahl+" Farben"
Text 0,20,"Ermittelt in "+(endzeit/1000)+" Sekunden"
WaitKey
End
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92

Triton

BeitragMo, Jul 12, 2004 14:51
Antworten mit Zitat
Benutzer-Profile anzeigen
Sehr schön. Super Optimiert.

Dennoch frage ich mich, wie gängige Tools (etwa Irfanview) dies in jedem Fall in weniger als 1 sek Schaffen.

Jan_

Ehemaliger Admin

BeitragMo, Jul 12, 2004 14:56
Antworten mit Zitat
Benutzer-Profile anzeigen
ganz einfach, indem die das Bild nicht Pixel für Pixel aus dem Grafikspeicher laden, sondern entweder im arrey abgelegt haben, oder das Dateiformat öffnen!
between angels and insects
 

David

BeitragMo, Jul 12, 2004 15:08
Antworten mit Zitat
Benutzer-Profile anzeigen
Hi!

Was Jan_ mit dem "Dateiformat öffnen" meinte weis ich zwar nicht, aber im Normalfall liest man die Pixeldaten tatsächlich nicht aus dem Grafikspeicher sondern hat eben, wie schon gesagt, ein Bytearray. Wenn man dieses nun durchsucht ist das ganze wesentlich schneller. Smile

grüße
http://bl4ckd0g.funpic.de

TheShadow

Moderator

BeitragMo, Jul 12, 2004 18:24
Antworten mit Zitat
Benutzer-Profile anzeigen
oje warum habt ihr floats drinne?

ich habe hier von meinem editor noch so eine routine drinne - muss mal etwas anpassen...
AMD64 3500+ | GeForce6600GT 128MB | 1GB DDR | WinXPsp2

Rallimen

Sieger des 30-EUR-Wettbewerbs

BeitragMo, Jul 12, 2004 18:36
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich habe mal nachgedacht, und ohne sortieralgo wüßte ich jetzt nicht wie das schneller gehen könnte, werde da mal was testen....
[BB2D | BB3D | BB+]

Rallimen

Sieger des 30-EUR-Wettbewerbs

BeitragMo, Jul 12, 2004 20:12
Antworten mit Zitat
Benutzer-Profile anzeigen
so hab da mal meine idee umgesetzt,
....bei 800 x 600 Bildern egal wie viele farben immer so um 450 millisecs
das Bild habe ich mal mit rein gebaut , könnt natürlich auch eins laden!
Code: [AUSKLAPPEN]
;** Minitool zum Farben-Zählen von Bildern
;** 2004, by Triton
Graphics 800,600,32,2
;bild = LoadImage("test.jpg")
;Bild erstellen
Bild = CreateImage (800,600)
SetBuffer ImageBuffer (bild)
For x =0 To 800 Step 5
For y =0 To 600 Step 5
Rect  x,y,2,2,1
Color Rand (0,255),Rand (0,255),Rand (0,255)
Next
Next

SetBuffer FrontBuffer()
DrawBlock bild, 0,0

breite=ImageWidth(bild)
hoehe=ImageHeight(bild)
Dim farbe(breite * hoehe)

timer1 = MilliSecs()
SetBuffer ImageBuffer(bild)
LockBuffer ImageBuffer(bild)

For scanX = 0 To breite -1
   For scanY = 0 To hoehe -1
      farbe(z) = ReadPixelFast(scanX,scanY)
     z= z +1
   Next
Next
UnlockBuffer ImageBuffer(bild)
quicksort(0,breite*hoehe)
For z = 1 To breite * hoehe
   If  Farbe (z -1) <>  Farbe (z) Then farbenanzahl = farbenanzahl +1
Next
timer1 = MilliSecs() -timer1
SetBuffer FrontBuffer()
DrawBlock bild, 0,0
Color 0,0,0
Rect 0,0,300,30,1
Color 255,255,255

Text 0,0,"Dieses Bild enthält "+farbenanzahl+" Farben"
Text 0,15,"Dieses Bild dauerte "+timer1 + " Millisek."
WaitKey
Cls
For t= 0 To breite*hoehe
DebugLog Farbe (t)
Next
End

; Speedsort
Function quicksort(l,r)
  Local p,q,h
  p=l :  q=r
  x=Farbe((l+r)/2)
  Repeat
    While Farbe(p)<x
      p=p+1
    Wend
    While x<Farbe(q)
      q=q-1
    Wend
    If p>q Then Exit
   ;SWAP------------------

   h=Farbe (q)
   Farbe (q)=Farbe (p)
   Farbe (p)=h
   ;----------------------
    p=p+1
    q=q-1
    If q<0 Then Exit
  Forever
  If l<q Then a=quicksort(l,q)
  If p<r Then a=quicksort(p,r)
  Return True
End Function
[BB2D | BB3D | BB+]

Triton

BeitragDi, Jul 13, 2004 0:13
Antworten mit Zitat
Benutzer-Profile anzeigen
Sehr schön. Wirklich erstaunlich verschnellert.

Wenn das Forum ein "daumen-hoch" Bild hätte, würde ich es jetzt posten.

Travis

BeitragDi, Jul 13, 2004 0:53
Antworten mit Zitat
Benutzer-Profile anzeigen
user posted image

Gute Idee. Nachdem Rallimen vorhin die Idee hatte mit 'nem Sortieralgo an die Sache ran zu gehen, habe ich's auch noch mal vrsucht, bin aber gescheitert, weil mir keine schnelle Methode dazu bekannt war.
www.funforge.org

Ich hasse WASD-Steuerung.

Man kann alles sagen, man muss es nur vernünftig begründen können.
 

hot-bit

Gast

BeitragDi, Jul 13, 2004 6:37
Antworten mit Zitat
Hoi,

nur mal so eine Frage am Rande:

Für was braucht man das eigentlich ?

Toni

BladeRunner

Moderator

BeitragDi, Jul 13, 2004 11:08
Antworten mit Zitat
Benutzer-Profile anzeigen
Respekt Rallimen!
Schneller gehgts wohl echt nimmer Shocked
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92

TheShadow

Moderator

BeitragDi, Jul 13, 2004 18:10
Antworten mit Zitat
Benutzer-Profile anzeigen
jo gute idee...
AMD64 3500+ | GeForce6600GT 128MB | 1GB DDR | WinXPsp2

Neue Antwort erstellen


Übersicht BlitzBasic Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group