rgb zu hsv und zurück beschleunigen?

Probleme beim Erstellen von 3D-Modellen und Texturen, keine Ahnung womit man Musik macht? Dies ist dein Forum.
Benutzeravatar
The_Dark_Zim-.-
Beiträge: 372
Registriert: 18.03.2008 16:53

rgb zu hsv und zurück beschleunigen?

Beitrag von The_Dark_Zim-.- »

Hey ho

ich versuche gerade eine Texture umfärben su lassen. Klappt soweit ganz gut aber mir ist die ganze sache noch etwas zu langsam. Ich habe ein Bild/Texture von 2048*2048 welche ich umfärben will.
Vllt hat ja der ein oder andere eine Idee wie man es schneller machen kann.

Code: Alles auswählen

Global H.d,S.d,V.d

Procedure RGB_To_HSV(ColorRed.d,ColorGreen.d,ColorBlue.d)
  
  MinColor.d
  MaxColor.d
  
  ColorRed / 255
  ColorGreen / 255
  ColorBlue / 255
  
  If ColorRed < ColorGreen
    MinColor = ColorRed
  Else
    MinColor = ColorGreen
  EndIf
  If MinColor > ColorBlue
    MinColor = ColorBlue
  EndIf
  If ColorRed > ColorGreen
    MaxColor = ColorRed
  Else
    MaxColor = ColorGreen
  EndIf
  If MaxColor < ColorBlue
    MaxColor = ColorBlue
  EndIf
  
  If MaxColor = MinColor
    H = 0
  ElseIf MaxColor = ColorRed
    H = 60 * ((ColorGreen-ColorBlue)/(MaxColor-MinColor))
  ElseIf MaxColor = ColorGreen
    H = 60 * (2+((ColorBlue-ColorRed)/(MaxColor-MinColor)))
  ElseIf MaxColor = ColorBlue
    H = 60 * (4+((ColorRed-ColorGreen)/(MaxColor-MinColor)))
  EndIf
  
  If MaxColor = 0
    S = 0
    H = 0
  Else
    S = (MaxColor-MinColor)/MaxColor
  EndIf
  
  V = MaxColor
  
EndProcedure

