动态裁剪图像边框

Crop image borders dynamically

如何裁剪看起来像这样的图像并将其另存为 3 张不同的图像?

问题是图片大小不一样,不成比例,所以我想做一个代码,动态切黑边,而不是图片里面的黑色部分。

这是期望的结果:

下面是我制作的示例代码,它仅适用于一张特定图像。

from PIL import Image
im = Image.open(r"image.jpg")

# Setting the points for cropped image1
# im1 = im.crop((left, top, right, bottom))
im1 = im.crop((...))
im2 = im.crop((...))
im3 = im.crop((...))

im1 = im1.save(r"image1.jpg")
im2 = im2.save(r"image2.jpg")
im3 = im3.save(r"image3.jpg")

我终于找到了解决办法。这是我所做的:

from PIL import Image, ImageChops

def RemoveBlackBorders(img):
    bg = Image.new(img.mode, img.size, img.getpixel((0,0)))
    diff = ImageChops.difference(img, bg)
    diff = ImageChops.add(diff, diff, 2.0, -100)
    bbox = diff.getbbox()
    if bbox:
        return img.crop(bbox)

# Opens a image in RGB mode
im = Image.open(r"C:\Path\Image.jpg")

# removing borders

im = RemoveBlackBorders(im)

# getting midpoint from size

width, height = im.size
mwidth = width/2

# assign shape of figure from the midpoint

     #crop((x,y of top left, x, y of bottom right))
im1 = im.crop((0, 0, mwidth-135, height))
im2 = im.crop((mwidth-78, 0, mwidth+84, height))
im3 = im.crop((mwidth+135, 0, width, height))

我从 here.

中找到的删除边框的函数

虽然解决方案不是完全动态的,但它仍然以 ~90% 的准确率解决了我的问题。但我相信应该有一个更通用的方法来解决这个问题。

如果区域始终具有相同的大小和相同的顶部和底部坐标,则以下应该有效:

可以通过计算每行和每列的总和,然后对其进行分析来检索作物的坐标。

import cv2
import numpy as np
im = cv2.imread(image_path)
sum_of_rows = np.sum(im, axis=(1,2))
sum_of_cols = np.sum(im, axis=(0,2))

可以通过计算每行的总和来计算顶部和底部(每个总和值按 R+G+B 计算,对于黑色,该值应为零)。然后寻找不同于零的第一个值和不同于零的最后一个值。均表示顶部和底部。

top = np.argmax(sum_of_rows > 0)
bottom = top + np.argmax(sum_of_rows[top:]==0)

对每一列的总和也可以这样做,但这里检查多个左右值。