Frage

Ich habe Probleme eine rohe YUV-Datei anzeigt, die es in NV12-Format ist.

Ich kann einen ausgewählten Rahmen angezeigt wird, ist es jedoch nach wie vor hauptsächlich in schwarz und weiß mit bestimmten Farben rosa und grün ist.

Hier ist, wie meine Ausgabe aussieht alt text

Wie auch immer, hier ist, wie mein Programm funktioniert. (Dies ist in Kakao / Objective-c getan, aber ich brauche Ihre kompetente Beratung über Programmalgorithmus, nicht auf Syntax.)

Vor der Ausführung zu programmieren, die YUV-Datei in einer binären Datei mit dem Namen „test.yuv“ gespeichert. Die Datei ist in NV12-Format, dh der Y-Plan zuerst gespeichert ist, dann wird der UV-Plan verschachtelt ist. Meine Dateiextrahierung hat kein Problem, weil ich viel testings auf es getan hat.

Während der Initiation, erstelle ich eine Lookup-Tabelle, die binäre / 8 Bisse konvertieren / ein Byte / Zeichen in respektiert Y, U, V Float-Werte

Für die Y-Ebene dies ist mein Code

-(void)createLookupTableY //creates a lookup table for converting a single byte into a float between 0 and 1
{
    NSLog(@"YUVFrame: createLookupTableY");
    lookupTableY = new float [256];

    for (int i = 0; i < 256; i++)
    {
        lookupTableY[i] = (float) i /255;
        //NSLog(@"lookupTableY[%d]: %f",i,lookupTableY[i]);//prints out the value of each float
    }
}

Die U-Ebene Lookup-Tabelle

-(void)createLookupTableU //creates a lookup table for converting a single byte into a float between 0 and 1
{
    NSLog(@"YUVFrame: createLookupTableU");
    lookupTableU = new float [256];

    for (int i = 0; i < 256; i++)
    {
        lookupTableU[i] =  -0.436 + (float) i / 255* (0.436*2);
        NSLog(@"lookupTableU[%d]: %f",i,lookupTableU[i]);//prints out the value of each float
    }
}

Und die V Nachschlagetabelle

-(void)createLookupTableV //creates a lookup table for converting a single byte into a float between 0 and 1
{
    NSLog(@"YUVFrame: createLookupTableV");
    lookupTableV = new float [256];

    for (int i = 0; i < 256; i++)
    {
        lookupTableV[i] =  -0.615 + (float) i /255 * (0.615*2);
        NSLog(@"lookupTableV[%d]: %f",i,lookupTableV[i]);//prints out the value of each float
    }
}

nach diesem Punkt zu extrahieren ich die Y & UV-Plan und speichere sie in zwei Puffer, yBuffer & uvBuffer

an dieser Stelle versuche ich die YUV-Daten zu konvertieren und es in einen RGB-Puffer-Array gespeichert namens „Frameimage“

-(void)sortAndConvert//sort the extracted frame data into an array of float
{
    NSLog(@"YUVFrame: sortAndConvert");
    int frameImageCounter = 0;
    int pixelCounter = 0;
    for (int y = 0; y < YUV_HEIGHT; y++)//traverse through the frame's height
    {
        for ( int x = 0; x < YUV_WIDTH; x++)//traverse through the frame's width
        {

            float Y = lookupTableY [yBuffer [y*YUV_WIDTH + x] ];
            float U = lookupTableU [uvBuffer [ ((y / 2) * (YUV_WIDTH / 2) + (x/2)) * 2  ] ]; 
            float V = lookupTableV [uvBuffer [  ((y / 2) * (YUV_WIDTH / 2) + (x/2)) * 2 + 1] ];

            float RFormula = Y + 1.13983f * V;
            float GFormula = Y - 0.39465f * U - 0.58060f * V;
            float BFormula = Y + 2.03211f * U;

             frameImage [frameImageCounter++] = [self clampValue:RFormula];
             frameImage [frameImageCounter++] = [self clampValue:GFormula];
             frameImage [frameImageCounter++] = [self clampValue:BFormula];

        }
    }

}

Dann habe ich versucht, das Bild in OpenGl

