Skript für Gimp

Hier werden alle anderen GUI-Toolkits sowie Spezial-Toolkits wie Spiele-Engines behandelt.
Antworten
gahleitner
User
Beiträge: 35
Registriert: Montag 1. Mai 2017, 09:57

Hallo, zusammen!

Ich habe mir was für Gimp (großteils mit Hilfe des Prozedurenbrowsers) programmiert: Es soll ein Bild zerlegen (Farbe-zerlegen-HSV), dann die Ebene "Wert" unscharf maskieren und dann wieder zusammenfügen. Leider bekomme ich es nicht in Gang. Konnte auch im Internet diesbezüglich keine brauchbaren Info finden. Kann mir jemand helfen. Hier der Code:

Code: Alles auswählen

#!/usr/bin/env python

from gimpfu import *
 
def sharpen(img,layer):
    img=gimp.Image() #3264mal2448
    pdb.plug_in_decompose(0,img,layers,"HSV",3) #Zerlegen
    img.set_active_layer(img,"Value")
    pdb.plug_in_unsharp_mask(1,img,layer,2,9,0)
    pdb.plug_in_compose(0,"Hue","Saturation","Value","HSV") # Zusammensetzen      
	
register(
    "",#python_fu_test_hello_world",
    "",#Hello world",
    "",#Display a 'hello world' message",
    "JFM",
    "",#Open source (BSD 3-clause license)",
    "2013",
    "<Image>/Colors/Auto/Scharfmacher",
    "*",
    [],
    [],
    sharpen)
    
main()
Melewo
User
Beiträge: 320
Registriert: Mittwoch 3. Mai 2017, 16:30

Einzelne Prozeduren könntest Du einfacher Schritt für Schritt in der Python-Fu-Console testen.

Wenn ich da einen Test mache, erhalte ich bei plug_in_unsharp_mask eine Fehlermeldung wegen des ersten Parameters. Der wird zwar im Prozeduren-Browser so mit aufgeführt,

[codebox=text file=Unbenannt.txt]INT32 The run mode { RUN-INTERACTIVE (0), RUN-NONINTERACTIVE (1) }[/code]
doch das könnte sich auf Scheme-Scripts beziehen, da es sich um ein anderes Plugin handelt. Wenn ich den weglasse und die gewohnte Reihenfolge für Python-Plugins benutze, funktioniert das auch bei mir, liefert aber alles andere als eine Unschärfe, eher eine extreme Schärfe mit einer Reduzierung der Farben, in Abhängigkeit von den restlichen Parametern. Doch es funktioniert zumindest mit Konsole:

[codebox=text file=Unbenannt.txt]>>> image = gimp.image_list()[0]
>>> ebene = image.layers[0]
>>> pdb.plug_in_unsharp_mask(image, ebene, 2, 9, 0) [/code]
Und wenn ich so wie in Deinem Beispiel gimp.Image() leer aufrufe, dann erhalte ich dieses Ergebnis:

[codebox=pycon file=Unbenannt.txt]
>>> img=gimp.Image()
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: Required argument 'width' (pos 1) not found[/code]
Melewo
User
Beiträge: 320
Registriert: Mittwoch 3. Mai 2017, 16:30

Also, habe noch einmal gesucht, "plug_in_unsharp_mask" ist seit Gimp 1.2 oder früher unter folgenden Menüpunkt erreichbar und dort kannst Du die Einstellungen testen:

Code: Alles auswählen

<Image>/Filters/Enhance/Unsharp Mask...

# Quelle: "http://oldhome.schmorp.de/marc/pdb/plug_in_unsharp_mask.html"

# Menüpfad auf Deutsch:
<Image>/Filter/Verbessern/Unscharf maskieren
Die Schreibweise erfolgte in bei github.com gefundenen Plugins ohne Angabe des ersten Parameters:

Code: Alles auswählen

pdb.plug_in_unsharp_mask(image, drawable, ...)
Ebenfalls im nachfolgenden Tutorial:

Code: Alles auswählen

workimg = pdb.gimp_image_duplicate(image)
# ...
# ...
pdb.plug_in_unsharp_mask(workimg, drawable, 0.1, 0.5, 25)
http://www.photomappe.de/gimp/python-bildskalierung/

Nur einen Hinweis, warum im Prozeduren-Browser ein erster Parameter mit 0 oder 1 oder Konstanten erwähnt wird, habe ich nicht gefunden. Das könnte sich aber bei Python-Plugins halt anders verhalten als bei Scheme-Scripts und irgendwie damit zusammenhängen.
gahleitner
User
Beiträge: 35
Registriert: Montag 1. Mai 2017, 09:57

