我試圖做蝴蝶的照片同樣的事情,但更多的不均衡和不可預測的背景,如this。一旦你確定了背景的一個很好的部分(例如通過閾值處理,或者像我們一樣,從隨機點填充),最好的辦法是使用GrabCut算法來獲得你在初始通過時可能會錯過的所有位。在Python中,假設你仍然希望通過閾值上飽和通道,以確定背景的初始區域,嘗試像
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等人提出的色度失真度量來比較圖像中的區域與現在已知的背景的顏色。人。 (1999),「實時穩健背景減法和陰影檢測的統計方法」。這一措施考慮到了對於不飽和的顏色,色相不是相關的措施。
請注意,您在網上找到的預印本的pdf在等式6中有一個錯誤(無+符號)。您可以使用在Rodriguez-Gomez et al (2012),等式1 & 2中重新引用的版本。或者你可以使用我下面的Python代碼:
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像素圖像作爲第一個參數,它應該告訴你的是陰影與背景基本上是相同的色度,並且與葉子非常不同。在下面的代碼中,我已經對chromacity進行了閾值處理,並且完成了另一次抓取通過。此作品去除陰影,即使第一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