zu ziehen
-(void)drawFrame:(int )x
{

    GLuint texture;

    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, YUV_WIDTH, YUV_HEIGHT, 0, GL_RGB, GL_FLOAT, frameImage);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, texture);
    glRotatef( 180.0f, 1.0f, 0.0f, 0.0f );

    glBegin( GL_QUADS );
    glTexCoord2d(0.0,0.0); glVertex2d(-1.0,-1.0);
    glTexCoord2d(1.0,0.0); glVertex2d(+1.0,-1.0);
    glTexCoord2d(1.0,1.0); glVertex2d(+1.0,+1.0);
    glTexCoord2d(0.0,1.0); glVertex2d(-1.0,+1.0);
    glEnd();

    glFlush();
}

also im Grunde das ist mein Programm in einer Nussschale. im wesentlichen gelesen i die binären Dateien YUV, speichert alle Daten in einem Array char Puffer. i dann diese Werte in ihren respektierten YUV Float-Werte übersetzen.

Dies ist, wo ich die Fehler denken könnten: in der Y-Lookup-Tabelle I die Y-Ebene auf [0,1], in der U-Ebene zu standardisieren standardisierte ich die Werte zwischen [-0.435,0.436] und in dem V Ebene standardisiert ich es bewteen [-0.615,0.615]. Ich tat dies, weil diejenigen, die YUV-Wertebereiche nach wikipedia sind.

Und die YUV auf RGB-Formel ist die gleiche Formel, die aus der Wikipedia. Ich habe auch verschiedene andere Formeln versucht, und dies ist die einzige Formel, die die groben Aussichten des Rahmens gibt. Wer könnte wagen zu erraten, warum mein Programm ist nicht korrekt die YUV-Rahmendaten. Ich denke, es ist etwas mit meiner Standardisierungstechnik zu tun, aber es scheint in Ordnung für mich.

Ich habe eine Menge von testings getan, und ich bin 100% sicher, dass der Fehler verursacht wird, durch durch Tabelle nachschlagen. Ich glaube nicht, meine Einstellung Formeln korrekt sind.

  

Ein Hinweis an alle, die das Lesen ist   diese. Für die längste Zeit, mein Rahmen   war nicht richtig, weil ich die Anzeige   war nicht in der Lage die Rahmendaten zu extrahieren,   richtig.

     

Als ich zuerst nach Programm gestartet, war ich   unter dem Eindruck, dass in einem Clip von   30 Rahmen sagen, alle 30 Daten Y planar   wird zunächst in der Datendatei geschrieben,   gefolgt dann durch UV-Ebene Daten.

     

Was ich herausgefunden habe, durch Versuch und   Fehler war, dass für eine YUV-Datendatei,   speziell NV12, ist die Datendatei   in der folgenden Art und Weise gespeichert

     

Y (1) UV (1) Y (2) UV (2) ... ...

@nschmidt

Ich änderte meinen Code zu dem, was Sie vorgeschlagen

float U = lookupTableU [uvBuffer [ (y * (YUV_WIDTH / 4) + (x/4)) * 2 ] ]
float V = lookupTableU [uvBuffer [ (y * (YUV_WIDTH / 4) + (x/4)) * 2 + 1] ]

und das ist das Ergebnis, das ich bekommen alt text

Hier ist die Druckleitung von der Konsole. Ich bin die Werte für Y, U, V ausdrucken und RGB-Wert, der in der Frameimage Array übersetzt und gespeichert werden auf

YUV: [0.658824, -0,022227, -,045824] RGBFinal: [0.606593,0.694201,0.613655]

YUV: [0.643137, -0,022227, -,045824] RGBFinal: [0.590906,0.678514,0.597969]

YUV: [0.607843, -0,022227, -,045824] RGBFinal: [0.555612,0.643220,0.562675]

YUV: [0.592157, -0,022227, -,045824] RGBFinal: [0.539926,0.627534,0.546988]

YUV: [0.643137,0.025647,0.151941] RGBFinal: [0.816324,0.544799,0.695255]

YUV: [0.662745,0.025647,0.151941] RGBFinal: [0.835932,0.564406,0.714863]

YUV: [0.690196,0.025647,0.151941] RGBFinal: [0.863383,0.591857,0.742314]

Update 13. Juli 2009

Das Problem wurde schließlich dank der Empfehlung gelöst von nschmidt . Es stellt sich heraus, dass meine YUV-Datei in YUV tatsächlich war 4: 1: 1-Format. Ich war ursprünglich gesagt, dass es in YUV NV12 Format ist. Wie auch immer, ich möchte meine Ergebnisse mit Ihnen teilen.

Hier wird ausgegeben

alt text