Hallo!
Vielen Dank. Es soll auch eine Schärfe erzeugen - mit den Einstellungen muss ich noch ein bisschen probieren.

Ein anderes Problem: Mit decompose:

Code: Alles auswählen

>>> pdb.plug_in_decompose(image,ebene,"HSV",2)
Traceback (most recent call last):
  File "<input>", line 1, in <module>
RuntimeError: calling error
Mir sagt die Meldung nichts. Wie es aussieht, liegt es am letzten Parameter (layers-mode - es wird ein Integer verlangt). Woher weiß ich, welche Zahl ich da eingeben muss.
Das Plugin soll folgendes machen: Es soll das Bild über Farben-Komponenten-Zerlegen in Ebenen zerlegen. Es soll HSV und "in Ebenen zerlegen" ausgewählt sein -Ok. Ebene "Wert" mit vorgegebenen Werten unscharf maskieren. Dann die Ebenen zusammensetzen (mit Farben-Komponenten-zusammensetzen-HSV).
gahleitner
User
Beiträge: 35
Registriert: Montag 1. Mai 2017, 09:57

Hallo!
Bei compose gibt es auch ein Problem:
pdb.plug_in_compose("Hue","Saturation","Value","HSV")
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: wrong number of parameters

Hab es auch mit drawable_compose versucht - mit folgenden Fehlermeldungen:
>>> pdb.plug_in_drawable_compose(image,"Hue","Saturation","Value","HSV")
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: wrong number of parameters
>>> pdb.plug_in_drawable_compose(image,"Hue","Saturation","Value",None,"HSV")
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: wrong parameter type
>>> pdb.plug_in_drawable_compose(image,"Hue","Saturation","Value","None","HSV")
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: wrong parameter type

So wie es aussieht, werden 4Ebenen verlangt. Beim Zerlegen mit HSV sind es aber nur 3. Was kann ich da machen?
Melewo
User
Beiträge: 320
Registriert: Mittwoch 3. Mai 2017, 16:30

gahleitner hat geschrieben:So wie es aussieht, werden 4Ebenen verlangt. Beim Zerlegen mit HSV sind es aber nur 3. Was kann ich da machen?
Meinst Du Farbkanäle oder Ebenen?
Ebenen kannst Du so viele erzeugen, wie Du möchtest.
Die Anzahl der Farbkanäle kann hingegen nur dem verwendeten Farbmodell oder Farbraum entsprechen.

Hier ist ein fertiges Script zum Testen.

https://gist.github.com/JacksonBates/59 ... 6657578854
gahleitner
User
Beiträge: 35
Registriert: Montag 1. Mai 2017, 09:57

Hallo!

Wenn man ein Bild zerlegt(egal ob mit RGB,LAB,HSV,...), entstehen immer drei Kanäle, werden aber im Ebenenregister angezeigt. Wenn ich diese wieder zusammenfüge, entsteht dann ein geschärftes Bild. Ich möchte ja nur Ebene "Wert" schärfen. Das mit unscharf maskieren funktioniert ja schon - ich möchte es aber nur auf einen "Kanal" anwenden.
Würde mich freuen, wenn du mir helfen würdest.

Gruss
Gerhard
Melewo
User
Beiträge: 320
Registriert: Mittwoch 3. Mai 2017, 16:30

Da müsste ich mich ja auch erst einmal einarbeiten.

[codebox=pycon file=Unbenannt.txt]>>> image = gimp.image_list()[0]
>>> ebene = image.layers[0]
>>> pdb.plug_in_decompose(1, image, ebene, RGB, 3)
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: wrong number of parameters[/code]

[codebox=pycon file=Unbenannt.txt]>>> image = gimp.image_list()[0]
>>> ebene = image.layers[0]
>>> pdb.plug_in_decompose(image, ebene, RGB, 3)
Traceback (most recent call last):
File "<input>", line 1, in <module>
RuntimeError: calling error[/code]

So schon einmal nicht, doch wenn ich mir das nächste Listing ansehe, da wird es doch vorgemacht, wie man ein Image richtig mit "pdb.plug_in_decompose" zerlegen und wieder zusammenfügen kann.

Code: Alles auswählen

lab_images=pdb.plug_in_decompose(img, pseudolab_layer, "RGB", 0)
l_work_layer=pdb.gimp_image_get_active_layer(lab_images[0])
view_image=pdb.plug_in_compose(lab_images[0], l_work_layer, lab_images[1], lab_images[2], lab_images[3], "LAB")
https://github.com/sergeG/gimp-plug-ins ... ecolors.py
Melewo
User
Beiträge: 320
Registriert: Mittwoch 3. Mai 2017, 16:30

