Listennamen ändern

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Smuun
User
Beiträge: 16
Registriert: Montag 12. Januar 2015, 13:43

Hallo liebes Forum.

Ich habe folgendes Problem. Ich möchte aus einem Ordner in dem mehrere Bilder enthalten sind alle in die unten dargestellte Funktion übernhemen, und dann den Namen ändern.
Ich kann aber mit dem geschriebenen Code die NAmen nicht ändern und es wird nach der Erstellung des ersten Plots, ohne abspeichern abgebrochen.

Die Fehlermeldung:

TypeError: can only concatenate list (not "str") to list

Jedoch hab ich grade keine Ahnung wie ich dieses Problem lösen kann.

Hier mein Code:

Code: Alles auswählen

import sys
sys.path.append('/usr/lib/python2.7/dist-packages/')
import cv2
from matplotlib import pyplot as plt
import glob
import multiprocessing as multi

def create_histogramm_plots(images):
    #reading the image 
    for i in images:    
        img = cv2.imread(i,0)
    
    #create the plots with subplots; first the histogramm on the left
        plt.subplot(1,2,1)
        plt.hist(img.ravel(),256,[0,256])

    #the image on the right
        plt.subplot(1,2,2)
        plt.imshow(img,cmap=plt.cm.binary )
    #image plot without axis    
        plt.axis('off')
    #save the plot
        outname = images[:-4]+ "_hist.png" 
        plt.savefig(outname)
    
    
image_list =[]

for png_file in glob.glob('/home/simon/Daten/test_10nm_10us/*.png'):
    print png_file
    image_list.append(png_file)


pool=multi.Pool(processes=1)
    
pool.map(create_histogramm_plots(image_list))
Vielen Dank schonmal für Eure Tips

Grüße
Simon
BlackJack

@Smuun: Es wäre hilfreich den gesamten Traceback zu zeigen damit man nicht raten muss *wo* diese Ausnahem auftritt. Ich vermute jetzt einfach mal in Zeile 23. Dann erklär doch mal was die Zeile macht und was `images` für einen Wert und Typ hat und was Du als Ergebnis von dieser Operation erwartest.
Smuun
User
Beiträge: 16
Registriert: Montag 12. Januar 2015, 13:43

Hier der vollständige Traceback:

Traceback (most recent call last):

File "<ipython-input-19-c7171997859c>", line 40, in <module>
pool.map(create_histogramm_plots(image_list))

File "<ipython-input-19-c7171997859c>", line 25, in create_histogramm_plots
outname = images[:-4]+ "_hist.png"

TypeError: can only concatenate list (not "str") to list


Die Ausgabe soll der neue Datiname sein unter dem gespeichert werden soll.
Wenn in der Liste eingelesen ist: bild.png
Will ich das zu "bild_hist.png" ändern.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Ich habe das Gefuehl du willst `img` und nicht `images` in der betreffenden Zeile.
BlackJack

Dicht vorbei ist auch daneben. An der Stelle ist vielleicht auch noch mal wichtig zu erwähnen das es sehr nützlich ist wenn man *passende* Namen verwenden statt kryptischer Abkürzungen oder subtil falscher Bezeichner. Also beispielsweise `image` statt `img` und `image_filename` statt `i` und `image_filenames` statt `images`. Dann kommt man nicht so leicht durcheinander. :-)

@Smuun: Mir ist schon klar was Du willst, aber Dir ist nicht klar was Du da machst beziehunsweise welchen Wert und Typ Du da vor Dir hast.

@Edit: Ich würde ja mit `os.path.splitext()` arbeiten statt mit so einer magischen -4 die nur funktioniert wenn die Namen tatsächlich alle eine dreibuchstabige Erweiterung haben.
Smuun
User
Beiträge: 16
Registriert: Montag 12. Januar 2015, 13:43

Den Namen von img möchte ich ändern bevor gespeichert wird.
BlackJack

@Smuun: `img` hat im Grunde keinen (Datei)Namen, das ist ein Bildobjekt. Wie das mal zustande gekommen ist, also zum Beispiel aus einer Datei mit einem Namen, weiss dieses Objekt nicht.

