0

我正在构建一个网络应用程序,它需要从具有白色背景的图像(或至少从与它有一些对比的背景中)“检测”服装。

我有以下函数应该将图像中的所有像素替换为白色像素,就其 RGB 值而言,它们与图像中心的像素相差超过 70%。

def crop(self, image_data):
    '''"Crops" image by changing all RGB values to [255, 255, 255] if they differ more than
        70% from the pixel in the center of the image.
    '''
    image_data.setflags(write=1)
    height, width, channels = image_data.shape
    new_image_data = np.full((height, width, 3), 255)
    middle_pixel = image_data[(height // 2), (width // 2)]
    middle_pixel_avg = np.mean(middle_pixel)
    difference_limit = middle_pixel_avg * 0.7
    for row in range(height):
        for col in range(width):
            pixel_avg = np.mean(image_data[row, col])
            if (abs(middle_pixel_avg - pixel_avg) <= difference_limit):
                new_image_data[row, col] = image_data[row, col]
    return new_image_data

它的效率极低,在 iPhone 上拍摄的常规图像上运行大约需要 30 秒。这也很可怕,并且似乎是检测图像背景的完全错误的方法。

首先,我想知道如何使我的这个功能更有效。其次,我想知道是否有更好,更可靠的方法可以做到这一点?

这是此函数实际执行的示例: 在此处输入图像描述 在此处输入图像描述

4

1 回答 1

1

我认为您可以将 OpenCV 用于您函数中的大部分部分。例如,一旦您对中心 3x3 区域的强度进行了采样(一个像素可能不足以代表织物的“平均”强度),您可以使用此结果对图像的灰度版本进行阈值处理使用 cv2.threshold() 函数,该函数先验应该比 python 循环更快。最终,您可以使用此蒙版提取前景。

这是这种实现的框架:

import cv2
import numpy as np

def remove_background(image):
    """
    Remove the light background from an image of a dark fabric.
    """

    image_intensity = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    assert (image.shape[:2] == image_intensity.shape[:2])
    height, width, channels = image.shape
    dst = np.zeros((height, width, 3))

    center_x = height // 2
    center_y = width // 2

    center_intensity = image_intensity[center_x:center_x+3, center_y:center_y+3]
    center_intensity_avg = np.mean(center_intensity)
    threshold = 3 * center_intensity_avg

    _, thresholded = cv2.threshold(image_intensity, threshold, 255, cv2.THRESH_BINARY)
    mask = cv2.cvtColor(thresholded, cv2.COLOR_GRAY2BGR)
    result = cv2.add(image, mask)

    return threshold, result

image = cv2.imread("./data/BuGgK.jpg", cv2.IMREAD_COLOR)
threshold, result = remove_background(image)
cv2.imwrite('./out/result.png', result)

如果织物中的某些补丁低于阈值,它们就会变得透明。为避免这种情况,您可以提取轮廓并删除那些“太小”而不能成为整块布料的轮廓。您还可以对图像进行预处理以移除产生孔的衣架(图像中的上部)。

于 2018-11-20T14:02:56.737 回答