2015-06-16 12 views
15

Recentemente mi è stato dato un progetto, in cui devo estrarre la faccia (viso + capelli) da una determinata immagine.Ottimizzazione delle prestazioni di GrabCut in opencv-java

Sto risolvendo questo problema nei seguenti modi.

  1. Sto estraendo le posizioni dei volti da una determinata immagine. [Sto ottenendo un rettangolo]
  2. sto estraenti rettangolo e ponendolo in un'altra immagine di stesse dimensioni immagine in ingresso. [Face_image]
  3. Mi candido grabCut algoritmo sulla face_image dello step 2.

quando il face_image contiene bassa regolare l'algoritmo grabCut funzionare bene ma quando lo sfondo di face_image è complessa l'algoritmo grabCut estratti alcuni parte del fondo troppo nell'immagine elaborata.

Ecco un'istantanea dei risultati che sto ottenendo.

results of each step

Ecco il mio codice di grabCut:

public void extractFace(Mat image, String fileNameWithCompletePath, 
         int xOne, int xTwo, int yOne, int yTwo) throws CvException { 

    System.loadLibrary(Core.NATIVE_LIBRARY_NAME); 

    Rect rectangle = new Rect(xOne, yOne, xTwo, yTwo); 
    Mat result = new Mat(); 
    Mat bgdModel = new Mat(); 
    Mat fgdModel = new Mat(); 
    Mat source = new Mat(1, 1, CvType.CV_8U, new Scalar(3)); 
    Imgproc.grabCut(image, result, rectangle, bgdModel, fgdModel, 8, Imgproc.GC_INIT_WITH_RECT); 
    Core.compare(result, source, result, Core.CMP_EQ); 
    Mat foreground = new Mat(image.size(), CvType.CV_8UC3, new Scalar(255, 255, 255)); 
    image.copyTo(foreground, result); 
    Imgcodecs.imwrite(fileNameWithCompletePath, foreground); 
} 

Come posso migliorare le prestazioni di algoritmi grabCut in modo che possa rilevare solo il viso e capelli dalla data immagine?

risposta

8

Si dovrebbe essere in grado di farlo "aiutando" grabCut conoscere un po 'di primo piano e sfondo. C'è un python tutorial che mostra come questo viene fatto manualmente selezionando il primo piano e lo sfondo.

Per eseguire questa operazione automaticamente, è necessario trovare metodi programmatici per rilevare il primo piano e lo sfondo. Il primo piano consiste principalmente di capelli e pelle, quindi dovrai rilevarli.

Skin - Ci sono several documenti e blogs su come fare questo. Alcuni di questi sono pretty simple e this OpenCV tutorial possono anche aiutare. Ho trovato tinta unita/saturazione per portarmi molto lontano.

Capelli - Questo is trickier ma è definitely ancora doable. Potresti essere in grado di capelli e usare solo la pelle e lo sfondo se questo risulta essere troppo lavoro.

Sfondo: dovresti essere in grado di utilizzare range() per trovare elementi nell'immagine che sono viola, verde e blu. Sai per certo che queste cose non sono pelle o capelli e quindi fanno parte dello sfondo.

Utilizzare la soglia per creare una maschera delle aree che sono più probabili pelle, capelli e sfondo. È quindi possibile utilizzarli come bgdModel e fgdModel (o le maschere pelle e capelli) anziché Mat().

Spiacente, questo è così di alto livello. Spero possa essere d'aiuto!

+0

Ho provato molte di queste cose, queste cose non funzionano secondo le mie aspettative ..... –

+0

Se puoi essere un po 'più dettagliato su cosa hai provato e come non ha funzionato e aggiungilo al tuo domanda, forse posso aiutare un po 'di più. –

+0

Sto avendo diversi tipi di immagini, per alcune immagini lo sfondo è un po 'molto simile ai capelli che non è possibile per un programma di differenziare tra loro, anche le cose citate non funzionano in tutti i casi .... –

0

Suggerisco di "giocare" con le coordinate del rettangolo (int xOne, int xTwo, int yOne, int yTwo).Usando il tuo codice e queste coordinate 1, 400, 30, 400 ho potuto evitare lo sfondo. (Ho provato a pubblicare le immagini che ho ritagliato correttamente ma ho bisogno di almeno 10 reputazione per farlo)

+1

Questo non fornisce una risposta alla domanda. Per criticare o richiedere chiarimenti da un autore, lascia un commento sotto il loro post - puoi sempre commentare i tuoi post, e una volta che hai [reputazione] sufficiente (http://stackoverflow.com/help/whats-reputation) essere in grado di [commentare qualsiasi post] (http://stackoverflow.com/help/privileges/comment). – Ram

+0

Ciao Ram, mi dispiace se questo non era il posto giusto per postare. Q: Come posso migliorare le prestazioni dell'algoritmo grabCut in modo che possa rilevare solo il viso e i capelli dall'immagine data? La mia risposta: più si avvicina il rettangolo al volto, migliore sarà il risultato. – sp1r0s

+1

Stavo rivedendo il tuo post e ho selezionato il messaggio di sistema generico da visualizzare. Sostanzialmente si dice che questo è più di un commento utile piuttosto una risposta in quanto non abbastanza dettagliata da essere una risposta e chiede di postarla come commento. So che non puoi postarlo come commento perché non hai la reputazione di farlo. Per favore rispondi ad alcune domande che conosci per raccogliere la reputazione e poi prova a commentare o rendere la tua risposta più dettagliata con esempi e immagini come link Converti i link alle immagini aggiungendoli per te. – Ram

-4

La migliore ottimizzazione che può essere eseguita su qualsiasi routine Java è la conversione in una lingua nativa.

2

Un altro approccio, dal momento che hai già rilevato la faccia, è semplicemente scegliere una maschera iniziale migliore per inizializzare GrabCut - ad es. utilizzando un ovale anziché un rettangolo.

  1. rilevare viso rettangolo (come si sta già facendo)
  2. creare una maschera:

    a) creare una nuova immagine nera della stessa dimensione dell'immagine in ingresso

    b) Draw un'ellisse piena di bianco con la stessa altezza, larghezza, posizione superiore e sinistra come rettangolo facciale

  3. Chiama GrabCut conanziché GC_INIT_WITH_RECT:

    Imgproc.grabCut(image, mask, rectangle, bgdModel, fgdModel, 8, Imgproc.GC_INIT_WITH_MASK); 
    

Questo inizializza il primo piano con un modello migliore, perché le facce sono più di rettangolo di forma ovale, quindi dovrebbe includere meno dello sfondo per cominciare.

+0

L'ho usato, questo non sta producendo i risultati desiderati .... –

Problemi correlati