2013-02-11 107 views
6

我想通過顏色深度縮放來減少顏色。使用opencv和LUT減少顏色深度

喜歡這個例子: enter image description here

第一圖像是CGA分辨率,第二個是EGA,第三是HAM。 我想用cv :: LUT來做,因爲我認爲這是更好的選擇。 我可以做灰度與此代碼:

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

原:enter image description here

退色:enter image description here

,但如果我試圖用顏色做我得到了奇怪的結果..

enter image description here

與此代碼:

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

回答

3

您現在可能已經移動了,但問題的根源在於您正在對uchar value(僅8位長)進行16位移位。在這種情況下,即使是8位的移位也太多了,因爲您將刪除uchar中的所有位。然後有一個事實,cv::LUT documentation明確指出src必須是「8位元素的輸入數組」,在您的代碼中顯然不是這種情況。最終結果是隻有彩色圖像的第一個通道(藍色通道)被cv::LUT轉換。

解決這些限制的最佳方法是在各個通道上分割彩色圖像,分別轉換每個通道,然後將轉換後的通道合併爲一個新的彩色圖像。見下面的代碼:

/* 
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

從哪裏我可以得到LUT的完整理解和使用?我看到了opencv文檔,但它對語法非常嚴格。如果要保存此「LUT圖像」的值並想將其應用於其他相同的值,您該做什麼 – AHF 2014-05-19 22:06:16

+1

LUT的目的是根據查找表更改圖像的顏色。這可能有多種目的,如降低顏色分辨率作爲圖像分割中的預處理步驟。有關其他信息,請參見此維基百科文章:http://en.wikipedia.org/wiki/Colour_look-up_table – xperroni 2014-05-20 02:02:54

+0

至於對不同的圖像應用相同的LUT轉換,您可以修改上面的'colorReduce()'函數以接受引用查找表作爲參數,然後在單獨調用'lookupTable()'或其他您認爲合適的方法的情況下計算表。 – xperroni 2014-05-20 02:04:19

0

in都是整數,因此i/n是整數。也許你想在發言之前將它轉換成雙倍((double)i/n),並乘以n

+0

你的答案如何解釋所有藍色? – nkint 2013-02-11 20:05:10

+0

那個uchar有多少個字節?你至少假設3個字節;即使它是寬字符,它仍然應該是2個字節,而不是3個或更多。 – 2013-02-11 21:30:57