21 Stimmen

Beschneiden eines PNG-Bildes auf seine Mindestgröße

Wie schneidet man den leeren Randbereich eines PNG-Bildes ab und verkleinert es mit Python auf seine Mindestgröße?

46voto

YOU Punkte 113320

PIL 's getbbox funktioniert bei mir

im.getbbox() => 4-Tupel oder Keine

Berechnet die Bounding Box des Nicht-Null-Regionen im Bild. Die Bounding Box wird als 4-Tupel zurückgegeben zurückgegeben, das den linken, oberen, rechten und unteren Pixelkoordinate definiert. Wenn das Bild komplett leer ist, gibt diese Methode keine zurück.

Codebeispiel, das ich ausprobiert habe, ich habe mit bmp getestet, aber es sollte auch für png funktionieren.

import Image
im = Image.open("test.bmp")
im.size  # (364, 471)
im.getbbox()  # (64, 89, 278, 267)
im2 = im.crop(im.getbbox())
im2.size  # (214, 178)
im2.save("test2.bmp")

0 Stimmen

Es scheint, dass es bei PNG-Dateien (z. B. mit MSPaint erstellt) nicht funktioniert. Vielleicht wegen der Transparenz oder etwas anderem?

0 Stimmen

@YOU warum gibt im.getbbox() diese Zahlen für ein neu geöffnetes Bild zurück, anstatt (0, 0, 364, 471)? Warum sind die ersten beiden Zahlen nicht Nullen?

7voto

Basj Punkte 36025

Hier ist eine gebrauchsfertige Lösung:

import numpy as np
from PIL import Image

def bbox(im):
    a = np.array(im)[:,:,:3]  # keep RGB only
    m = np.any(a != [255, 255, 255], axis=2)
    coords = np.argwhere(m)
    y0, x0, y1, x1 = *np.min(coords, axis=0), *np.max(coords, axis=0)
    return (x0, y0, x1+1, y1+1)

im = Image.open('test.png')
print(bbox(im))  # (33, 12, 223, 80)
im2 = im.crop(bbox(im))
im2.save('test_cropped.png')

Beispieleingabe ( Download-Link wenn Sie es versuchen wollen):

enter image description here

Ausgabe:

enter image description here

5voto

Ich hatte heute das gleiche Problem. Hier ist meine Lösung, um die transparenten Ränder zu beschneiden. Legen Sie dieses Skript einfach in Ihren Ordner mit Ihren Batch-.png-Dateien:

from PIL import Image
import numpy as np
from os import listdir

def crop(png_image_name):
    pil_image = Image.open(png_image_name)
    np_array = np.array(pil_image)
    blank_px = [255, 255, 255, 0]
    mask = np_array != blank_px
    coords = np.argwhere(mask)
    x0, y0, z0 = coords.min(axis=0)
    x1, y1, z1 = coords.max(axis=0) + 1
    cropped_box = np_array[x0:x1, y0:y1, z0:z1]
    pil_image = Image.fromarray(cropped_box, 'RGBA')
    print(pil_image.width, pil_image.height)
    pil_image.save(png_image_name)
    print(png_image_name)

for f in listdir('.'):
    if f.endswith('.png'):
        crop(f)

0 Stimmen

Dieses Skript funktioniert nicht.

3voto

noj Punkte 139

https://gist.github.com/3141140

import Image
import sys
import glob

# Trim all png images with alpha in a folder
# Usage "python PNGAlphaTrim.py ../someFolder"

try:
    folderName = sys.argv[1]
except :
    print "Usage: python PNGPNGAlphaTrim.py ../someFolder"
    sys.exit(1)

filePaths = glob.glob(folderName + "/*.png") #search for all png images in the folder

for filePath in filePaths:
    image=Image.open(filePath)
    image.load()

    imageSize = image.size
    imageBox = image.getbbox()

    imageComponents = image.split()

    if len(imageComponents) < 4: continue #don't process images without alpha

    rgbImage = Image.new("RGB", imageSize, (0,0,0))
    rgbImage.paste(image, mask=imageComponents[3])
    croppedBox = rgbImage.getbbox()

    if imageBox != croppedBox:
        cropped=image.crop(croppedBox)
        print filePath, "Size:", imageSize, "New Size:",croppedBox
        cropped.save(filePath)

2voto

AaronJPung Punkte 895

Ich denke, es ist notwendig, die Antwort von @Frank Krueger zu ergänzen. Er macht einen guten Punkt, aber er sagt nicht, wie man zusätzliche Randfarbe richtig aus einem Bild herausschneidet. Das habe ich gefunden aquí . Konkret fand ich dies nützlich:

from PIL import Image, ImageChops

def trim(im):
    bg = Image.new(im.mode, im.size, im.getpixel((0,0)))
    diff = ImageChops.difference(im, bg)
    diff = ImageChops.add(diff, diff, 2.0, -100)
    bbox = diff.getbbox()
    if bbox:
        return im.crop(bbox)

im = Image.open("bord3.jpg")
im = trim(im)
im.show()

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X