2013-02-11 19 views
6

Mi piacerebbe eseguire una riduzione del colore tramite ridimensionamento del colore.Riduzione della profondità del colore con opencv e LUT

come in questo esempio: enter image description here

la prima immagine è risoluzione CGA, il secondo è EGA, il terzo è HAM. Mi piacerebbe farlo con cv :: LUT perché penso che sia la via migliore per farlo. posso fare con scala di grigi con questo codice:

Mat img = imread("test1.jpg", 0); 
uchar* p; 
Mat lookUpTable(1, 256, CV_8U); 
p = lookUpTable.data; 
for(int i = 0; i < 256; ++i) 
    p[i] = 16 * (i/16) 
LUT(img, lookUpTable, reduced); 

originale: enter image description here

colore ridotto: enter image description here

ma se provo a che fare con il colore ottengo strano risultato ..

enter image description here

con questo codice:

imgColor = imread("test1.jpg"); 
Mat reducedColor; 
int n = 16; 
for (int i=0; i<256; i++) { 
    uchar value = floor(i/n) * n; 
    cout << (int)value << endl; 
    lut.at<Vec3b>(i)[2]= (value >> 16) & 0xff; 
    lut.at<Vec3b>(i)[1]= (value >> 8) & 0xff; 
    lut.at<Vec3b>(i)[0]= value & 0xff; 
} 
LUT(imgColor, lut, reducedColor); 

risposta

3

A questo punto probabilmente si è già passati, ma la radice del problema è che si sta eseguendo uno spostamento di 16 bit su uchar value, che è lungo solo 8 bit. Anche uno spostamento a 8 bit in questo caso è eccessivo, poiché cancellerai tutti i bit nello uchar. Poi c'è il fatto che il cv::LUT documentation afferma esplicitamente che src deve essere un "array di input di elementi a 8 bit", che chiaramente non è il caso nel tuo codice. Il risultato netto è che solo il primo canale dell'immagine a colori (il canale blu) viene trasformato da cv::LUT.

Il modo migliore per aggirare queste limitazioni è dividere le immagini a colori attraverso i canali, trasformare ciascun canale separatamente e quindi unire i canali trasformati in una nuova immagine a colori. Vedere il codice qui sotto:

/* 
Calculates a table of 256 assignments with the given number of distinct values. 

Values are taken at equal intervals from the ranges [0, 128) and [128, 256), 
such that both 0 and 255 are always included in the range. 
*/ 
cv::Mat lookupTable(int levels) { 
    int factor = 256/levels; 
    cv::Mat table(1, 256, CV_8U); 
    uchar *p = table.data; 

    for(int i = 0; i < 128; ++i) { 
     p[i] = factor * (i/factor); 
    } 

    for(int i = 128; i < 256; ++i) { 
     p[i] = factor * (1 + (i/factor)) - 1; 
    } 

    return table; 
} 

/* 
Truncates channel levels in the given image to the given number of 
equally-spaced values. 

Arguments: 

image 
    Input multi-channel image. The specific color space is not 
    important, as long as all channels are encoded from 0 to 255. 

levels 
    The number of distinct values for the channels of the output 
    image. Output values are drawn from the range [0, 255] from 
    the extremes inwards, resulting in a nearly equally-spaced scale 
    where the smallest and largest values are always 0 and 255. 

Returns: 

Multi-channel images with values truncated to the specified number of 
distinct levels. 
*/ 
cv::Mat colorReduce(const cv::Mat &image, int levels) { 
    cv::Mat table = lookupTable(levels); 

    std::vector<cv::Mat> c; 
    cv::split(image, c); 
    for (std::vector<cv::Mat>::iterator i = c.begin(), n = c.end(); i != n; ++i) { 
     cv::Mat &channel = *i; 
     cv::LUT(channel.clone(), table, channel); 
    } 

    cv::Mat reduced; 
    cv::merge(c, reduced); 
    return reduced; 
} 
+1

da dove posso ottenere la comprensione completa e l'uso di LUT? Ho visto la documentazione di Opencv ma è solo rigorosa per la sintassi. Cosa si fa se si desidera salvare i valori di questa immagine LUT e si desidera applicarlo su altri valori uguali – AHF

+1

Lo scopo di LUT è di cambiare i colori di un'immagine in base a una tabella di ricerca. Questo può avere vari scopi, come la riduzione della risoluzione del colore come fase di pre-elaborazione nella segmentazione dell'immagine. Consulta questo articolo di Wikipedia per ulteriori informazioni: http://en.wikipedia.org/wiki/Colour_look-up_table – xperroni

+0

Per applicare la stessa trasformazione LUT a immagini diverse, puoi modificare la funzione 'colorReduce()' in alto per accettare un fare riferimento a una tabella di ricerca come argomento, quindi calcolare la tabella in una chiamata separata a 'lookupTable()' o qualsiasi altro metodo che si ritenga appropriato. – xperroni

0

Sia i e n sono numeri interi, quindi i/n è un numero intero. Forse lo vuoi convertire in double ((double)i/n) prima di prendere la parola e moltiplicare per n?

+0

come spiega la tua risposta tutto ciò che è blu? – nkint

+0

quanti byte è quel uchar? assumi almeno 3 byte; anche se è wide char, dovrebbe comunque essere 2 byte, non 3 o più. –

Problemi correlati