Compressione rapida e senza perdita di flusso video

15

Ho un video proveniente da una telecamera fissa. Sia la risoluzione sia l'FPS sono piuttosto alti. I dati che ottengo sono in formato Bayer e utilizzano 10 bit per pixel. Poiché sulla mia piattaforma non è presente un tipo di dati a 10 bit, i dati originali vengono archiviati in memoria utilizzando parole a 16 bit. Voglio implementare una sorta di compressione senza perdita dei dati prima di trasmetterli su una rete.

  • La fotocamera non si muove, quindi grandi parti di fotogrammi consecutivi quasi identico - ma ancora non completamente, a causa dell'inevitabile rumore (il denoising non è un'opzione, in quanto dovrebbe essere privo di perdite e non dovrebbe "perdere" nemmeno il rumore).
  • A causa dell'elevato FPS, anche le parti che cambiano non cambiano molto tra due frame consecutivi.
  • Tuttavia, sembra che anche la fotocamera tremoli leggermente. Molto poco, ma ancora, anche gli oggetti fissi non sono completamente così nello spazio dell'immagine.
  • La compressione deve essere eseguita al volo, quindi non posso raccogliere molto di fotogrammi e li comprime tutti insieme, ma posso guardare indietro 1 fotogramma e usarlo come riferimento.

Sulla base di quanto sopra, il mio primo pensiero è stato quello di impacchettare i dati, in modo che quei 6 bit ridondanti non venissero sprecati per ogni parola. Tuttavia, ho pensato che se usassi qualche codifica entropica (per esempio Huffman ecc.), Quella ridondanza sarebbe automaticamente presa in considerazione, quindi non è necessario alcun imballaggio aggiuntivo. Quindi ho fatto quanto segue:

  • Ha preso la differenza binaria tra due fotogrammi consecutivi. L'originale l'intervallo di dati era 0 ~ 1023 (ad esempio 10 bit senza segno). Dati di differenza diventa firmato e l'intervallo aumenta a -1023 ~ 1023, ma i dati la variazione (o qual è il termine matematico corretto) diventa molto meno rispetto ai dati originali, infatti, la maggior parte dei valori non lo sono sorprendentemente, vicino a zero.
  • Codifica di riso applicata alla differenza. Da quello che capisco, questo sembra una buona scelta per set di dati per lo più di piccole dimensioni numeriche valori.

Questo mi dà una riduzione di circa il 60% delle dimensioni per i frame 1280x720 e il mio sistema di test (Linux in VirtualBox su un singolo core) può eseguire circa 40 compressioni al secondo (senza molta ottimizzazione). Non così bello, ma ragionevole, credo (o è?).

Ci sono modi migliori? Qualche errore comune che ho fatto? Qualche passo generale che ho perso? È possibile utilizzare i fotogrammi con una risoluzione più alta in un secondo momento - dovrei aspettarmi migliori tassi di compressione per telai di dimensioni maggiori?

UPD .:

  • Ho usato questa libreria per la codifica Rice. La libreria è molto lenta (l'autore stesso lo descrive come qualcosa per l'apprendimento piuttosto che per l'uso reale), ad esempio legge e scrive bit uno alla volta nei loop, che uccide le prestazioni. Inizialmente mi ha dato solo 20 FPS, dopo un'ottimizzazione molto semplice è diventato 40 FPS (come riportato sopra), in seguito l'ho ottimizzato ancora, è diventato 80. Quello è su un singolo core i7 senza vettorizzazione.
  • Per quanto riguarda la vettorizzazione, però, sfortunatamente non riuscivo a pensare a un modo per vettorializzare il codice Rice (non so nemmeno se fosse possibile) - non riuscivo a trovare alcun dato sul codice Rice, cosa potevo trovare su Huffman il codice suggerisce che è sequenziale e non può essere vettorizzato in modo efficiente, che può essere applicato al codice Rice e ad altri codici a lunghezza variabile).
  • Ho anche provato un approccio completamente diverso: dividere i dati in piccoli pezzi (ad esempio, come 64 pixel ciascuno) e utilizzare la semplice soppressione dello zero . Troviamo il numero più grande in un blocco, scriviamo il numero di bit necessari per rappresentarlo all'inizio del blocco (sono necessari 4 bit aggiuntivi per quello, nel mio caso), quindi riduciamo tutti i numeri nel blocco allo stesso numero di bit. Mi aspettavo che il tasso di compressione fosse cattivo, ma se i pezzi sono piccoli, molti di loro non avranno picchi di rumore, quindi la loro differenza binaria può essere ridotta a qualcosa come 4 ~ 6 bit per valore, ed è stato, infatti, solo circa il 5% in più rispetto a quello del codice Rice, pur essendo circa il doppio (ad es. 160 FPS per il mio caso). Ho provato a vettorializzare, ma mi piace succhiare la vettorizzazione, quindi forse a causa di ciò ho potuto ottenere solo circa x 1,8 di ulteriore accelerazione.

Poiché i numeri negativi non hanno zero iniziali, ho applicato la codifica a zigzag dopo la differenza binaria e prima della soppressione del riso / zero .

    
posta Headcrab 04.07.2016 - 07:17
fonte

2 risposte

4

Hai una previsione temporale, ma non spaziale. Per una compressione migliore al costo della velocità, dovresti essere in grado di utilizzare i pixel sopra e a sinistra del pixel corrente nel fotogramma corrente come predittori, nonché il pixel nella stessa posizione nel fotogramma precedente. Il motivo per il solo guardare in alto a sinistra è lo stesso del motivo per il solo guardare il frame precedente; vuoi basarti solo sui dati che hai già decodificato e limitarne la quantità da conservare.

I codici riso sono probabilmente un buon compromesso tra efficienza e velocità, ma un codice Huffman statico (precalcolato da te su un campione di dati video) potrebbe essere più efficiente e altrettanto veloce.

Per quanto riguarda la velocità, assicurati che il tuo codice ottenga vettorializzato - utilizzando i flag di compilazione e i modelli di codice corretti per consentire al compilatore di auto-vectorize, o scrivendo a mano il codice per usare il vettore intrinsics o assembly.

Infine, è possibile ridurre fino a 8 bit per pixel? Ovviamente questo lascia il regno di "lossless", ma non solo ridurrebbe le dimensioni del tuo output compresso, ma anche, con il codice vettoriale, potrebbe aumentare il throughput fino a 2x.

    
risposta data 04.07.2016 - 11:30
fonte
0

Probabilmente ti servirà meglio utilizzando le implementazioni esistenti di compressione e decompressione. La tua implementazione esistente sembra simile al HuffYUV codec, quindi potrebbe valere la pena provarlo per vedere se funziona abbastanza bene per te .

    
risposta data 05.07.2016 - 09:41
fonte

Leggi altre domande sui tag