Ich versuche zu tun, was ich ursprünglich dachte, wäre ziemlich einfach. Nämlich:Wiederholte Aufrufe von image.png.Decode() führt zu Fehlern, die nicht genügend Speicher haben
Für jede Datei in der Liste der Eingabedateien:
- die Datei mit png.Decode öffnen()
- scannen jedes Pixel in der Datei und Test, um zu sehen, ob es „grau ist ".
- Gibt den Prozentsatz der "grauen" Pixel im Bild zurück.
Dies ist die Funktion, die ich anrufen bin:
func greyLevel(fname string) (float64, string) {
f, err := os.Open(fname)
if err != nil {
return -1.0, "can't open file"
}
defer f.Close()
i, err := png.Decode(f)
if err != nil {
return -1.0, "unable to decode"
}
bounds := i.Bounds()
var lo uint32 = 122 // Low grey RGB value.
var hi uint32 = 134 // High grey RGB value.
var gpix float64 // Grey pixel count.
var opix float64 // Other (non-grey) pixel count.
var tpix float64 // Total pixels.
for x := bounds.Min.X; x < bounds.Max.X; x++ {
for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
r, g, b, _ := i.At(x, y).RGBA()
if ((r/255)-1 > lo && (r/255)-1 < hi) &&
((g/255)-1 > lo && (g/255)-1 < hi) &&
((b/255)-1 > lo && (b/255)-1 < hi) {
gpix++
} else {
opix++
}
tpix++
}
}
return (gpix/tpix) * 100, ""
}
func main() {
srcDir := flag.String("s", "", "Directory containing image files.")
threshold := flag.Float64("t", 65.0, "Threshold (in percent) of grey pixels.")
flag.Parse()
dirlist, direrr := ioutil.ReadDir(*srcDir)
if direrr != nil {
log.Fatalf("Error reading %s: %s\n", *srcDir, direrr)
}
for f := range dirlist {
src := path.Join(*srcDir, dirlist[f].Name())
level, msg := greyLevel(src)
if msg != "" {
log.Printf("error processing %s: %s\n", src, msg)
continue
}
if level >= *threshold {
log.Printf("%s is grey (%2.2f%%)\n", src, level)
} else {
log.Printf("%s is not grey (%2.2f%%)\n", src, level)
}
}
}
Die Dateien relativ klein sind (960x720, 8-bit RGB)
I ioutil.ReadDir nenne(), um eine Liste zu erzeugen, von Dateien, Schleifen über die Scheibe und Aufruf von GreyLevel().
Nach etwa 155 Dateien (aus einer Liste von> 4000) das Skript panics mit:
runtime: memory allocated by OS not in usable range
runtime: out of memory: cannot allocate 2818048-byte block (534708224 in use)
throw: out of memory
ich meine, es ist etwas einfach mir fehlt. Ich dachte, Go würde den Speicher freigeben, der in greyLevels() zugewiesen wurde, aber ich denke nicht?
Follow up:
Nach dem Einlegen runtime.GC() nach jedem Aufruf an Graustufen, gleicht die Speichernutzung. Letzte Nacht habe ich ungefähr 800 Bilder gemacht und dann aufgehört. Heute lasse ich es über den gesamten Eingabesatz laufen, ca. 6800 Bilder.
Nach 1500 Bilder sieht oben wie folgt aus:
top - 10:30:11 up 41 days, 11:47, 2 users, load average: 1.46, 1.25, 0.88
Tasks: 135 total, 2 running, 131 sleeping, 1 stopped, 1 zombie
Cpu(s): 49.8%us, 5.1%sy, 0.2%ni, 29.6%id, 15.0%wa, 0.0%hi, 0.3%si, 0.0%st
Mem: 3090304k total, 2921108k used, 169196k free, 2840k buffers
Swap: 3135484k total, 31500k used, 3103984k free, 640676k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
28474 mtw 20 0 2311m 1.8g 412 R 99 60.5 16:48.52 8.out
Und blieb stabil nach dem anderen 5000 die Bearbeitung von Bildern.
Fügen Sie Go-Version, OS-Plattform und CPU-Architekturinformationen hinzu. Auch der vollständige Code, der das Problem reproduziert, wäre nützlich. – zzzz
@jnml Sie können von "nicht genügend Arbeitsspeicher ... (534708224 in Verwendung)" auf CPU-Architektur schließen. –
@Atom: Intel oder ARM? ;-) – zzzz