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
Crop a PNG image to its minimum size
提问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
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):
示例输入(如果您想尝试,请下载链接):
Output:
输出: