2016-06-09 269 views
2

我試圖將12位RGGB顏色值轉換爲8位RGGB顏色值,但用我目前的方法,它給出了奇怪的結果。將12位顏色值轉換爲8位顏色值C++

從邏輯上講,我認爲簡單地將12位RGGB成8位RGGB會工作,並非常簡單:

// raw_color_array contains R,G1,G2,B in a bayer pattern with each element 
// ranging from 0 to 4096 
for(int i = 0; i < array_size; i++) 
{ 
    raw_color_array[i] /= 16; // 4096 becomes 256 and so on 
} 

然而,在實踐中這其實是行不通的。例如,給出一個帶有水和冰塊的小圖像,您可以看到轉換中實際發生的情況(最右圖)。

enter image description hereenter image description here

爲什麼會出現這種情況?以及如何在左側獲得相同(或接近)的圖像,而是以8位值爲準?謝謝!

編輯:關@MSalters答案,我得到一個更好的圖像質量,但顏色仍然激烈傾斜。我可以研究哪些資源將12位數據轉換爲8位數據,而不會造成質量的嚴重損失?

+2

你有沒有試過在頻道上做直方圖,看看你是否應該贊成某些範圍,而不是廣泛開放的16分方法? –

+0

您是否調試過並觀察過'raw_color_array'的值?他們是你期望的嗎? 'raw_color_array'的數據類型是什麼?你有一個舍入錯誤? –

+0

@ChrisO事實上,我的第一次嘗試是觀察直方圖並猜測正態化方案。它產生的結果幾乎相同,但它不是一個可擴展的解決方案(例如,我需要重新爲14位彩色圖像等進行此過程)。想知道這是否可能,而沒有關注它。 –

回答

1

後您澄清,這12位數據只是一種顏色,這裏是我的答案很簡單:

既然你想它的值轉換爲它的8位等效,這顯然意味着你失去了一些數據( 4位)。這就是爲什麼你沒有得到相同的輸出。

+0

所討論的12位實際上代表** 1 **顏色的12位顏色值。在我的情況下,有2^12個可能的紅色值,我想將它轉換爲2^8個可能的紅色值。每個特定元素只代表一種顏色,並且顏色以紅色綠色紅色第一行的拜耳模式排列,綠色藍色綠色第二行 –

+0

無論您打算使用多少位。我的答案是,如果你將有不同的範圍或轉換,你需要計算該目標範圍的比例。該公式已在我的答案中提出。如果您想將2^12位轉換爲2^8位,如您所說只代表一種顏色。然後獲得儘可能高的紅色值並分割。 24(2X12)/ 16(2^8)= 1.5 實際值/1.5實際轉換爲2^8 ex。 24/1.5 = 16這給你2^8中的最高數字 – winux

+0

我不明白你爲什麼寫24(2 * 12)/ 16(2^8)= 1.5。如果我想計算12位的最大最大值除以最高8位的最大值,是不是'4096(2^12)/ 256(2^8)= 16'。而16是我在代碼示例中使用的內容,我在OP –

0

澄清後: 如果你想保留實際的顏色值! 在12位圖像中應用去鑲嵌,然後將結果數據縮放到8位。因此,與以前的方法相比,由於去鑲嵌造成的顏色損失會較少。

0

你說你的12位代表一種顏色的2^12位。這是不正確的。圖像中有紅色,綠色和藍色。看直方圖。我在命令行中使用ImageMagick的做這樣的:

convert cells.jpg histogram:png:h.png 

enter image description here

如果你想每像素8位,而不是試圖一味/靜態分配3位綠色,2位紅和3從藍色到藍色,使用8位調色板可能會更好,因此您可以使用250種以上顏色的所有變體,而不僅限於8種藍色,4種紅色和8種綠色。所以,像這樣:

convert cells.jpg -colors 254 PNG8:result.png 

這裏是原來旁邊的結果:

enter image description hereenter image description here

上面的過程被稱爲「量化」,如果你想實現它C/C++,有一個寫法here

+0

如果RGB位模式爲RGB 444,除以16並重新解釋結果爲RGB323將丟棄所有4個藍色位並將原始綠色通道的3個最低位重新解釋爲藍色。不,這絕對不會發生。 – MSalters

+0

我只使用JPG,所以我實際上可以顯示圖像,實際上圖像是'.NEF'文件中的0,1,1,2模式。這意味着我每個顏色仍然有2^12位是嗎? –

2

看起來你的原始12位數據不是線性的。這對圖像來說很常見。對於非線性比例,您不能使用線性變換(如16除)。

sqrt(x*16)這樣的非線性變換也會給您一個8位值。std::pow(x, 12.0/8.0)

低梯度圖像的一個已知問題是你得到了條帶。如果您的圖像有一個區域,其原始值從100到200不等,則12到8位縮小將縮小到不到100個不同的值。你四捨五入,用天真的(本地)四捨五入來得到樂隊。線性或非線性的,那麼將會有一些輸入x映射到y,還有一些映射到y + 1。這可以通過在浮點上進行轉換,然後在舍入之前在-1.0和+1.0之間添加一個隨機值來緩解。這有效地打破了樂隊結構。

+0

謝謝! 'sqrt(x * 16)'和'std :: pow(x,12/8)'都比線性變換好得多。 但是,我的形象似乎變得灰暗更綠,有沒有辦法打擊它?結果,藍色的海水變得更加蒼白無比。 –