Procedure.l HSV_To_RGB()
  
  ColorRed.d
  ColorGreen.d
  ColorBlue.d
  
  If S = 0
    ColorRed = V
    ColorGreen = V
    ColorBlue = V
  Else
    
    hi.d = H/60
    l = Round(hi, #PB_Round_Down)
    f.d = hi-l
    p.d = V * (1-S)
    q.d = V * (1-S*f)
    t.d = V * (1-S*(1-f))
    
    If l = 1
      ColorRed = q
      ColorGreen = V
      ColorBlue = p
    ElseIf l = 2
      ColorRed = p
      ColorGreen = V
      ColorBlue = t
    ElseIf l = 3
      ColorRed = p
      ColorGreen = q
      ColorBlue = V
    ElseIf l = 4
      ColorRed = t
      ColorGreen = p
      ColorBlue = V
    ElseIf l = 5
      ColorRed = V
      ColorGreen = p
      ColorBlue = q
    Else
      ColorRed = V
      ColorGreen = t
      ColorBlue = p
    EndIf
  EndIf
  
  ProcedureReturn Color.l = RGB(ColorRed * 255,ColorGreen * 255,ColorBlue * 255)
EndProcedure

Procedure ChangeColor(Grad)
  
  StartTime = ElapsedMilliseconds()  
  
  If IsImage(1) = 0
    
    LoadImage(1,"media\CarTexture.bmp")
    LoadImage(3,"media\TailLight.png")
    CreateImage(2,ImageWidth(1),ImageHeight(1),ImageDepth(1))
    
    Global Dim Color(ImageWidth(1),ImageHeight(1))
    
    StartDrawing(ImageOutput(1))
    
    For i = 0 To ImageHeight(1)-1
      
      For j = 0 To ImageWidth(1)-1
        
        Color(j, i) = Point(j, i)
        
      Next j
      
    Next
    StopDrawing()
    
  EndIf
  
  i = 0
  j = 0
  
  StartDrawing(ImageOutput(2))
  For i = 0 To ImageHeight(1)-1
    
    For j = 0 To ImageWidth(1)-1
      
      RGB_To_HSV(Red(Color(j,i)),Green(Color(j,i)),Blue(Color(j,i)))
      
      H + Grad
      
      If H < 0
        H + 360
      ElseIf H > 360
        H - 360
      EndIf   
      
      Plot(j,i,HSV_To_RGB())
      
    Next j
    
  Next  
  
  DrawAlphaImage(ImageID(3), 0, 0)
  
  StopDrawing()  
  
  SaveImage(2,"media\NewTexture.bmp",#PB_ImagePlugin_BMP)
  
  Debug ElapsedMilliseconds()-StartTime
EndProcedure
Ja ich habe auch ohne Debuger getestet ^^

Testsystem:
Win7 Ultimate
PB 4.6 x86
Intel Core 2 Duo T5250 @ 1,5ghz
2GB Ram
Nvidia Gforce 8600M GS 256mb

Gruß Zim
Zuletzt geändert von The_Dark_Zim-.- am 28.02.2012 23:06, insgesamt 1-mal geändert.
PB: 5.xx LTS x86/x64 | WIN: 10 Pro x64, Linux Mint x64
Benutzeravatar
WPö
Moderator
Beiträge: 669
Registriert: 27.05.2008 12:44
Wohnort: Oberland
Kontaktdaten:

Re: rgb zu hsv und zurück beschleunigen?

Beitrag von WPö »

Öööhh. Kenne mich da ja nicht sooo aus, aber ich glaube, das sollte sich mit 'ner GPU doch wohl erheblich beschleunigen lassen. Das gab's doch schon vor ein, zwei Tagen eine Frage zu dem Thema. Such doch mal danach.

Gruß - WPö
Ich glaube nur der Statistik, die ich selbst gefälscht habe!
Meine Netzpräsenz: WPö.de
PB5.31 auf LMDE und Pentium T7200 2,00GHz, 4GB DDR2, ATI X1400.
Benutzeravatar
The_Dark_Zim-.-
Beiträge: 372
Registriert: 18.03.2008 16:53

Re: rgb zu hsv und zurück beschleunigen?

Beitrag von The_Dark_Zim-.- »

Ja das habe ich gesehen ;) Hab ich auch schon dran gedacht, aber ich denke das an diesem Code auch so noch Verbesserungen möglich sind :)
PB: 5.xx LTS x86/x64 | WIN: 10 Pro x64, Linux Mint x64
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 6996
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: rgb zu hsv und zurück beschleunigen?

Beitrag von STARGÅTE »

Ich weiß nicht genau ob meins schneller ist, aber ich hatte vor einigen Monaten mal ein paar Proceduren dazu geschrieben, welche die Funktion CustomFilterCallback() nutzen, und damit etwas schneller sein könnten, u.a. auch eine für dein Zweck:
ImageColorRotation(Image.i, Angle.f)
http://www.purebasic.fr/german/viewtopi ... 63#p291263
EInfach das Bild "reinwerfen" und den Winkel angeben, fertig.

Natürlich musst du solche rechenintensiven Funktionen immer ohne Debugger starten, weil der sonst viel Zeit frisst.

Edit: Dein Code könnte schon mal schneller laufen wenn du sowas vermeidest:

Code: Alles auswählen

For i = 0 To ImageHeight(1)-1
Weil dann mit jedem Durchgang erneut das Image "gesucht" wird und die Height - 1 gerechnet wird.
Dann lieber:

Code: Alles auswählen

max_i = ImageHeight(1)-1
For i = 0 To max_i
oder

Code: Alles auswählen

For i = ImageHeight(1)-1 To 0 step -1
weil der For-Parameter nur einmal ausgewertet wird, der To-Parameter hingegen immer.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
The_Dark_Zim-.-
Beiträge: 372
Registriert: 18.03.2008 16:53

Re: rgb zu hsv und zurück beschleunigen?

Beitrag von The_Dark_Zim-.- »

Hey

ja wo du es sagst ist natürlich ein blöder Fehler ^^ Hat es bei mir mit Debuger 100ms schneller gemacht :)
ich guck mir mal die Sachen an.

Edit:
So habe mir deins mal durchgeguckt. Sieht in meinen Augen aus wie das Selbe nur kleiner wegen Select und CustomFilterCallback ^^
PB: 5.xx LTS x86/x64 | WIN: 10 Pro x64, Linux Mint x64
Benutzeravatar
Thorium
Beiträge: 1722
Registriert: 12.06.2005 11:15
Wohnort: Germany
Kontaktdaten:

