python 将 PNG 图像裁剪为最小尺寸

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1905421/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 23:18:36  来源:igfitidea点击:

Crop a PNG image to its minimum size

pythonimagepng

提问by Hyman

How to cut off the blank border area of a PNG image and shrink it to its minimum size using Python?

如何使用Python切断PNG图像的空白边框区域并将其缩小到最小尺寸?

回答by YOU

PIL's getbboxis working for me

PILgetbbox对我有用

im.getbbox() => 4-tuple or None

Calculates the bounding box of the non-zero regions in the image. The bounding box is returned as a 4-tuple defining the left, upper, right, and lower pixel coordinate. If the image is completely empty, this method returns None.

im.getbbox() => 4 元组或无

计算图像中非零区域的边界框。边界框作为定义左、上、右和下像素坐标的 4 元组返回。如果图像完全为空,则此方法返回 None。

Code Sample that I tried, I have tested with bmp, but it should work for png too.

我试过的代码示例,我已经用 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")

回答by ícaro Magalh?es

I had the same problem today. Here is my solution to crop the transparent borders. Just throw this script in your folder with your batch .png files:

我今天遇到了同样的问题。这是我裁剪透明边框的解决方案。只需将此脚本与批处理 .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)

回答by noj

https://gist.github.com/3141140

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)

回答by Frank Krueger

You can use PILto find rows and cols of your image that are made up purely of your border color.

您可以使用PIL查找完全由边框颜色组成的图像行和列。

Using this information, you can easily determine the extents of the inlaid image.

使用此信息,您可以轻松确定镶嵌图像的范围。

PIL again will then allow you to crop the image to remove the border.

PIL 将再次允许您裁剪图像以去除边框。

回答by AaronJPung

I think it's necessary to supplement @Frank Krueger's answer. He makes a good point, but it doesn't include how to properly crop extra border color out of an image. I found that here. Specifically, I found this useful:

我认为有必要补充@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()

回答by Basj

Here is ready-to-use solution:

这是现成的解决方案:

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

Example input (download linkif you want to try):

示例输入(如果您想尝试,请下载链接):

enter image description here

在此处输入图片说明

Output:

输出:

enter image description here

在此处输入图片说明