Wie funktionieren die Bewegungsvektoren bei der prädiktiven Codierung für MPEG?

16

In MPEG gibt es einen Prozess, bei dem ein Bild in Makroblöcke aufgeteilt und für jeden dieser Makroblöcke ein Bewegungsvektor berechnet wird. Anschließend senden Sie diese Vektoren zusammen mit den Vorhersagefehlern, um das nächste Bild in der Videosequenz zu rekonstruieren.

Ich versuche zu verstehen, wie das funktioniert. Jedem Makroblock ist ein Bewegungsvektor zugeordnet, der besagt (wenn der Vektor [1,0] ist), dass all the pixels in this block move 1 in the x direction and 0 in the y direction for the next frame. wenn alle Bewegungsvektoren nicht korrekt ausgerichtet sind, Bereiche des Bildes nicht unberücksichtigt bleiben (wie der Bereich, in dem sich der Makroblock befindet) dieser Makroblock war an erster Stelle)?

Ich habe zum Beispiel die folgende Frage gefunden.

Betrachten Sie das folgende Bild zum Zeitpunkt t:

7   7   7   7           
7   7   5   5        
7   5   5   8         
8   8   8   8           
9   9   9   9       
9   9   9   9

Dieses Bild wurde in 2 x 2 Makroblöcke aufgeteilt und die folgenden Bewegungsvektoren wurden gesendet, um es neu zu erstellen:

(0,0)  (0,0)  (0,1)  (-1,1)  (0,0)  (0,0)

Das Bild im vorherigen Zeitschritt, t - 1, sah folgendermaßen aus:

7   7   7   7           
7   7   5   4        
7   7   7   7         
7   5   8   8           
8   9   8   9       
9   9   9   9   

Welche Fehler wurden übertragen?

Wie würden Sie das lösen?

Brieftasche
quelle

Antworten:

5

Um Ihre Verwirrung zu vereinfachen, gibt es zwei Prozesse:

1. Bewegungsschätzung
2. Bewegungskompensation

Bevor wir über die Schätzung sprechen, sollten wir über die Bewegungskompensation sprechen.

, das ist in Block .Imaget(x,y)Blockst[k](x,y)

Die Aufgabe der Bewegungskompensation besteht darin, aus jedem Bereich von zu erzeugen .Blockst[k](x,y)Imaget1(x,y)

Daher ist ein weiterer Block, der nicht unbedingt an der 16x16-Grenze ausgerichtet ist, eine bestmögliche Übereinstimmung.Blockst1[k](x+mx,y+my)

Hier heißt Bewegungsvektoren.mx,my

Wir können den Fehler zwischen dem Ziel und der Referenz als berechnen

Errt[k](x,y)=Blockst[k](x,y)Blockst1[k](x+mx,y+my)

Der Codierer überträgt im Grunde genommen (mit DCT und Quantisierung) und für jeden Block.Errt[k](x,y)(mx,my)[k]

Encoder hat also zwei Aufgaben zu erledigen:

1. Bewegungsschätzung
Der Prozess oder das Schätzen von für jedes so dass minimiert wird, wird als Bewegungsschätzung bezeichnet.mx,my[k]kErrt[k](x,y)

2. Erzeugung eines nach der Bewegungskompensation
Der Vorgang des Konstruierens von aus Bildpixeln und wird als Bewegungskompensation bezeichnet. Das Fehlerbild wird übertragen.Blockst[k](x,y)It(mx,my)[k]

Schließlich kann der Decodierer die Bewegungskompensation unter Verwendung von Moiton-Vektoren und des Fehlerbildes selbst durchführen, um die endgültige Rekonstruktion des Bildes vorzunehmen.

Jetzt erkennen wir ein paar Punkte:

  1. Die Schätzung der besten Bewegung hilft dabei, die zu übertragende Energie zu minimieren und somit die Bits für eine bestimmte Qualität zu optimieren.

  2. Selbst wenn nicht ideal ist oder wenn die Szene eine signifikante Änderung gegenüber dem letzten Bild aufweist, wird immer an den Empfänger gesendet - daher die Rekonstruktion ist immer perfekt (modulo der durch die Quantisierung erzeugte Verlust). Selbst wenn Sie einen suboptimalen Bewegungsvektor haben oder die Redundanz nicht groß ist, ist die Rekonstruktion immer perfekt, wenn auch mit mehr Bits!(mx,my)[k]Errt[k](x,y)

  3. Jeder Block ist für sich bewegungskompensiert - also auch dann, wenn die tatsächlichen Bewegungsvektoren benachbarter Blöcke keinen Einfluss auf die Konstruktion haben. Daher ist es nicht erforderlich, Bewegungsvektoren perfekt auszurichten, damit eine perfekte Rekonstruktion möglich ist.Blockst[k](x,y)

  4. Obwohl es Algorithmen gibt, die klug genug sind, zu erraten, dass, wenn einen Bewegungsvektor die für möglicherweise nur näher daran liegt.Blockst[k](mx,my)[k]Blockst[k+1]

  5. Nehmen wir schließlich an, das nächste Bild ist völlig anders. Möglicherweise ist Energie für .

    Energy(Errt[k](x,y))>Energy(Blockst[k](x,y))

