Что такое интерактивное извлечение переднего плана
Классические методы извлечения переднего плана в основном выполняются с использованием информации о текстуре (цвете), например, инструмента «Волшебная палочка», или на основе информации о краях (контрасте), например, «умные ножницы» и т. д. В 2004 году Ротер и др. из Microsoft Research предложили интерактивную технику выделения переднего плана в своей статье. Предложенный ими алгоритм может точно извлекать изображения переднего плана с минимальным взаимодействием.
Приступая к извлечению переднего плана, сначала используйте прямоугольную рамку, чтобы указать приблизительный диапазон местоположения области переднего плана, а затем итеративно сегментируйте, пока не будет достигнут наилучший эффект. После вышеуказанной обработки эффект выделения переднего плана может быть не идеальным, и возникает ситуация, когда передний план не извлекается, или фон извлекается как передний.В этом случае пользователю необходимо вмешаться в извлечение процесс. В копии исходного изображения (или любого изображения того же размера, что и исходное изображение) пользователь помечает область, которую нужно выделить как передний план, белым цветом, область, которая будет использоваться в качестве фона, черным цветом, а затем использует помеченное изображение как маска по модулю, пусть алгоритм продолжит итеративно извлекать передний план, чтобы получить окончательный результат.
Например, для изображения человека на изображении выше сначала используйте прямоугольную рамку, чтобы обрамить извлекаемый передний план, а затем используйте белый и черный цвета, чтобы отметить изображение переднего плана и фоновое изображение соответственно. После завершения аннотации весь передний план персонажа может быть извлечен с использованием интерактивного алгоритма извлечения переднего плана.
Ниже блогер подробно представит принцип интерактивного алгоритма извлечения переднего плана алгоритма GrabCut:
- Используйте прямоугольник, чтобы отметить приблизительную область, где расположен передний план. Стоит отметить, что прямоугольная рамка в это время лишь очерчивает приблизительное положение переднего плана, включающего в себя как передний, так и задний план, поэтому эта область фактически является неопределенной областью. Но области за пределами этой области считаются «определяющим контекстом».
- Различать передний план и фон в области поля на основе данных «определить фон» за пределами поля.
- Смоделируйте передний план и фон с помощью гауссовой модели смеси (GMM). GMM изучает и создает новые распределения пикселей на основе пользовательского ввода. Неклассифицированные пиксели (которые могут быть фоном или передним планом) классифицируются в соответствии с их отношением к известным классифицированным пикселям (передний план и фон).
- График создается в соответствии с распределением пикселей, а узлы на графике представляют собой отдельные пиксели. В дополнение к пикселям есть два узла: узел переднего плана и узел фона. Все пиксели переднего плана подключены к узлам переднего плана, а все пиксели фона подключены к узлам фона. Вес ребра каждого пикселя, соединяющегося с передним или фоновым узлом, определяется вероятностью того, что пиксель находится на переднем или заднем плане.
- В дополнение к соединению с узлами переднего плана или фона, каждый пиксель в графе также связан друг с другом. Значение веса ребра, соединяющего два пикселя, определяется их сходством, чем ближе цвет значений двух пикселей, тем выше значение веса ребра.
- После завершения соединения узлов решаемая задача становится связным графом. Граф разрезается в соответствии с соотношением весов соответствующих ребер, а разные точки делятся на узлы переднего плана и узлы фона.
- Описанный выше процесс повторяется непрерывно, пока классификация не сойдется.
функция захватаCut
В OpenCV он предоставляет нам функцию cv2.grabCut() для интерактивного извлечения переднего плана, которая полностью определена следующим образом:
def grabCut(img, mask, rect, bgdModel, fgdModel, iterCount, mode=None):
img: входное изображение, 8-битное 3-канальное
mask: изображение маски, 8-битный одиночный канал. Этот параметр используется для определения области переднего плана, области фона и неопределенной области и может быть установлен в 4 формах:
ценность | значение |
---|---|
cv2.GC_BGD | Указывает, что фон определен, а также может быть представлен значением 0 |
cv2.GC_FGD | Указывает, что передний план определен, а также может быть представлен значением 1 |
cv2.GC_PR_BGD | Указывает на возможный фон, который также может быть представлен значением 2 |
cv2.GC_PR_FGD | Указывает на возможные перспективы, которые также могут быть представлены значением 3 |
При использовании шаблона для извлечения переднего плана значения параметров 0 и 2 будут объединены с фоном (оба рассматриваются как 0), а значения параметров 1 и 3 будут объединены с передним планом (оба обработаны как 1). ). Обычно мы можем использовать белую кисть и черную кисть, чтобы отметить изображение маски, а затем установить белые пиксели на 0, а черные пиксели на 1 посредством преобразования.
rect: относится к области, содержащей объект переднего плана, часть за пределами этой области считается «определенным фоном». Поэтому обязательно убедитесь, что передний план входит в диапазон, указанный прямоугольником при выборе, иначе часть переднего плана за пределами прямоугольника не будет извлечена. Параметр rect имеет смысл только тогда, когда значение режима параметра установлено в режим прямоугольника cv2.GC_INIT_WITH_RECT. Его формат (x, y, w, h), которые соответственно представляют координаты оси X и оси Y левого верхнего угла области, а также длину и ширину области. Если передний план находится внизу справа и вы не хотите судить о размере исходного изображения, вы можете напрямую использовать большое значение для w и h. При использовании режима маски установите для этого значения значение none.
bgdModel: массив, используемый внутри алгоритма, значение необходимо для создания массива numpy.float64 размера (1, 65).
fgdModel: массив, используемый внутри алгоритма, значение необходимо для создания массива numpy.float64 размера (1, 65).
iterCount: количество итераций
режим: Итеративный режим, конкретные значения следующие:
ценность | значение |
---|---|
cv2.GC_INIT_WITH_RECT | Используйте прямоугольный шаблон |
cv2.GC_INIT_WITH_MASK | Используйте пользовательские шаблоны. Обратите внимание, что cv2.GC_INIT_WITH_RECT и cv2.GC_INIT_WITH_MASK можно использовать в комбинации. Все пиксели за пределами области интереса (то есть не в пределах указанного диапазона шаблона или прямоугольника) будут автоматически обработаны как фон. |
cv2.GC_EVAL | Режим ремонта |
cv2.GC_EVAL_FREEZE_MODEL | Использовать фиксированный режим |
Извлечь изображение переднего плана
Теперь, когда мы понимаем принцип, мы также знаем методы, предоставляемые OpenCV. Далее попробуем извлечь передний план изображения выше, код выглядит следующим образом:
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread("4.jpg")
plt.subplot(121)
plt.imshow(img, cmap="gray")
plt.axis('off')
mask = np.zeros(img.shape[:2], dtype=np.uint8)
bgdModel = np.zeros((1, 65), dtype=np.float64)
fgdModel = np.zeros((1, 65), dtype=np.float64)
mask[10:200, 95:220] = 3
cv2.grabCut(img, mask, None, bgdModel, fgdModel, 5, cv2.GC_INIT_WITH_MASK)
mask2 = np.where((mask == 2) | (mask == 0), 0, 1).astype('uint8')
ogc = img * mask2[:, :, np.newaxis]
plt.subplot(122)
plt.imshow(ogc, cmap="gray")
plt.axis('off')
plt.show()
После запуска мы можем полностью разделить лицо и фон, эффект получается следующий:
Что касается того, почему значение маски такое, давайте посмотрим на следующий код:
import cv2
img = cv2.imread("4.jpg")
rect=img[10:200,95:220]
cv2.imshow("4",rect)
cv2.waitKey()
cv2.destroyAllWindows()
После запуска эффект следующий:
Видно, что 10:200, 95:220 — это прямоугольный прямоугольник с координатами (10, 95) шириной и высотой 200, 220, который является прямоугольным прямоугольником возможного переднего плана. С помощью возможного переднего плана и алгоритма CrabCut мы получаем определенный передний план (вот голова персонажа).
Извлечь передний план изображения с помощью шаблона
Ниже мы напрямую используем cv2.GC_INIT_WITH_MASK для извлечения. код показывает, как показано ниже:
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread("4.jpg")
mask = np.zeros(img.shape[:2], dtype=np.uint8)
bgdModel = np.zeros((1, 65), dtype=np.float64)
fgdModel = np.zeros((1, 65), dtype=np.float64)
rect = (60, 10, 400, 500)
cv2.grabCut(img, mask, rect, bgdModel, fgdModel, 5, cv2.GC_INIT_WITH_RECT)
mask2 = cv2.imread("37.jpg",0)
plt.subplot(121)
plt.imshow(mask2, cmap="gray")
plt.axis('off')
mask[mask2 == 0] = 0
mask[mask2 == 255] = 1
mask, bgd, fgd = cv2.grabCut(img, mask, None, bgdModel, fgdModel, 5, cv2.GC_INIT_WITH_MASK)
mask = np.where((mask == 2) | (mask == 0), 0, 1).astype('uint8')
ogc = img * mask[:, :, np.newaxis]
plt.subplot(122)
plt.imshow(ogc, cmap="gray")
plt.axis('off')
plt.show()
После запуска эффект следующий:
Здесь мы построили шаблон без использования прямоугольного блока. Через шаблон мы можем получить другое изображение и примерно определить передний план. Здесь мы используем аннотацию пикселя 0 для определения фона и аннотацию пикселя 1 для определения переднего плана.