Quello che hai è quasi corretto. Se date un'occhiata alla vostra immagine con soglia, il motivo per cui non funziona è perché l'oggetto da scarpe ha lacune nell'immagine. In particolare, quello che cerchi è che ti aspetti che la scarpa abbia il suo perimetro all connesso. Se ciò dovesse accadere, allora se estrai il contorno più esterno (che è ciò che sta facendo il tuo codice), dovresti avere solo un contorno che rappresenta il perimetro esterno dell'oggetto. Una volta completato il contorno, la scarpa dovrebbe essere completamente solida.
Poiché il perimetro della scarpa non è completo e rotto, ciò provoca aree bianche disconnesse. Se si utilizza findContours
per trovare tutti i contorni, verranno individuati solo i contorni di ciascuna delle forme bianche e non il perimetro più esterno. Pertanto, se provi a utilizzare findContours
, otterrai lo stesso risultato dell'immagine originale, perché stai semplicemente individuando il perimetro di ciascuna regione bianca all'interno dell'immagine, quindi riempiendo queste aree con findContours
.
Quello che dovete fare è assicurarsi che l'immagine è completamente chiuso. Quello che vorrei raccomandare è usare morphology per chiudere tutte le regioni disconnesse insieme, quindi eseguire una chiamata findContours
su questa nuova immagine. In particolare, eseguire una chiusura morfologica binaria. Ciò che fa è che prende le regioni bianche disconnesse che sono vicine e assicura che siano connesse. Usa una chiusura morfologica e forse usa qualcosa come un elemento strutturante quadrato 7 x 7 per chiudere la scarpa. Questo elemento strutturante può essere considerato come la separazione minima tra le regioni bianche per considerarle come connesse.
Come tale, fare qualcosa di simile:
import numpy as np
import cv2
image = cv2.imread('...') # Load your image in here
# Your code to threshold
image = cv2.adaptiveThreshold(image, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 45, 0)
# Perform morphology
se = np.ones((7,7), dtype='uint8')
image_close = cv2.morphologyEx(image, cv2.MORPH_CLOSE, se)
# Your code now applied to the closed image
cnt = cv2.findContours(image_close, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[0]
mask = np.zeros(image.shape[:2], np.uint8)
cv2.drawContours(mask, cnt, -1, 255, -1)
Questo codice riprende in sostanza l'immagine thresholded, e si applica chiusura morfologica di questa immagine. Dopo, troviamo i contorni esterni di questa immagine e li riempiamo di bianco. FWIW, ho scaricato la tua immagine con soglia e l'ho provata da sola. Questo è quello che ottengo con la vostra immagine:

Ciò è impressionante, non riesco a credere che questo funziona! In un pomeriggio sono riuscito a sfocare lo sfondo di un'immagine. Opencv è abbastanza bello. – emschorsch
@emschorsch - grazie per l'upvote :) Sì, OpenCV è una piattaforma fantastica. Lo uso ogni giorno per lavoro. Buon divertimento! – rayryeng
@rayryeng Ho provato questo codice ma sull'ultima riga lancia il seguente errore 'drawing.cpp: 2380: errore: (-215) npoints> 0 nella funzione cv :: drawContours' - Sto usando OpenCV 3.1 e Python 2.7 . Qualche idea? – g491