2016-07-17 71 views
7

Ho appena letto il tutorial this e ho provato questo esempio. Così ho scaricato un video dal web per i miei test. Tutto quello che devo fare è modificare i valori RGB in se le condizioniCome filtrare accuratamente il valore RGB per l'effetto chroma-key

Ecco il codice di esempio da esempio

computeFrame: function() { 
    this.ctx1.drawImage(this.video, 0, 0, this.width, this.height); 
    let frame = this.ctx1.getImageData(0, 0, this.width, this.height); 
    let l = frame.data.length/4; 

    for (let i = 0; i < l; i++) { 
     let r = frame.data[i * 4 + 0]; 
     let g = frame.data[i * 4 + 1]; 
     let b = frame.data[i * 4 + 2]; 
     if (g > 100 && r > 100 && b < 43) 
     frame.data[i * 4 + 3] = 0; 
    } 
    this.ctx2.putImageData(frame, 0, 0); 
    return; 
    } 

Nell'esempio esercitazione suo filtraggio fuori giallo (non gialla credo) di colore. Il video di esempio che ho scaricato utilizza lo sfondo verde. Quindi ho ottimizzato il valore di rgb in condizione per ottenere i risultati desiderati

Dopo diversi tentativi, sono riuscito a ottenere questo.

enter image description here

Ora quello che voglio sapere è come faccio a filtrare accuratamente schermo verde (o di qualsiasi altro schermo) perfettamente senza indovinare. O modificare i valori in modo casuale.

Con solo indovinare ci vogliono ore per farlo perfettamente nel modo giusto. E questo è solo un esempio con un'applicazione del mondo reale. Può volerci forse di più.

NOTA: L'esempio sta lavorando in Firefox per ora ..

risposta

3

Probabilmente solo bisogno di un algoritmo migliore. Eccone uno, non è perfetto, ma puoi modificarlo molto più facilmente.

just do it bro

In pratica ti basta un colorpicker, e scegliere i valori chiare e più scure dal video (mettendo i valori RGB nella l_ e d_ variabili rispettivamente). È possibile regolare un po 'la tolleranza se necessario, ma ottenere i valori l_ e r_ in modo corretto selezionando aree diverse con il selettore di colori darà una chiave migliore.

let l_r = 131, 
    l_g = 190, 
    l_b = 137, 

    d_r = 74, 
    d_g = 148, 
    d_b = 100; 

let tolerance = 0.05; 

let processor = { 
    timerCallback: function() { 
    if (this.video.paused || this.video.ended) { 
     return; 
    } 
    this.computeFrame(); 
    let self = this; 
    setTimeout(function() { 
     self.timerCallback(); 
     }, 0); 
    }, 

    doLoad: function() { 
    this.video = document.getElementById("video"); 
    this.c1 = document.getElementById("c1"); 
    this.ctx1 = this.c1.getContext("2d"); 
    this.c2 = document.getElementById("c2"); 
    this.ctx2 = this.c2.getContext("2d"); 
    let self = this; 
    this.video.addEventListener("play", function() { 
     self.width = self.video.videoWidth; 
     self.height = self.video.videoHeight; 
     self.timerCallback(); 
     }, false); 
    }, 

    calculateDistance: function(c, min, max) { 
     if(c < min) return min - c; 
     if(c > max) return c - max; 

     return 0; 
    }, 

    computeFrame: function() { 
    this.ctx1.drawImage(this.video, 0, 0, this.width, this.height); 
    let frame = this.ctx1.getImageData(0, 0, this.width, this.height); 
     let l = frame.data.length/4; 

    for (let i = 0; i < l; i++) { 
     let _r = frame.data[i * 4 + 0]; 
     let _g = frame.data[i * 4 + 1]; 
     let _b = frame.data[i * 4 + 2]; 

     let difference = this.calculateDistance(_r, d_r, l_r) + 
         this.calculateDistance(_g, d_g, l_g) + 
         this.calculateDistance(_b, d_b, l_b); 
     difference /= (255 * 3); // convert to percent 
     if (difference < tolerance) 
     frame.data[i * 4 + 3] = 0; 
    } 
    this.ctx2.putImageData(frame, 0, 0); 
    return; 
    } 
}; 
// :/ 
+0

