Как удалить белый фон с некоторой тенью в grabcut? - PullRequest
2 голосов
/ 28 июня 2019

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

Входное изображение

Input image

Выходное изображение

output image

Пробный захват, контур, нормальный порог, но тень остается

img_ray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(img_ray, 127, 255, cv.THRESH_BINARY+cv.THRESH_OTSU)
contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_NONE)
cnt = contours[4]
cv.drawContours(img, [cnt], 0, (0, 255, 0), 3)
mask = np.zeros(img.shape[:2], np.uint8)
bgdmodel = np.zeros((1, 65), np.float64)
fgdmodel = np.zeros((1, 65), np.float64)
height = img.shape[0]
width = img.shape[1]
rect = (50, 0, width, height)
cv.grabCut(img, mask, rect, bgdmodel, fgdmodel, 10, cv.GC_INIT_WITH_RECT)
mask2 = np.where((mask == 2) | (mask == 0), 0, 1).astype('uint8')
img = img * mask2[:, :, np.newaxis]
img[np.where((img == [230, 230, 230]).all(axis=2))] = [0, 0, 0]
cv.bitwise_not(img)

должен полностью удалить фон

1 Ответ

1 голос
/ 28 июня 2019

Этот ответ объясняет, как использовать Grabcut и маску для извлечения переднего плана. В этом ответе есть два шага. Первым шагом является создание маски, которая маркирует пиксели как уверенный передний план, верный фон или неизвестный Второй шаг - применение алгоритма Grabcut.

Маска создается с использованием Canny краевого фильтра и двух морфологических преобразований .

edges = cv.Canny(img, 80,150)
kernel = np.ones((5,5), np.uint8)
closing = cv.morphologyEx(edges, cv.MORPH_CLOSE, kernel, iterations=3)
erosion = cv.morphologyEx(closing, cv.MORPH_ERODE, kernel, iterations=1)

# When using Grabcut the mask image should be:
#    0 - sure background
#    1 - sure foreground
#    2 - unknown

mask = np.zeros(img.shape[:2], np.uint8)
mask[:] = 2
mask[erosion == 255] = 1

Эта маска даст алгоритму Grabcut подсказки о том, что является верным передним планом и каков верный фон. Затем примените Grabcut с маской:

bgdmodel = np.zeros((1, 65), np.float64)
fgdmodel = np.zeros((1, 65), np.float64)

out_mask = mask.copy()
out_mask, _, _ = cv.grabCut(img,out_mask,None,bgdmodel,fgdmodel,1,cv.GC_INIT_WITH_MASK)
out_mask = np.where((out_mask==2)|(out_mask==0),0,1).astype('uint8')
out_img = img*out_mask[:,:,np.newaxis]

mask отображается как mask*123, так что передний план серого цвета, задний фон черного цвета, а неизвестный белый: output

...