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 .