Domanda

Sto avendo problemi di visualizzazione di un raw YUV file che è in NV12 formato.

Posso visualizzare un fotogramma selezionato, tuttavia, è ancora prevalentemente in bianco e nero, con alcune sfumature del rosa e del verde.

Ecco come la mia uscita sembra alt text

Comunque, qui è come il mio programma funziona.(Questo viene fatto al cacao/objective-c, ma ho bisogno della tua consulenza di esperti per il programma di algoritmo, non sulla sintassi.)

Prima dell'esecuzione del programma, il file YUV è memorizzato in un file binario di nome "prova.yuv".Il file è in NV12 formato, il che significa Y piano viene prima memorizzato, poi UV piano è interlacciato.Il mio file di estrazione ha nessun problema, perché ho fatto un sacco di test su di esso.

Nella fase di avvio, ho creato una tabella di ricerca che la conversione binario/8 morsi/byte/caratteri in rispettate Y, U, V valori float

Per la Y questo è il mio codice

-(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
    }
}

U Aereo tabella di ricerca

-(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
    }
}

E la V (look-up table

-(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
    }
}

dopo questo punto, ho estratto la Y & UV piano e memorizzarli in due buffer, yBuffer & uvBuffer

a questo punto, provo a convertire i dati YUV e memorizzati in un RGB buffer array chiamato "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];

        }
    }

}

poi ho provato a disegnare l'Immagine in OpenGl

-(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();
}

quindi, in pratica questo mio programma in un guscio di noce.essenzialmente ho letto il binario i file YUV, che memorizza tutti i dati in un array di char buffer.ho poi tradurre questi valori in loro rispettato YUV valori float.

Questo è dove penso che l'errore potrebbe essere:Y tabella di ricerca ho standardizzare il Y a [0,1], in U aereo che mi standardizzate valori tra [-0.435,0.436], e nel V piano mi standardizzato tra [-0.615,0.615].Ho fatto questo perché quelle sono le YUV valore varia secondo wikipedia.

E da YUV a RGB, la formula è la stessa formula da Wikipedia.Ho provato anche varie altre formule, e questa è l'unica formula che fornisca l'outlook del telaio.Chiunque può avventurarsi a indovinare perché il mio programma non visualizza correttamente il YUV frame di dati.Penso che sia qualcosa a che fare con il mio normazione tecnica, ma sembra che va bene per me.

Ho fatto un sacco di prove, e sono sicuri al 100% che l'errore è causato dal look up table.Non credo che la mia impostazione di formule sono corrette.

Una nota per chi legge questo.Per lungo tempo, il mio telaio non veniva visualizzato correttamente perché mi non era in grado di estrarre i dati di telaio correttamente.

Quando ho iniziato a programmare, mi è stato sotto l'impressione che in una clip di dire 30 fotogrammi, 30 Y planare dati prima vengono scritti nel file di dati, seguita poi da UV piano dati.

Quello che ho scoperto attraverso la prova e l'errore è stato quello di un YUV file di dati, in particolare NV12, il file di dati è memorizzati nel seguente modo

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

@nschmidt

Ho cambiato il mio codice di quello che hai suggerito

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

e questo è il risultato che ottengo alt text

ecco la riga di stampa dalla console.io sono di stampare i valori di Y, U, V e Valore RGB che vengono tradotti e memorizzati nell'array frameImage

YUV:[0.658824,-0.022227,-0.045824] RGBFinal:[0.606593,0.694201,0.613655]

YUV:[0.643137,-0.022227,-0.045824] RGBFinal:[0.590906,0.678514,0.597969]

YUV:[0.607843,-0.022227,-0.045824] RGBFinal:[0.555612,0.643220,0.562675]

YUV:[0.592157,-0.022227,-0.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]

Aggiornamento 13 Luglio 2009

Il problema è stato finalmente risolto, grazie per la raccomandazione nschmidt .Si scopre che il mio file YUV era in realtà in YUV 4:1:1 formato.Mi è stato originariamente detto che era in YUV NV12 formato.Comunque, vorrei condividere i miei risultati con voi.

Qui è uscita

alt text

e il mio codice per decodificare è come indicato di seguito

        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();

in sostanza, ho usato NSData per i file raw di estrazione.memorizzati in un array di char buffer.Per la conversione da YUV a RGB, ho usato la formula sopra, poi l'ho bloccato i valori in [0:255].poi ho usato un 2DTexture in OpenGL per la visualizzazione.

Quindi, se si esegue la conversione da YUV a RGB in futuro, utilizzare la formula di cui sopra.Se si sta utilizzando la conversione da YUV a RGB formula precedente post, allora avete bisogno di visualizzare la texture in GL_Float dai valori RGB sono fissati tra [0:1]

È stato utile?

Soluzione

Prossima prova :) Penso che tu abbia uv buffer non è interleaved.Sembra che i valori U di venire prima e quindi la matrice di V valori.Cambiando le linee di

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] ];

potrebbe indicare se questo è davvero il caso.

Altri suggerimenti

Penso che ti stai rivolgendo U e V in modo non corretto.Piuttosto che:

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

Dovrebbe essere qualcosa lungo le linee di

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] ];

L'immagine appare come se sono 4:1:1 formato.Si dovrebbe cambiare il vostro linee di

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

Forse è possibile inviare il risultato a vedere, che cosa è sbagliato.Trovo sempre difficile pensare su di esso.È molto più facile avvicinarsi a questo modo iterativo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top