sto cercando di fare la stessa cosa con le foto di farfalle, ma con sfondi più irregolari e imprevedibili, come this. Una volta identificata una buona parte dello sfondo (ad esempio tramite la soglia, o come facciamo, riempire inondazioni da punti casuali), ciò che funziona bene è usare l'algoritmo GrabCut per ottenere tutti quei bit che potresti perdere sul passaggio iniziale. In Python, supponendo che si vuole ancora identificare un'area iniziale di sfondo dal thresholding sul canale di saturazione, provare qualcosa di simile
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])
Questo in realtà si libera delle ombre per voi, in questo caso, perché il bordo dell'ombra ha effettivamente alti livelli di saturazione, quindi è incluso nella cancellazione del taglio. (Pubblicheremo le immagini, ma non ho abbastanza reputazione)
Di solito, tuttavia, non è possibile considerare le ombre da includere nel rilevamento dello sfondo. In questo caso probabilmente vorrai confrontare le aree dell'immagine con il colore dello sfondo ora noto usando la distorsione di cromaticità proposta da Horprasert et. al. (1999) in "Un approccio statistico per la sottrazione di fondo e il rilevamento dell'ombra" in tempo reale. Questa misura tiene conto del fatto che per i colori desaturati, la tonalità non è una misura pertinente.
Si noti che il pdf della prestampa che si trovano on-line ha un errore (no segni +) nell'equazione 6. È possibile utilizzare la versione re-citato in Rodriguez-Gomez et al (2012), equazioni 1 & 2.Oppure si può utilizzare il mio codice python di seguito:
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))
è possibile alimentare il fondo noto significare & stdev come gli ultimi due parametri della funzione chromacity_distortion, e l'immagine RGB dei pixel come primo parametro, che dovrebbe mostrare che l'ombra è fondamentalmente la stessa cromaticità dello sfondo e molto diversa dalla foglia. Nel codice qui sotto, ho quindi eseguito il thresholding sulla chromacity e ho fatto un altro passaggio grabcut. Questo funziona per rimuovere l'ombra, anche se il primo passaggio grabcut non (ad esempio, se in origine thresholded sulla tonalità)
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)
ho paura con i parametri che ho provato, questo elimina ancora il gambo, però. Penso che sia perché GrabCut pensa che abbia un colore simile alle ombre. Fammi sapere se trovi un modo per tenerlo.
Poiché la foglia è verde e lo sfondo è bianco/ombra, è possibile lavorare sul canale della tonalità. – GilLevi
@GilLevi, vedere l'aggiornamento. Non aiuta a eliminare l'ombra. – Mahm00d
Hmmm, non sono davvero sicuro. Forse usando un diverso spazio colore, come LAB? Mi dispiace, non posso aiutare ulteriormente. – GilLevi