veramente bello esempio .. ma sto ancora avendo problemi capire ..Visually sembra la stessa .. Come è possibile determinare le tonalità scure e chiare, cercando in RGBvalues. –

+0

@Akash Kumar verso il centro è praticamente sempre più luminoso rispetto agli angoli del greenscreen. Se c'è ancora del verde che non viene filtrato, il colore si abbassa e lo usa come nuova luce o buio. Potrebbero essere necessari alcuni passaggi, ma dovrebbero essere necessari solo pochi minuti. – Entity

+0

capito .. necessario per regolare un po 'la tolleranza .. –

1

Se le prestazioni non sono importanti, è possibile lavorare in un altro spazio colore, ad es. HSV. Potresti usare il pixel in alto a sinistra come riferimento.

È possibile confrontare il valore di tonalità del punto di riferimento con il valore di tonalità di altri pixel ed escludere tutti i pixel che superano una determinata soglia e le aree scure e chiare utilizzando la saturazione e il valore.

Questo come mai non elimina completamente il sanguinamento del colore, potrebbe essere necessario correggere il colore/desaturazione.

function rgb2hsv() { 
    var rr, gg, bb, 
     r = arguments[0]/255, 
     g = arguments[1]/255, 
     b = arguments[2]/255, 
     h, s, 
     v = Math.max(r, g, b), 
     diff = v - Math.min(r, g, b), 
     diffc = function(c){ 
      return (v - c)/6/diff + 1/2; 
     }; 

    if (diff == 0) { 
     h = s = 0; 
    } else { 
     s = diff/v; 
     rr = diffc(r); 
     gg = diffc(g); 
     bb = diffc(b); 

     if (r === v) { 
      h = bb - gg; 
     }else if (g === v) { 
      h = (1/3) + rr - bb; 
     }else if (b === v) { 
      h = (2/3) + gg - rr; 
     } 
     if (h < 0) { 
      h += 1; 
     }else if (h > 1) { 
      h -= 1; 
     } 
    } 
    return { 
     h: Math.round(h * 360), 
     s: Math.round(s * 100), 
     v: Math.round(v * 100) 
    }; 
} 


let processor = { 
    timerCallback: function() { 
    if (this.video.paused || this.video.ended) { 
     return; 
    } 
    this.computeFrame(); 
    let self = this; 
    setTimeout(function() { 
     self.timerCallback(); 
     }, 0); 
    }, 

    doLoad: function() { 
    this.video = document.getElementById("video"); 
    this.c1 = document.getElementById("c1"); 
    this.ctx1 = this.c1.getContext("2d"); 
    this.c2 = document.getElementById("c2"); 
    this.ctx2 = this.c2.getContext("2d"); 
    let self = this; 
    this.video.addEventListener("play", function() { 
     self.width = self.video.videoWidth/2; 
     self.height = self.video.videoHeight/2; 
     self.timerCallback(); 
     }, false); 
    }, 

    computeFrame: function() { 
    this.ctx1.drawImage(this.video, 0, 0, this.width, this.height); 
    let frame = this.ctx1.getImageData(0, 0, this.width, this.height); 
     let l = frame.data.length/4; 


    let reference = rgb2hsv(frame.data[0], frame.data[1], frame.data[2]); 

    for (let i = 0; i < l; i++) { 
     let r = frame.data[i * 4 + 0]; 
     let g = frame.data[i * 4 + 1]; 
     let b = frame.data[i * 4 + 2]; 
     let hsv = rgb2hsv(r, g, b); 

     let hueDifference = Math.abs(hsv.h - reference.h); 

     if(hueDifference < 20 && hsv.v > 50 && hsv.s > 50) { 
     frame.data[i * 4 + 3] = 0; 
     } 


    } 
    this.ctx2.putImageData(frame, 0, 0); 
    return; 
    } 
}; 
+0

Le prestazioni contano. ma farò un tentativo .. comunque. –

Problemi correlati