Wenn Du weiter testen möchtest, so sei erwähnt, zuerst das im Fenster geöffnete Image und dessen Ebene auswählen, wobei die Zählung bei 0 beginnt beginnt. Beide Zeilen werden nur in der Konsole benötigt, in einem Plugin haben die nichts verloren. Die übliche Bezeichnung ist nicht ebene, sondern drawable für Auswahl und layer für Ebene, nur konnte ich anfänglich nichts mit der ersten Bezeichnung anfangen.

[codebox=pycon file=Unbenannt.txt]image = gimp.image_list()[0]
ebene = image.layers[0][/code]
Dann hat gimp.Image() in Deinem Plugin nichts verloren, eigentlich nie, wenn Du einen Filter auf ein vorhandenes Image anwenden möchtest.
Wenn Du hingegen ein neues erzeugen möchtest, ohne ein bestehendes zu öffnen, musst Du zwingend die erforderlichen Werte übergeben.

[codebox=pycon file=Unbenannt.txt]gimp.Image(width als int, height als int, Type als Konstante oder int) [/code]
Die Prozedur mit plug_in_decompose() und bisher gesehene Beispiele verstehe ich immer noch nicht richtig.
Bei "oldhome.schmorp.de/marc/pdb/plug_in_decompose.html" sieht es so aus:

[codebox=pycon file=Unbenannt.txt]
(new_image,new_image,new_image,new_image) = plug_in_decompose (run_mode,image,drawable,decompose_type)[/code]
bei "developer.gimp.org" finde ich die nicht und der Prozedurenbrowser übergibt es bei Klick so an die Konsole, die damit richtig liegen sollte, obwohl der Browser es anders beschreibt:

[codebox=pycon file=Unbenannt.txt]new_image, new_image, new_image, new_image = pdb.plug_in_decompose(image, drawable, decompose_type, layers_mode)[/code]
Die Variablen "new_image" stehen somit wohl für einen Tupel [0] bis [3], falls ich mich nicht irren sollte, müsste man an einem funktionierenden Beispiel prüfen. In den gefundenen Beispielen sieht es ja auch danach aus. Irgendwann werde ich mich sicherlich noch damit auseinandersetzen, doch bislang gehe ich noch schrittweise vor. Manuell hatte ich es probiert, also über Menü Farben->Komponenten->zerlegen aufgerufen und ausgeführt und dann im Browser vom neuen Fenster aufgerufen:

[codebox=pycon file=Unbenannt.txt]image = gimp.image_list()[0]
ebene = image.layers[0]
pdb.plug_in_unsharp_mask(image, ebene, 0.5, 5.0, 0) [/code]
Dann auf "später" verschoben. Bis dahin nur Beispiele, wie Du ein Image ebenfalls schärfen kannst.

Als farbiges Image:

[codebox=pycon file=Unbenannt.txt]>>> # Diese Zeile nur in der Konsole verwenden
>>> image = gimp.image_list()[0]
>>> # Image duplizieren
>>> geschaerftes_image = pdb.gimp_image_duplicate(image)
>>> # Aktive Ebene
>>> ebene = pdb.gimp_image_get_active_drawable(geschaerftes_image)
>>> #Image schärfen
>>> pdb.plug_in_unsharp_mask(geschaerftes_image , ebene, 0.5, 5.0, 0)
>>> # anzeigen
>>> pdb.gimp_display_new(geschaerftes_image)[/code]
Als Graustufen-Image:

[codebox=pycon file=Unbenannt.txt]>>> # Diese Zeile nur in der Konsole verwenden
>>> image = gimp.image_list()[0]
>>> # Image duplizieren
>>> geschaerftes_image = pdb.gimp_image_duplicate(image)
>>> # Aktive Ebene
>>> ebene = pdb.gimp_image_get_active_drawable(geschaerftes_image)
>>> # Image in Graustufen
>>> pdb.gimp_desaturate_full(ebene, DESATURATE_LIGHTNESS)
>>> #Image schärfen
>>> pdb.plug_in_unsharp_mask(geschaerftes_image , ebene, 0.5, 5.0, 0)
>>> # anzeigen
>>> pdb.gimp_display_new(geschaerftes_image)[/code]
Melewo
User
Beiträge: 320
Registriert: Mittwoch 3. Mai 2017, 16:30

Nun dachte ich, ich wäre fertig aber unten mit den 4-mal delete, ich dachte es würde besser gehen. Bereinigt muss es werden, sonst ist nur ein Aufruf möglich und man muss für einen weiteren Aufruf Gimp erst neu starten.

