Методы извлечения переднего плана изображения с использованием Python

Я подготовил фрагмент кода на питоне с использованием OpenCV, который извлекает передний план изображения. Моя программа получает поток изображений, и мне нужно извлечь объект из этих изображений.

Изображения включают такие продукты, как обувь, сумки или одежду. У большинства изображений белый фон, но иногда я получаю серый градиентный фон. Я использовал пороговое значение, чтобы отделить передний план от фона и извлечь объект.

Но проблема в том, что даже если я предполагаю, что фон будет белым, и устанавливаю фиксированные верхнее и нижнее пороговые значения, я иногда получаю белый цвет в объекте, а пороговое значение не отображает правильный вывод.

Я хотел знать, какие могут быть хорошие подходы в Computer Vision, которые я могу использовать, чтобы получить здесь наилучшие результаты?

введите здесь описание изображения


person Ubaid    schedule 26.04.2021    source источник
comment
Можете ли вы опубликовать код, который у вас есть до сих пор?   -  person stateMachine    schedule 27.04.2021
comment
Вам понадобится искусственный интеллект / глубокое обучение, чтобы сделать это достаточно хорошо. См., например, remove.bg.   -  person fmw42    schedule 27.04.2021
comment
@ fmw42 Я думал о том же решении. Есть ли какие-то наборы данных для этого теста?   -  person Ubaid    schedule 28.04.2021
comment
@Убайд. Не то чтобы я знаю.   -  person fmw42    schedule 28.04.2021
comment
Только что выполнил поиск и нашел towardsdatascience.com/. Он использует набор данных COCO.   -  person fmw42    schedule 28.04.2021


Ответы (1)


Вы можете получить этот результат:

введите здесь описание изображения

используя детектор краев Канни, дилатацию и эрозию:

import cv2
import numpy as np

def process(img):
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    img_canny = cv2.Canny(img_gray, 12, 54)
    kernel = np.ones((3, 3))
    img_dilate = cv2.dilate(img_canny, kernel, iterations=10)
    img_erode = cv2.erode(img_dilate, kernel, iterations=8)
    return img_erode

img = cv2.imread("robe.jpg")
contours, _ = cv2.findContours(process(img), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
cv2.drawContours(img, contours, -1, (0, 255, 0), 2)
cv2.imshow("Image", img)
cv2.waitKey(0)

Объяснение функции process:

  1. Во-первых, преобразуйте изображение в оттенки серого, чтобы использовать на нем детектор краев. Затем обнаружьте его края с помощью детектора осторожных краев:
def process(img):
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    img_canny = cv2.Canny(img_gray, 12, 54)
  1. Определите ядро, которое будет использоваться для расширения и размытия изображения:
    kernel = np.ones((3, 3))
  1. Наконец, несколько раз расширьте изображение, чтобы заполнить пробелы, удалить шум и сгладить неровности по краям. конечно, расширение делает края более толстыми, поэтому после этого размывайте изображение, чтобы уменьшить их обратно. Но так как перед расширением было много пробелов по краям, размывайте изображение меньшим количеством итераций. Вернуть размытое изображение:
    img_dilate = cv2.dilate(img_canny, kernel, iterations=10)
    img_erode = cv2.erode(img_dilate, kernel, iterations=8)
    return img_erode
person Ann Zen    schedule 27.04.2021
comment
Я пробовал его и пару других детекторов краев, но проблема с детекторами краев заключается в том, что мы получаем только внешний контур, а это довольно простое изображение, в котором нет внутренних контуров, которые необходимо обнаружить. Допустим, если бы на этом изображении была сумочка и внутри ремня сумки была бы какая-то часть фона, мы бы не получили этого с помощью детекторов краев. А если мы включим еще и внутренние контуры, то наверняка получим много нежелательных контуров и при этом можем потерять часть объекта. - person Ubaid; 28.04.2021