Re: rgb zu hsv und zurück beschleunigen?

Beitrag von Thorium »

Ich sehe jede Menge Optimierungsmöglichkeiten.
Die offensichtlichste zuerst: Warum überhaupt nach HSV umrechnen und wieder zurück, warum färbst du nicht im RGB-System um?

Dann nutzt du Point, das durch direkten Zugriff auf den Speicher ersetzen. Stichwort: DrawingBuffer

Wenn du die beiden Sachen änderst sollte es minimum 10 fach schneller werden.
The_Dark_Zim-.- hat geschrieben: ja wo du es sagst ist natürlich ein blöder Fehler ^^ Hat es bei mir mit Debuger 100ms schneller gemacht :)
ich guck mir mal die Sachen an.
Immer ohne Debugger testen, nicht nur weil ersn unnötig verlangsamt, sondern er verfälscht auch das Ergebnis, da verschiedener Code unterschiedlich durch den Debugger verlangsamt wird.
Zu mir kommen behinderte Delphine um mit mir zu schwimmen.

Wir fordern mehr Aufmerksamkeit für umfallende Reissäcke! Bild
Benutzeravatar
The_Dark_Zim-.-
Beiträge: 372
Registriert: 18.03.2008 16:53

Re: rgb zu hsv und zurück beschleunigen?

Beitrag von The_Dark_Zim-.- »

Ich wandle das ganze zum HSV-Farbbaum um damit ich die Farben gleichmäßig ändern kann. Ich weiss nicht wie ich das nur mit RGB machen soll.

Okey werde mich mal ran machen das mit dem DrawBuffer um zu setzen.

Ich teste doch nur im Debugger um zu sehen ob es überhaupt einen Unterschied gibt ;)
Ich habe doch ganz oben geschrieben das ich auch ohne getestet habe.

Gruß Zim

Edit:

So ich habe das ganze nun auf DrawingBuffer umgestellt. Es schwangt bei mir extrem zwischen ~400 bis ~1700 :|

Achja die Texture hat nur eine Auflösung von 1024*1024 <)

Code: Alles auswählen

Global H.d,S.d,V.d

Structure Pixel
  Pixel.l
EndStructure

Procedure RGB_To_HSV(ColorRed.d,ColorGreen.d,ColorBlue.d)
  
  MinColor.d
  MaxColor.d
  
  ColorRed / 255
  ColorGreen / 255
  ColorBlue / 255
  
  If ColorRed < ColorGreen
    MinColor = ColorRed
  Else
    MinColor = ColorGreen
  EndIf
  If MinColor > ColorBlue
    MinColor = ColorBlue
  EndIf
  If ColorRed > ColorGreen
    MaxColor = ColorRed
  Else
    MaxColor = ColorGreen
  EndIf
  If MaxColor < ColorBlue
    MaxColor = ColorBlue
  EndIf
  
  If MaxColor = MinColor
    H = 0
  ElseIf MaxColor = ColorRed
    H = 60 * ((ColorGreen-ColorBlue)/(MaxColor-MinColor))
  ElseIf MaxColor = ColorGreen
    H = 60 * (2+((ColorBlue-ColorRed)/(MaxColor-MinColor)))
  ElseIf MaxColor = ColorBlue
    H = 60 * (4+((ColorRed-ColorGreen)/(MaxColor-MinColor)))
  EndIf
  
  If MaxColor = 0
    S = 0
    H = 0
  Else
    S = (MaxColor-MinColor)/MaxColor
  EndIf
  
  V = MaxColor
  
EndProcedure