Enthalten in temp_image bei Verwendung von "HSV":

[codebox=pycon file=Unbenannt.txt]>>> temp_image = pdb.plug_in_decompose(geklontes_image, ebene_imageklon, "HSV", 0)
>>> print "# Prüfen: {0}".format(type(temp_image))
# Prüfen: <type 'tuple'>
>>> print "# Ergebnis mit HSV: {0}".format(temp_image)
# Ergebnis mit HSV: (<gimp.Image 'Farbton'>, <gimp.Image 'Sättigung'>, <gimp.Image 'Wert'>, None)[/code]
Enthalten in temp_image bei Verwendung von "RGB":

[codebox=pycon file=Unbenannt.txt]>>> temp_image = pdb.plug_in_decompose(geklontes_image, ebene_imageklon, "RGB", 0)
>>> print "# Prüfen: {0}".format(type(temp_image))
# Prüfen: <type 'tuple'>
>>> print "# Ergebnis mit RGB: {0}".format(temp_image)
# Ergebnis mit RGB: (<gimp.Image 'Rot'>, <gimp.Image 'Grün'>, <gimp.Image 'Blau'>, None)[/code]
Abschließendes Aufräumen erster Versuch:

Code: Alles auswählen

>>> for temp in range(temp_image):
...     print temp
... 
Traceback (most recent call last):
  File "<input>", line 1, in <module>
TypeError: range() integer end argument expected, got tuple.
Abschließendes Aufräumen letzter Versuch. Keine Fehlermeldung beim ersten Aufruf, dafür beim zweiten um so mehr, weil nicht bereinigt. Nur mit del temp_image funktionierte es ebenfalls nicht.

[codebox=python file=Unbenannt.txt]for temp in range(len(temp_image)):
pdb.gimp_image_delete(temp_image[temp])[/code]
So funktioniert es, habe es nun erst einmal so belassen, soweit es fertig ist. Ist ja dann nur noch in eine Funktion übernehmen und die Registrierung.

Code: Alles auswählen

# Die erste Zeile nur in der Konsole verwenden.
image = gimp.image_list()[0]

# In die Gruppe der rückgängig-machbaren Prozeduren einreihen?
pdb.gimp_image_undo_group_start(image)
# Image duplizieren
geklontes_image = pdb.gimp_image_duplicate(image)
ebene_imageklon = geklontes_image.layers[0]
# Image zerlegen und in Tupel speichern
temp_image = pdb.plug_in_decompose(geklontes_image, ebene_imageklon, "HSV", 0)
# Aktive Ebene
arbeits_ebene = pdb.gimp_image_get_active_layer(temp_image[0])
# Arbeits-Ebene schärfen
pdb.plug_in_unsharp_mask(geklontes_image, arbeits_ebene, 0.5, 5.0, 0) 
# Image wieder vereinen, die Reihenfolge ist vorgegeben.
neues_image = pdb.plug_in_compose(
                     temp_image[0], 
                     arbeits_ebene, 
                     temp_image[1], 
                     temp_image[2], 
                     temp_image[3], 
                     "HSV")     
# Ausgabe
pdb.gimp_display_new(neues_image)                     
# Einreihen Ende an dieser Stelle?
pdb.gimp_image_undo_group_end(image)   

# Tupel zwinged aufräumen, ansonsten ist 
# nur ein Aufruf pro Gimp-Sitzung möglich.
pdb.gimp_image_delete(temp_image[0])
pdb.gimp_image_delete(temp_image[1])
pdb.gimp_image_delete(temp_image[2])
pdb.gimp_image_delete(temp_image[3])
Melewo
User
Beiträge: 320
Registriert: Mittwoch 3. Mai 2017, 16:30

Der Fehler mit der For-Schleife lag einfach daran, dass die Python-Fu-Console das Ende der Schleife nicht erkannt hat und bei einem nachfolgenden Test-Kommentar den genauso weit einrückte, wie den Schleifenrumpf. Zum Glück nur die Konsole.

Dann ärgerte noch das None aus temp_image, weil delete nun auf eine nicht mehr existierende Image-ID angewendet wurde:

Code: Alles auswählen

(<gimp.Image 'Farbton'>, <gimp.Image 'Sättigung'>, <gimp.Image 'Wert'>, None)
(<gimp.Image 'Rot'>, <gimp.Image 'Grün'>, <gimp.Image 'Blau'>, None)
Nun funktioniert das Plugin:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from gimpfu import pdb, register, main, PF_IMAGE, PF_DRAWABLE

