Обрезать изображение PNG до минимального размера

Как обрезать пустую область границы изображения PNG и уменьшить ее до минимального размера с помощью Python?


person jack    schedule 15.12.2009    source источник
comment
Размер области границы статичен? В таком случае вы можете попробовать использовать привязки Python ImageMagick.   -  person Rich Schuler    schedule 15.12.2009
comment
размер пустой рамки не является фиксированным значением, он зависит от изображения.   -  person jack    schedule 15.12.2009


Ответы (6)


PIL getbbox работает для меня

im.getbbox () => 4-кортеж или Нет

Вычисляет ограничивающую рамку ненулевых областей изображения. Ограничивающая рамка возвращается как кортеж из четырех элементов, определяющий координату левого, верхнего, правого и нижнего пикселей. Если изображение полностью пусто, этот метод возвращает None.

Пример кода, который я пробовал, я тестировал с bmp, но он должен работать и с png.

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")
person YOU    schedule 15.12.2009
comment
Кажется, это не работает для файлов PNG (например, созданных с помощью MSPaint). Может из-за прозрачности или чего-то еще? - person Basj; 22.05.2020

Сегодня у меня была такая же проблема. Вот мое решение для обрезки прозрачных границ. Просто киньте этот скрипт в свою папку с вашими пакетными файлами .png:

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)
person Ícaro Magalhães    schedule 22.06.2017

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)
person noj    schedule 19.07.2012

Вот готовое решение:

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')

Пример ввода (ссылка для скачивания, если вы хотите попробовать):

введите описание изображения здесь

Вывод:

введите описание изображения здесь

person Basj    schedule 22.05.2020

Вы можете использовать PIL, чтобы найти строки и столбцы вашего изображения, состоящие исключительно из ваших цвет границы.

Используя эту информацию, вы можете легко определить размеры инкрустированного изображения.

PIL снова позволит вам обрезать изображение, чтобы удалить границу.

person Frank Krueger    schedule 15.12.2009

Я считаю необходимым дополнить ответ @Frank Krueger. Он хорошо замечает, но в нем не говорится о том, как правильно обрезать лишний цвет границы изображения. Я обнаружил, что здесь. В частности, я нашел это полезным:

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()
person AaronJPung    schedule 29.02.2016