In solchen Fällen ist es möglicherweise empfehlenswerter, den Block direkt ohne Vorhersage zu senden, als die Differenz zu senden. Dies ist auch im Encoder durch eine als INTRA-Block bezeichnete Vorkehrung möglich.

Dipan Mehta
quelle
3

Nein, es hinterlässt keine Löcher, da der Vektor von einem unbekannten Frame (P oder B) zu einem bekannten Frame (I-Frame) wechselt. Es erinnert ein wenig daran, wie eine Bildtransformation berechnet wird - Sie verwenden eine Rücktransformation, um Löcher zu vermeiden.

Andrey Rubshtein
quelle
3

Wie bei vielen Standard-Signalverarbeitungsroutinen ist es auf dem Papier recht einfach und in der Praxis etwas schwierig. Sie haben Ihr Bild in sechs Blöcke mit und . Jeder dieser Blöcke hat Koordinaten bei (wir betrachten die obere linke Ecke von jedem, um seine Position zu identifizieren). Wir haben also jetzt sechs Blöcke anB(i,j)i={0,1,2}j={0,1}(2i,2j)

(0,0) (0,2)
(2,0) (2,2)
(4,0) (4,2)

Ihre berechneten Bewegungsvektoren für jeden Block sindM(i,j)

(0,0) (0,0)
(0,1) (-1,1)
(0,0) (0,0)

Um nun das resultierende Bild zu berechnen, müssen wir zuerst wissen, wo sich jeder Block bewegt hat. Dazu addieren wir einfach die obige Koordinatenmatrix zu ihrer Bewegungsmatrix: . Wir bekommenB(i,j)=B(i,j)+M(i,j)

(0,0) (0,2)
(2,1) (1,3)
(4,0) (4,2)

Um, wie Sie sagten, "Löcher" zu vermeiden, verschieben wir nicht einfach die Blöcke des ursprünglichen Rahmens, um den neuen zu erhalten, sondern nehmen den ursprünglichen als Referenz und fügen die neu berechneten Blöcke ein. Dazu erstellen wir zunächst eine Kopie des Originalrahmens. Wir nehmen dann jedes und ersetzen es durch Pixel des entsprechenden .B(i,j)B(i,j)

Hinweis: Wir sind nicht vor Überlappungen von "in Bewegung" befindlichen Blöcken geschützt (zwei Blöcke werden an überlappende Stellen verschoben). Es gibt Möglichkeiten, damit umzugehen, aber das geht über den Rahmen dieser Antwort hinaus. Im Moment werden Pixel mit einem Block, den wir an ihre Position verschieben, nur neu geschrieben, sodass sie überschrieben werden, selbst wenn zuvor Blöcke dorthin verschoben wurden.

Gehen wir nun Block für Block in der Reihenfolge vor, die Sie in Ihrer Frage angegeben haben, ersetzen wir jedes durch das entsprechende . Wir erhalten den folgenden geschätzten FrameB ( i , j ) F eB(i,j)B(i,j)Fe

7 7 7 7
7 7 5 7
7 7 7 8
7 5 5 8
8 9 8 9
9 9 9 9

Der Fehler wird zwischen dem geschätzten Rahmen und demjenigen gefunden, den wir vorherzusagen versuchen. wird durch dessen wir berechnenF e F E = F - F eEFeFE=FFe

0 0 0 0           
0 0 0 -3        
0 0 0 -1         
0 0 3 0           
0 0 0 0       
0 0 0 0
Phonon
quelle
Während ich denke, dass die Signalverarbeitungs-Community bei weitem der beste Ort ist, um diese Frage zu stellen, brauchen solche Themen und stark involvierte Technologien einen eigenen Raum. Es gibt einen neuen Vorschlag der Q & A-Site Broadcast and Media Technologies. Bitte mach mit und trage bei.
Dipan Mehta
@ DipanMehta Sehr cool! =)
Phonon