Я пытаюсь сделать то же самое с фотографиями бабочек, но с более неровным и непредсказуемым происхождением, такими как this. Как только вы определили хорошую часть фона (например, через пороговое значение или, как мы делаем, заливаем поток из случайных точек), хорошо работает алгоритм GrabCut, чтобы получить все те биты, которые вы могли бы пропустить при первоначальном проходе. В питоне, если вы все еще хотите, чтобы определить начальную область фона по пороговому на канале насыщения, попробуйте что-то вроде
import cv2
import numpy as np
img = cv2.imread("leaf.jpg")
sat = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)[:,:,1]
sat = cv2.medianBlur(sat, 11)
thresh = cv2.adaptiveThreshold(sat , 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 401, 10);
cv2.imwrite("thresh.jpg", thresh)
h, w = img.shape[:2]
bgdModel = np.zeros((1,65),np.float64)
fgdModel = np.zeros((1,65),np.float64)
grabcut_mask = thresh/255*3 #background should be 0, probable foreground = 3
cv2.grabCut(img, grabcut_mask,(0,0,w,h),bgdModel,fgdModel,5,cv2.GC_INIT_WITH_MASK)
grabcut_mask = np.where((grabcut_mask ==2)|(grabcut_mask ==0),0,1).astype('uint8')
cv2.imwrite("GrabCut1.jpg", img*grabcut_mask[...,None])
Это фактически избавляется от теней для вас в этом случае, потому что край тени на самом деле имеет высокий уровень насыщения, поэтому включен в удаление разреза. (Я бы разместил изображения, но не имел достаточной репутации)
Обычно вы не можете доверять теням, которые должны быть включены в обнаружение фона. В этом случае вы, вероятно, захотите сравнить области изображения с цветом уже известного фона с использованием искажения по току , предложенного Horprasert et. и др. (1999) в «Статистическом подходе к вычитанию и обнаружению тени в реальном времени». Эта мера учитывает тот факт, что для ненасыщенных цветов оттенок не является подходящей мерой.
Обратите внимание, что в pdf препринте, который вы находите в Интернете, есть ошибка (нет + знаков) в уравнении 6. Вы можете использовать версию, указанную в Rodriguez-Gomez et al (2012), уравнения 1 & 2.Или вы можете использовать мой питон код ниже:
def brightness_distortion(I, mu, sigma):
return np.sum(I*mu/sigma**2, axis=-1)/np.sum((mu/sigma)**2, axis=-1)
def chromacity_distortion(I, mu, sigma):
alpha = brightness_distortion(I, mu, sigma)[...,None]
return np.sqrt(np.sum(((I - alpha * mu)/sigma)**2, axis=-1))
Вы можете кормить известный фон означает, & STDEV как последние два параметра функции chromacity_distortion, а RGB пиксела изображения в качестве первого параметра, который должен показать, что тень в основном такая же, как и у фона, и очень отличается от листа. В приведенном ниже коде я установил пороговое значение в отношении непрозрачности и сделал еще один проход grabcut. Это работает, чтобы удалить тень, даже если первый grabcut проход не (например, если вы изначально порогами на оттенок)
mean, stdev = cv2.meanStdDev(img, mask = 255-thresh)
mean = mean.ravel() #bizarrely, meanStdDev returns an array of size [3,1], not [3], so flatten it
stdev = stdev.ravel()
chrom = chromacity_distortion(img, mean, stdev)
chrom255 = cv2.normalize(chrom, alpha=0, beta=255, norm_type=cv2.NORM_MINMAX).astype(np.uint8)[:,:,None]
cv2.imwrite("ChromacityDistortionFromBackground.jpg", chrom255)
thresh2 = cv2.adaptiveThreshold(chrom255 , 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 401, 10);
cv2.imwrite("thresh2.jpg", thresh2)
grabcut_mask[...] = 3
grabcut_mask[thresh==0] = 0 #where thresh == 0, definitely background, set to 0
grabcut_mask[np.logical_and(thresh == 255, thresh2 == 0)] = 2 #could try setting this to 2 or 0
cv2.grabCut(img, grabcut_mask,(0,0,w,h),bgdModel,fgdModel,5,cv2.GC_INIT_WITH_MASK)
grabcut_mask = np.where((grabcut_mask ==2)|(grabcut_mask ==0),0,1).astype('uint8')
cv2.imwrite("final_leaf.jpg", grabcut_mask[...,None]*img)
Боюсь, с параметрами, которые я пробовал, это все еще снимает стебелек, хотя. Я думаю, это потому, что GrabCut считает, что он похож на тени. Дайте мне знать, если вы найдете способ сохранить его.
Поскольку лист зеленый, а фон белый/тень, вы можете работать на канале оттенка. – GilLevi
@ GilLevi, см. Обновление. Это не помогает устранить тень. – Mahm00d
Хммм, я действительно не уверен. Возможно, используя другое цветовое пространство, например LAB? Извините, я не могу помочь дальше. – GilLevi