Как сделать эту функцию «обрезки» / изменения цвета фона более эффективной? - PullRequest
0 голосов
/ 20 ноября 2018

Я создаю веб-приложение, которое требует "обнаружения" одежды по изображению с белым фоном (или, по крайней мере, по фону с некоторой контрастностью).

У меня есть следующая функция, которая должназаменить все пиксели на белые пиксели в изображении, которые отличаются более чем на 70% от пикселя в центре изображения с точки зрения их значения RGB.

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 голосов
/ 20 ноября 2018

Я думаю, что вы могли бы использовать 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)

Если некоторые патчи в структуре ниже порога, они становятся прозрачными.Чтобы избежать этого, вы можете извлечь контуры и удалить «слишком маленькие», чтобы они были целой тканью.Вы также можете предварительно обработать изображения, чтобы удалить вешалку, которая создает отверстия (верхняя часть вашего изображения).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...