Procedure.l HSV_To_RGB()
  
  ColorRed.d
  ColorGreen.d
  ColorBlue.d
  
  If S = 0
    ColorRed = V
    ColorGreen = V
    ColorBlue = V
  Else
    
    hi.d = H/60
    l = Round(hi, #PB_Round_Down)
    f.d = hi-l
    p.d = V * (1-S)
    q.d = V * (1-S*f)
    t.d = V * (1-S*(1-f))
    
    If l = 1
      ColorRed = q
      ColorGreen = V
      ColorBlue = p
    ElseIf l = 2
      ColorRed = p
      ColorGreen = V
      ColorBlue = t
    ElseIf l = 3
      ColorRed = p
      ColorGreen = q
      ColorBlue = V
    ElseIf l = 4
      ColorRed = t
      ColorGreen = p
      ColorBlue = V
    ElseIf l = 5
      ColorRed = V
      ColorGreen = p
      ColorBlue = q
    Else
      ColorRed = V
      ColorGreen = t
      ColorBlue = p
    EndIf
  EndIf
  
  ProcedureReturn RGB(Colorblue * 255,ColorGreen * 255,Colorred * 255)
EndProcedure

Procedure ChangeColor(Grad)
  
  StartTime = ElapsedMilliseconds()  
  
  If IsImage(1) = 0
    
    Global MaxHeight,MaxWidth
    
    LoadImage(1,"media\CarTexture.bmp")
    LoadImage(3,"media\TailLight.png")
    MaxHeight = ImageHeight(1)
    MaxWidth = ImageWidth(1)
    CreateSprite(2,MaxWidth,MaxHeight)
    
    Global Dim Color(MaxWidth,MaxHeight)

    MaxHeight-1
    MaxWidth-1
    
    StartDrawing(ImageOutput(1))
    
    For i = 0 To MaxHeight
      
      For j = 0 To MaxWidth
        
        Color(j, i) = Point(j, i)
        
      Next j
      
    Next
    StopDrawing()
    
  EndIf
  
  i = 0
  j = 0
  
  StartDrawing(SpriteOutput(2))
  
      Buffer      = DrawingBuffer()             ; Get the start address of the screen buffer
      Pitch       = DrawingBufferPitch()        ; Get the length (in byte) took by one horizontal line
  
  For i = 0 To MaxHeight

    For j = 0 To MaxWidth

      RGB_To_HSV(Red(Color(j,i)),Green(Color(j,i)),Blue(Color(j,i)))
      
      H + Grad
      
      If H < 0
        H + 360
      ElseIf H > 360
        H - 360
      EndIf 
      
      *Line.Pixel = Buffer+(Pitch*i)+(j*4) 
      *Line\Pixel = HSV_To_RGB()
      
    Next j
    
  Next  
  
  DrawAlphaImage(ImageID(3), 0, 0)
  
  StopDrawing()  
  
  SaveSprite(2,"media\NewTexture.bmp",#PB_ImagePlugin_BMP)
  
  MessageRequester("Time",Str(ElapsedMilliseconds()-StartTime))
EndProcedure
PB: 5.xx LTS x86/x64 | WIN: 10 Pro x64, Linux Mint x64
Benutzeravatar
Thorium
Beiträge: 1722
Registriert: 12.06.2005 11:15
Wohnort: Germany
Kontaktdaten:

Re: rgb zu hsv und zurück beschleunigen?

Beitrag von Thorium »

Die Berechnung der Pixelposition ist zu aufwendig.
Wenn ich heut abend nachhause komme schreib ich dir ne optimale Schleife für DrawingBuffer.
Die Schleife mit Point kanns du dadurch auch ersetzen.

Wie wichtig ist den die Geschwindigkeit dabei? Das ganze würde sich wunderbar parallelisieren lassen. Mit reinem PB könntest du die Arbeit au mehrere Threads aufteilen um alle Cores zu nutzen. Ich würde dafür jedem Thread X Zeilen des Bildes zuweisen.

Hier würde sich auch SSE anbieten aber dafür muss dann Assembler rann.
Zu mir kommen behinderte Delphine um mit mir zu schwimmen.

Wir fordern mehr Aufmerksamkeit für umfallende Reissäcke! Bild
Benutzeravatar
The_Dark_Zim-.-
Beiträge: 372
Registriert: 18.03.2008 16:53

Re: rgb zu hsv und zurück beschleunigen?

Beitrag von The_Dark_Zim-.- »

Naja das soll für ein spiel sein, was ich entwickeln will. Da will ich das der Benutzer sich die Farbe seines Autos auswählen kann. Dafür will ich dann einfach die Texture ändern und nicht tausende Texturen benutzen.
PB: 5.xx LTS x86/x64 | WIN: 10 Pro x64, Linux Mint x64
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 6996
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: rgb zu hsv und zurück beschleunigen?

Beitrag von STARGÅTE »

Dann kannst du doch die Texturefarbe direkt ändern:
Sprite3DColor()

Das erspart das Umrechnen und außerdem den zusätzliche Speicher für die geänderten Texturen.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Antworten