Wie gesagt: Mach Dir mal klar was Du in der Zeile *tatsächlich* machst, und warum das nicht funktionieren kann. Dann kommst Du vielleicht auch darauf was Du stattdessen machen musst.
Smuun
User
Beiträge: 16
Registriert: Montag 12. Januar 2015, 13:43

Hey BlackJack


Ich danke dir für deinen Hinweis mit den Namen. Ich bin da nachlässig geworden. HAb die Namen geändert und den Fehler gefunden!

Hab jetzt wieder gelernt, immer volle und sinnvolle Namen zu verwenden!

Grüße Simon
Smuun
User
Beiträge: 16
Registriert: Montag 12. Januar 2015, 13:43

Eine Frage hätte ich noch. Mein Code macht jetzt wass er soll, nur am Ende kommt eine Fehlermeldung.

Traceback (most recent call last):

File "<ipython-input-27-4f6e0ab0516b>", line 1, in <module>
pool.map(create_histogramm_plots(image_list))

TypeError: map() takes at least 3 arguments (2 given)

Der Code sieht so aus

Code: Alles auswählen

import sys
sys.path.append('/usr/lib/python2.7/dist-packages/')
import cv2
from matplotlib import pyplot as plt
import glob
import multiprocessing as multi



def create_histogramm_plots(images):
    #reading the image 
    for image_file in images:    
        image = cv2.imread(image_file,0)
    
    #create the plots with subplots; first the histogramm on the left
        plt.subplot(1,2,1)
        plt.hist(image.ravel(),256,[0,256])

    #the image on the right
        plt.subplot(1,2,2)
        plt.imshow(image,cmap=plt.cm.binary )
    #image plot without axis    
        plt.axis('off')
    #save the plot
        outname = image_file[:-4]+ "_hist.png" 
        plt.savefig(outname)
    
    
image_list =[]

for png_file in glob.glob('/home/simon/Daten/test_10nm_10us/*.png'):
    print png_file
    image_list.append(png_file)


pool=multi.Pool(processes=1)
    
pool.map(create_histogramm_plots(image_list))
Also er führt alles fehlerfrei aus.
Würde nur gerne verstehen, warum die Fehlermeldung kommt.

Danke.

Grüße Simon
BlackJack

@Smuun: Der Code macht nicht was er soll, denn er soll ja wohl die Arbeit auf mehrere Prozesse verteilen und das machst Du so nicht, und fehlerfrei würde ich das auch nicht nennen wenn einem eine Ausnahme um die Ohren fliegt.

`Pool.map()` erwartet wie die Meldung sagt drei Argumente, bekommt aber nur zwei. Das erste ist das implizite `self`. Und das zweite ist der *Rückgabewert* von dem `create_histogramm_plots()`-Aufruf. Du rufst die Funktion auf statt sie zu übergeben, womit dann ihr Rückgabewert an `map()` übergeben wird. Und die Daten übergibst Du `map()` gar nicht, deswegen die Fehlermeldung. Der Aufruf müsste so aussehen ``pool.map(create_histogramm_plots, image_list)``. Allerdings ist es recht sinnfrei einen `multiprocessing.Pool` zu erstellen und den auf *einen* Prozessor zu beschränken. Warum machst Du denn so was?
Benutzeravatar
sparrow
User
Beiträge: 4144
Registriert: Freitag 17. April 2009, 10:28

Naja, genaugenommen führt er es ja nicht fehlefrei aus, sonst würde ja der Fehler nicht kommen ;)

multiprocessing.map() benötigt 3 Argumente, aber du übergibst nur 2. Das ist in Python etwas verwirrend, weil das erste übergebene Argument eine Referenz auf die Instanz der Klasse ist.
Also musst du 2 Argumente übergeben, übergibst aber nur 1. Daher die Fehlermeldung.

So wie du es aufrufst übergibst du der Funktion das Ergebnis des folgenden Aufrufs: create_histogramm_plots(image_list)
Du möchtest der Funktion aber eigentlich als ersten Parameter die Funktion und als zweiten Parameter das iterierbare Objkekt übergeben, mit dessen Elementen die Funktion arbeiten soll.

Das müsste also

Code: Alles auswählen

pool.map(create_histogramm_plots, image_list)
sein.
Antworten