如何使这种“裁剪” /背景颜色更改功能更有效?

时间:2018-11-20 13:41:55

标签: python numpy image-processing

我正在构建一个Web应用程序,该应用程序需要从具有白色背景的图像(或至少从与之形成对比的背景)“检测”服装。

我具有以下功能,该功能应该将图像中的所有像素替换为白色像素,这些像素的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

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

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

以下是此函数实际作用的一个示例: enter image description here enter image description here

1 个答案:

答案 0 :(得分: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)

如果结构中的某些色块低于阈值,它们将变为透明。为避免这种情况,您可以提取轮廓,然后去除“太小”以至不能整块衣服的轮廓。您也可以对图像进行预处理,以除去会产生孔的衣架(图像的上部)。