裁剪图像中的背景 - NumPy / Python

Crop out background in an image - NumPy / Python

我提取了以下图像。背景值为 170,我需要提取至少包含 170 个值的多边形。 图像如下

我想要一张经过处理的图片如下

我可以实现一个嵌套的 for 循环并遍历,直到我找到列的最小索引并找到每行列号的最大索引,然后提取区域..但我对 numpy 查询感兴趣更高效的解决方案

方法 #1

一种策略是标记图像,获取其中一个角的标签,作为背景颜色的一个样本,并创建该颜色的遮罩。因此,倒置遮罩区域是我们要裁剪的区域。对于裁剪,我们将从 Crop black border of image using NumPy : Answer post.

中获取灵感

这是实现 -

import cv2
from scipy.ndimage import label

im = cv2.imread('xYTKn.png') # read in input image
L,_ = label(im)
mask = (L!=L[0,0]).any(-1)
out = im[np.ix_(mask.any(1), mask.any(0))]
cv2.imwrite('output.png',out)

输入-

输出-


方法 #2

另一种类似的策略是预先转换为灰度,然后标记并获得所需的蒙版,就像这样 -

gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
L,_ = label(gray)
mask = (L!=L[0,0])
out = im[np.ix_(mask.any(1), mask.any(0))]

基准测试

我们将在给定的示例图像上对建议的解决方案进行计时。两种方法的掩码创建不同。所以,我们将只为这些部分计时 -

In [70]: %%timeit
    ...: L,_ = label(im)
    ...: mask = (L!=L[0,0]).any(-1)
47.4 ms ± 2.37 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [71]: %%timeit
    ...: gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
    ...: L,_ = label(gray)
    ...: mask = (L!=L[0,0])
2.59 ms ± 20.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)