【问题标题】:Background color when cropping image with PIL使用 PIL 裁剪图像时的背景颜色
【发布时间】:2018-05-25 11:10:06
【问题描述】:

PIL.crop 的好处是,如果我们想在图像尺寸之外进行裁剪,它只适用于:

from PIL import Image
img = Image.open("test.jpg")
img.crop((-10, -20, 1000, 500)).save("output.jpg")

问题:如何将添加区域的背景颜色改为白色(默认:黑色)?

注意:

【问题讨论】:

    标签: python image python-imaging-library pillow


    【解决方案1】:

    我认为一个函数调用是不可能的,因为相关的 C 函数似乎将目标图像内存区域归零(参见此处:https://github.com/python-pillow/Pillow/blob/master/src/libImaging/Crop.c#L47

    您提到对创建新图像并复制它不感兴趣,但我还是粘贴了这种解决方案以供参考:

    from PIL import Image
    img = Image.open("test.jpg")
    x1, y1, x2, y2 = -10, -20, 1000, 500  # cropping coordinates
    bg = Image.new('RGB', (x2 - x1, y2 - y1), (255, 255, 255))
    bg.paste(img, (-x1, -y1))
    bg.save("output.jpg")
    

    输出:

    【讨论】:

    • @Basj 确保不要编辑其他人的答案。如果你有答案,你可以添加它。对其他人的答案做出重大改变是不道德的。诸如拼写和标题更改之类的小修改都可以。在您的编辑中,OP 的意图已完全改变,因此最好添加另一个答案。
    • @JeruLuke,sardok 回答的最初想法完全保留在编辑中(bg = Image.new('RGB', ..., (255, 255, 255)),然后是bg.paste)。这只是一个小修改,因为我的问题最初是关于顶部和左侧的 相同 的边框。我只是更改为符合问题的(更一般的)当前表述。
    • @JeruLuke 所以这不是一个新想法/新答案,只是一个小小的修改。此外,它现在 100% 正常工作(见输出),这就是为什么最好不要将其更改为初始状态。
    • @Basj 无法反驳 +1
    • 谢谢@JeruLuke! (几天前我也已经为你 +1 了;))
    【解决方案2】:

    使用 PIL 的 ImageOps 模块中的 expand() 函数后,您可以做您想做的事情。

    from PIL import Image
    from PIL import ImageOps
    filename = 'C:/Users/Desktop/Maine_Coon_263.jpg'
    img = Image.open(filename)
    
    val = 10    #--- pixels to be cropped
    
    #--- a new image with a border of 10 pixels on all sides
    #--- also notice fill takes in the color of white as (255, 255, 255)
    new_img = ImageOps.expand(img, border = val, fill = (255, 255, 255))
    
    #--- cropping the image above will not result in any black portion
    cropped = new_img.crop((val, val, 150, 150))
    

    crop() 函数只接受一个参数,即需要裁剪多少部分。当传入负值时,没有功能可以处理这种情况。因此,在传递负值时,图像会被填充为黑色像素。

    使用expand() 函数,您可以设置您选择的颜色,然后继续进行裁剪。

    编辑

    作为对您的编辑的回应,我的想法很天真,但它确实有效。

    • 获取所有要裁剪的值的绝对值。您可以使用numpy.abs()
    • 接下来是这些值中的最大值,使用numpy.max()
    • 最后使用此值扩展图像并进行相应裁剪。

    此代码将帮助您:

    #--- Consider these values in a tuple that are to crop your image 
    crop_vals = (-10, -20, 1000, 500)
    
    #--- get maximum value after obtaining the absolute of each
    max_val = np.max(np.abs(crop_vals))
    
    #--- add border to the image using this maximum value and crop
    new_img = ImageOps.expand(img, border = max_val, fill = (255, 255, 255))
    cropped = new_img.crop((max_val - 10, max_val - 20, new_img.size[0], new_img.size[1]))
    

    【讨论】:

    • 好主意!
    • 感谢您的回答@JeruLuke。我的问题是在特定情况下制定的(每边 10 像素的边框)。我编辑了一个更一般的情况(每边的黑色边框不同),您将如何处理这种一般情况?
    • '填充黑色像素'的描述并不完全正确。 “额外”像素的图像数据设置为零。对于 RGB(A) 图像,这意味着这些像素是黑色的。对于调色板图像,它是分配给调色板中位置 0 的任何颜色。
    • 我们很接近@JeruLuke,但它给出了输出:imgur.com/a/92UFOeS ;)
    • @Basj 有一个小错误。再次查看更新
    猜你喜欢
    • 2010-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-24
    • 2014-02-08
    • 1970-01-01
    相关资源
    最近更新 更多