und mein Code für decode ist wie folgt

        float Y = (float) yBuffer [y*YUV_WIDTH + x] ;
        float U = (float) uvBuffer [ ((y / 2) * (YUV_WIDTH  / 2) + (x/2))   ] ; 
        float V = (float) uvBuffer [  ((y / 2) * (YUV_WIDTH  / 2) + (x/2))  + UOffset] ;

        float RFormula = (1.164*(Y-16) + (1.596* (V - 128) ));
        float GFormula = ((1.164 * (Y - 16)) - (0.813 * ((V) - 128)) - (0.391 * ((U) - 128)));
        float BFormula = ((1.164 * (Y - 16)) + (2.018 * ((U) - 128)));


        frameImage [frameImageCounter] = (unsigned char)( (int)[self clampValue:RFormula]);
        frameImageCounter ++;
        frameImage [frameImageCounter] =  (unsigned char)((int)[self clampValue:GFormula]);
        frameImageCounter++;
        frameImage [frameImageCounter] = (unsigned char)((int) [self clampValue:BFormula]);
        frameImageCounter++;



GLuint texture;

glGenTextures(1, &texture);
glEnable(GL_TEXTURE_2D);

glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, YUV_WIDTH, YUV_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, frameImage);

//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE_SGIS);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE_SGIS);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);

glRotatef( 180.0f, 1.0f, 0.0f, 0.0f );

glBegin( GL_QUADS );
glTexCoord2d(0.0,0.0); glVertex2d(-1.0,-1.0);
glTexCoord2d(1.0,0.0); glVertex2d(+1.0,-1.0);
glTexCoord2d(1.0,1.0); glVertex2d(+1.0,+1.0);
glTexCoord2d(0.0,1.0); glVertex2d(-1.0,+1.0);
glEnd();

NSLog(@"YUVFrameView: drawRect complete");
glFlush();

Im Wesentlichen habe ich NSData für die RAW-Datei-Extraktion. in einem Array char Puffer gespeichert. Für YUV auf RGB-Konvertierung, verwendete ich die obige Formel, danach geklemmt ich die Werte auf [0: 255]. dann habe ich eine 2DTexture in OpenGL für die Anzeige.

Wenn Sie also YUV auf RGB in Zukunft Umwandlung sind, verwenden Sie die Formel von oben. Wenn sich die YUV auf RGB Umrechnungsformel aus der früheren Post verwenden, dann müssen Sie aus den Werten für RGB die Textur in GL_FLOAT angezeigt werden eingespannt zwischen [0: 1]

War es hilfreich?

Lösung

Nächster Versuch :) Ich glaube, Sie sind UV-Puffer nicht verschachtelt ist. Es sieht aus wie die U-Werte kommen zuerst und dann die Anordnung von V-Werten. Ändern der Zeilen

unsigned int voffset = YUV_HEIGHT * YUV_WIDTH / 2;
float U = lookupTableU [uvBuffer [ y * (YUV_WIDTH / 2) + x/2] ]; 
float V = lookupTableV [uvBuffer [ voffset + y * (YUV_WIDTH / 2) + x/2] ];

könnte darauf hindeuten, ob dies wirklich der Fall ist.

Andere Tipps

Ich glaube, du Adressierung falsch U und V-Werte. Anstatt:

float U = lookupTableU [uvBuffer [ ((y / 2) * (x / 2) + (x/2)) * 2  ] ]; 
float V = lookupTableV [uvBuffer [  ((y / 2) * (x / 2) + (x/2)) * 2 + 1] ];

Es sollte etwas entlang der Linien von

sein
float U = lookupTableU [uvBuffer [ ((y / 2) * (YUV_WIDTH / 2) + (x/2)) * 2  ] ]; 
float V = lookupTableV [uvBuffer [  ((y / 2) * (YUV_WIDTH / 2) + (x/2)) * 2 + 1] ];

Das Bild sieht aus wie Sie haben 4: 1: 1-Format. Sie sollten Ihre Zeilen

ändern
float U = lookupTableU [uvBuffer [ (y * (YUV_WIDTH / 4) + (x/4)) * 2 ] ]
float V = lookupTableU [uvBuffer [ (y * (YUV_WIDTH / 4) + (x/4)) * 2 + 1] ]

Vielleicht können Sie das Ergebnis veröffentlichen, um zu sehen, was sonst falsch ist. Ich finde es immer schwer, darüber nachzudenken. Es ist viel einfacher, dies iterativ zu nähern.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top