# Nur für Fehler bei der Registrierung.
# Danach diese 3 Zeilen auskommentieren oder entfernen.
import sys
import os
sys.stderr = open(os.path.normcase("C:/.../gimpfehler.txt"), "a")

def erhoehe_schaerfe(image, ebene):
    # In die Gruppe der rückgängig-machbaren Prozeduren einreihen?
    pdb.gimp_image_undo_group_start(image)

    # Image duplizieren
    geklontes_image = pdb.gimp_image_duplicate(image)
    ebene_imageklon = geklontes_image.layers[0]
    # Image zerlegen und in Tupel speichern
    temp_image = pdb.plug_in_decompose(geklontes_image, ebene_imageklon, "HSV", 0)
    # Aktive Ebene
    arbeits_ebene = pdb.gimp_image_get_active_layer(temp_image[0])
    # Arbeits-Ebene schärfen
    pdb.plug_in_unsharp_mask(geklontes_image, arbeits_ebene, 0.5, 5.0, 0)
    # Image wieder vereinen, die Reihenfolge ist vorgegeben.
    neues_image = pdb.plug_in_compose(
                         temp_image[0],
                         arbeits_ebene,
                         temp_image[1],
                         temp_image[2],
                         temp_image[3],
                         "HSV")
    # Ausgabe
    pdb.gimp_display_new(neues_image)

    # Einreihen Ende an dieser Stelle?
    pdb.gimp_image_undo_group_end(image)

    # Tupel zwinged aufräumen, ansonsten ist nur ein Aufruf
    # pro Gimp-Sitzung möglich.
    for i in range(len(temp_image)):
        if temp_image[i] is not None:
            pdb.gimp_image_delete(temp_image[i])

register(
    "erhoehe_schaerfe",
    "Schärfe erhöhen",
    "Schärfe von Images erhöhen",
    "Mele Melewo",
    "MIT-Lizenz",
    "2017",
    "Filter Schärfe",
    "*",
    [
        (PF_IMAGE,    "image", "Input Image", None),
        (PF_DRAWABLE, "ebene", "Input Ebene", None)
    ],
    [],
    erhoehe_schaerfe,
    menu="<Image>/Filters/Eigene")

main()
Melewo
User
Beiträge: 320
Registriert: Mittwoch 3. Mai 2017, 16:30

Habe noch einige Varianten durchgespielt, die beiden Zeilen "gimp_image_duplicate" und "layers" vom Duplikat sind eigentlich über, weil ohnehin ein neues Image erstellt wird.

Weiterhin ergibt "gimp_image_undo_group_..." in diesem Zusammenhang eher wenig Sinn. Mit "gimp_image_undo_group_..." erscheint ein Eintrag unter Menü Bearbeiten->Rückgängig, ohne nicht. Doch ein neu erstelltes Image in einem neuen Fenster wird ja ohnehin nicht mehr rückgängig gemacht. Wichtig wird undo_group erst, wenn mehrere Prozeduren für ein Image folgen, die dann der Reihe nach rückgängig gemacht werden könnten. Schaden tun sie aber halt auch nicht, womit es so aussehen könnte:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from gimpfu import pdb, register, main, PF_IMAGE, PF_DRAWABLE

def erhoehe_schaerfe(image, ebene):
    pdb.gimp_image_undo_group_start(image)

    temp_image = pdb.plug_in_decompose(image, ebene, "HSV", 0)
    arbeits_ebene = pdb.gimp_image_get_active_layer(temp_image[0])
    pdb.plug_in_unsharp_mask(image, arbeits_ebene, 0.5, 5.0, 0)
    neues_image = pdb.plug_in_compose(
                         temp_image[0],
                         arbeits_ebene,
                         temp_image[1],
                         temp_image[2],
                         temp_image[3],
                         "HSV")

    pdb.gimp_image_undo_group_end(image)
    pdb.gimp_display_new(neues_image)

    for i in range(len(temp_image)):
        if temp_image[i] is not None:
            pdb.gimp_image_delete(temp_image[i])

register(
    "erhoehe_schaerfe",
    "Schärfe erhöhen",
    "Schärfe von Images erhöhen",
    "Mele Melewo",
    "MIT-Lizenz",
    "2017",
    "Filter Schärfe",
    "*",
    [
        (PF_IMAGE,    "image", "Input Image", None),
        (PF_DRAWABLE, "ebene", "Input Ebene", None)
    ],
    [],
    erhoehe_schaerfe,
    menu="<Image>/Filters/Eigene")

main()
Antworten