使用python/PIL自动裁剪图像

dim*_*mka 14 python image crop image-processing python-imaging-library

任何人都可以帮我弄清楚我的图像自动裁剪脚本中发生了什么?我有一个带有大透明区域/空间的png图像.我希望能够自动裁剪出那个空间并留下必需品.原始图像有一个方形的画布,最好是矩形,只包含分子.

这是原始图片: 原始图像

做一些谷歌搜索我遇到了报告工作的PIL/python代码,但是在我手中,运行下面的代码过度裁剪图像.

import Image
import sys

image=Image.open('L_2d.png')
image.load()

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

imageComponents = image.split()

rgbImage = Image.new("RGB", imageSize, (0,0,0))
rgbImage.paste(image, mask=imageComponents[3])
croppedBox = rgbImage.getbbox()
print imageBox
print croppedBox
if imageBox != croppedBox:
    cropped=image.crop(croppedBox)
    print 'L_2d.png:', "Size:", imageSize, "New Size:",croppedBox
    cropped.save('L_2d_cropped.png')
Run Code Online (Sandbox Code Playgroud)

输出是这样的:脚本的输出

任何更熟悉图像处理/ PLI的人都可以帮我解决这个问题吗?

sne*_*awo 29

对我来说它的作用如下:

import Image

image=Image.open('L_2d.png')

imageBox = image.getbbox()
cropped=image.crop(imageBox)
cropped.save('L_2d_cropped.png')
Run Code Online (Sandbox Code Playgroud)

当您搜索边界时mask=imageComponents[3],仅搜索蓝色通道.

  • 仅供参考,谁想知道:`pip install枕头` (3认同)
  • 不过,赞成票,numpy-find-all-empty-cols-rows 方式更有趣。 (2认同)
  • 如果这不起作用,可能是因为图像的“空白”区域是不透明的白色 (255) 而不是透明的 (0)。 (2认同)
  • 安装“pillow”后使用“from PIL import Image”。 (2认同)

Tho*_*anz 19

您可以使用numpy,将图像转换为数组,查找所有非空列和行,然后根据这些创建图像:

import Image
import numpy as np

image=Image.open('L_2d.png')
image.load()

image_data = np.asarray(image)
image_data_bw = image_data.max(axis=2)
non_empty_columns = np.where(image_data_bw.max(axis=0)>0)[0]
non_empty_rows = np.where(image_data_bw.max(axis=1)>0)[0]
cropBox = (min(non_empty_rows), max(non_empty_rows), min(non_empty_columns), max(non_empty_columns))

image_data_new = image_data[cropBox[0]:cropBox[1]+1, cropBox[2]:cropBox[3]+1 , :]

new_image = Image.fromarray(image_data_new)
new_image.save('L_2d_cropped.png')
Run Code Online (Sandbox Code Playgroud)

结果看起来像 裁剪图像

如果有什么不清楚,请问.

  • `(...)cropBox [2]:cropBox [3] +1,:]`< - +1这个笑脸:)我是Python的新手......:P (5认同)
  • 如果将“Image”导入为“from PIL import Image”(已为 Python3 安装了 [`PILLOW`](https://python-pillow.org/)),则此方法适用于 Python3。 (2认同)

neo*_*hur 10

我测试了本文中回答的大多数答案,但是最终还是自己回答了。我使用了蟒蛇python3。

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)
    #Bounding box given as a 4-tuple defining the left, upper, right, and lower pixel coordinates.
    #If the image is completely empty, this method returns None.
    bbox = diff.getbbox()
    if bbox:
        return im.crop(bbox)

if __name__ == "__main__":
    bg = Image.open("test.jpg") # The image to be cropped
    new_im = trim(bg)
    new_im.show()
Run Code Online (Sandbox Code Playgroud)

  • 此代码具有适用于任何颜色和 alpha 的巨大优势。 (2认同)

jcu*_*itt 5

这是使用pyvips的另一个版本。

import sys
import pyvips

image = pyvips.Image.new_from_file(sys.argv[1])
left, top, width, height = image.find_trim(threshold=2, background=[255, 255, 255])
image = image.crop(left, top, width, height)
image.write_to_file(sys.argv[2])
Run Code Online (Sandbox Code Playgroud)

pyvips 修剪器对摄影图像很有用。它执行中值滤波器,减去背景,找到超过阈值的像素,并删除该集合之外的第一行和最后一行。中位数和阈值意味着它不会被 JPEG 压缩之类的东西抛弃,其中噪声或不可见的压缩伪影可能会混淆其他修剪器。

如果您不提供background参数,它将使用 (0, 0) 处的像素。threshold默认为 10,这对于 JPEG 来说是正确的。

这是在8k x 8k 像素的 NASA 地球图像上运行的

$ time ./trim.py /data/john/pics/city_lights_asia_night_8k.jpg x.jpg
real    0m1.868s
user    0m13.204s
sys     0m0.280s
peak memory: 100mb
Run Code Online (Sandbox Code Playgroud)

前:

收割前晚上的地球

后:

收获后的地球

有一篇博客文章,这里有更多讨论