2016-06-09 309 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)'都比线性变换好得多。 但是,我的形象似乎变得灰暗更绿,有没有办法打击它?结果,蓝色的海水变得更加苍白无比。 –