Bayer转换算法
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Bayer转换算法[转]
/* raw.h */
#ifndef __RAW_H__
#define __RAW_H__
#define GP_OK 1
typedef enum {
BAYER_TILE_RGGB = 0,
BAYER_TILE_GRBG = 1,
BAYER_TILE_BGGR = 2,
BAYER_TILE_GBRG = 3,
BAYER_TILE_RGGB_INTERLACED = 4,
BAYER_TILE_GRBG_INTERLACED = 5,
BAYER_TILE_BGGR_INTERLACED = 6,
BAYER_TILE_GBRG_INTERLACED = 7,
} BayerTile;
int gp_bayer_expand (unsigned char *input, int w, int h, unsigned char *output, BayerTile tile);
int gp_bayer_decode (unsigned char *input, int w, int h, unsigned char *output, BayerTile tile);
int gp_bayer_interpolate (unsigned char *image, int w, int h, BayerTile tile);
#endif
/* raw.c */
#include "raw.h"
static const int tile_colours[8][4] = {
{0, 1, 1, 2},
{1, 0, 2, 1},
{2, 1, 1, 0},
{1, 2, 0, 1},
{0, 1, 1, 2},
{1, 0, 2, 1},
{2, 1, 1, 0},
{1, 2, 0, 1}};
#define RED 0
#define GREEN 1
#define BLUE 2
static int
gp_bayer_accrue (unsigned char *image, int w, int h, int x0, int y0,
int x1, int y1, int x2, int y2, int x3, int y3, int colour);
int
gp_bayer_expand (unsigned char *input, int w, int h, unsigned char *output, BayerTile tile)
{
int x, y, i;
int colour, bayer;
unsigned char *ptr = input;
switch (tile) {
case BAYER_TILE_RGGB:
case BAYER_TILE_GRBG:
case BAYER_TILE_BGGR:
case BAYER_TILE_GBRG:
for (y = 0; y < h; ++y)
for (x = 0; x < w; ++x, ++ptr)
{
bayer = (x&1?0:1) + (y&1?0:2);
colour = tile_colours[tile][bayer];
i = (y * w + x) * 3;
output[i+RED] = 0;
output[i+GREEN] = 0;
output[i+BLUE] = 0;
output[i+colour] = *ptr;
}
break;
case BAYER_TILE_RGGB_INTERLACED:
case BAYER_TILE_GRBG_INTERLACED:
case BAYER_TILE_BGGR_INTERLACED:
case BAYER_TILE_GBRG_INTERLACED:
for (y = 0; y < h; ++y, ptr+=w)
for (x = 0; x < w; ++x)
{
bayer = (x&1?0:1) + (y&1?0:2);
colour = tile_colours[tile][bayer];
i = (y * w + x) * 3;
output[i+RED] = 0;
output[i+GREEN] = 0;
output[i+BLUE] = 0;
output[i+colour] = (x&1)? ptr[x>>1]:ptr[(w>>1)+(x>>1)];
}
break;
}
return (GP_OK);
}
#define AD(x, y, w) ((y)*(w)*3+3*(x))
int
gp_bayer_interpolate (unsigned char *image, int w, int h, BayerTile tile) {
int x, y, bayer;
int p0, p1, p2, p3;
int value, div ;
switch (tile) {
default:
case BAYER_TILE_RGGB:
case BAYER_TILE_RGGB_INTERLACED:
p0 = 0; p1 = 1; p2 = 2; p3 = 3;
break;
case BAYER_TILE_GRBG:
case BAYER_TILE_GRBG_INTERLACED:
p0 = 1; p1 = 0; p2 = 3; p3 = 2;
break;
case BAYER_TILE_BGGR:
case BAYER_TILE_BGGR_INTERLACED:
p0 = 3; p1 = 2; p2 = 1; p3 = 0;
break;
case BAYER_TILE_GBRG:
case BAYER_TILE_GBRG_INTERLACED:
p0 = 2; p1 = 3; p2 = 0; p3 = 1;
break;
}
for (y = 0; y < h; y++)
for (x = 0; x < w; x++) {
bayer = (x&1?0:1) + (y&1?0:2);
if ( bayer == p0 ) {
/* red. green lrtb, blue diagonals */
image[AD(x,y,w)+GREEN] =
gp_bayer_accrue(image, w, h, x-1, y, x+1, y, x, y-1, x, y+1, GREEN) ;
image[AD(x,y,w)+BLUE] =
gp_bayer_accrue(image, w, h, x+1, y+1, x-1, y-1, x-1, y+1, x+1, y-1, BLUE) ; } else if (bayer == p1) {
/* green. red lr, blue tb */
div = value = 0;
if (x < (w - 1)) {
value += image[AD(x+1,y,w)+RED];
div++;
}
if (x) {
value += image[AD(x-1,y,w)+RED];
div++;
}
image[AD(x,y,w)+RED] = value / div;
div = value = 0;
if (y < (h - 1)) {
value += image[AD(x,y+1,w)+BLUE];
div++;
}
if (y) {
value += image[AD(x,y-1,w)+BLUE];
div++;
}
image[AD(x,y,w)+BLUE] = value / div;
} else if ( bayer == p2 ) {
/* green. blue lr, red tb */
div = value = 0;
if (x < (w - 1)) {
value += image[AD(x+1,y,w)+BLUE];
div++;
}
if (x) {
value += image[AD(x-1,y,w)+BLUE];
div++;
}
image[AD(x,y,w)+BLUE] = value / div;
div = value = 0;
if (y < (h - 1)) {
value += image[AD(x,y+1,w)+RED];
div++;
}
if (y) {
value += image[AD(x,y-1,w)+RED];
div++;
}
image[AD(x,y,w)+RED] = value / div;
} else {
/* blue. green lrtb, red diagonals */
image[AD(x,y,w)+GREEN] =
gp_bayer_accrue (image, w, h, x-1, y, x+1, y, x, y-1, x, y+1, GREEN) ;
image[AD(x,y,w)+RED] =
gp_bayer_accrue (image, w, h, x+1, y+1, x-1, y-1, x-1, y+1, x+1, y-1, RED) ; }
}
return (GP_OK);
}
static int
gp_bayer_accrue (unsigned char *image, int w, int h, int x0, int y0,
int x1, int y1, int x2, int y2, int x3, int y3, int colour)
{ int x [4] ;
int y [4] ;
int value [4] ;
int above [4] ;
int counter ;
int sum_of_values;
int average ;
int i ;
x[0] = x0 ; x[1] = x1 ; x[2] = x2 ; x[3] = x3 ;
y[0] = y0 ; y[1] = y1 ; y[2] = y2 ; y[3] = y3 ;
counter = sum_of_values = 0 ;
if(colour == GREEN)
{
for (i = 0 ; i < 4 ; i++)
{ if ((x[i] >= 0) && (x[i] < w) && (y[i] >= 0) && (y[i] < h)) {
value [i] = image[AD(x[i],y[i],w) + colour] ;
counter++;
}
else
{
value [i] = -1 ;
}
}
if(counter == 4)
{
int hdiff ;
int vdiff ;
hdiff = value [1] - value [0] ;
hdiff *= hdiff ; /* Make value positive by squaring */ vdiff = value [3] - value [2] ;
vdiff *= vdiff ; /* Make value positive by squaring */ if(hdiff > 2*vdiff)
{
return (value [3] + value [2])/2 ;
}
if(vdiff > 2*hdiff)
{
return (value [1] + value [0])/2 ;
}
}
}
/* for blue and red */
counter = sum_of_values = 0 ;
for (i = 0 ; i < 4 ; i++)
{ if ((x[i] >= 0) && (x[i] < w) && (y[i] >= 0) && (y[i] < h)) { value [i] = image[AD(x[i],y[i],w) + colour] ;
sum_of_values += value [i] ;
counter++ ;
}
}
average = sum_of_values / counter ;
if (counter < 4) return average ;
/* Less than four surrounding - just take average */
counter = 0 ;
for (i = 0 ; i < 4 ; i++)
{ above[i] = value[i] > average ;
if (above[i]) counter++ ;
}
/* Note: counter == 0 indicates all values the same */
if ((counter == 2) || (counter == 0)) return average ;
sum_of_values = 0 ;
for (i = 0 ; i < 4 ; i++)
{ if ((counter == 3) == above[i])
{ sum_of_values += value[i] ; }
}
return sum_of_values / 3 ;
}
int
gp_bayer_decode (unsigned char *input, int w, int h, unsigned char *output, BayerTile tile)
{
gp_bayer_expand (input, w, h, output, tile);
gp_bayer_interpolate (output, w, h, tile);
return (GP_OK);
}
Bayer图像处理
Bayer是相机内部的原始图片, 一般后缀名为.raw. 很多软件都可以查看, 比如PS. 我们相机拍照下来存储在存储卡上的.jpeg或其它格式的图片, 都是从.raw格式转化过来的. .raw格式内部的存储方式有多种, 但不管如何, 都是前两行的排列不同. 其格式可能如下:
G R G R G R G R
B G B G B G B G
G R G R G R G R
B G B G B G B G
横为2的倍数, 竖为4的倍数, 它们构成了分辨率. 如, 上面则代表了8 * 4 分辨率的
Bayer图.
我们要知道的是, G = 2 * R 及G = 2 * B, 即绿色值为红色值或蓝色值的两倍, 因
为人眼对绿色更敏感, 所以绿色的分量更重.
下面说一下从bayer转换成rgb图的算法, RGB图, 即为三色图, 一个像素点就由RGB
三种颜色构成的混合色, 而bayer图一个像素就只有一个颜色, 或R或G或B. 因为bayer 一个像素点只有一种颜色, 需要借助这个像素点周围的颜色对它进行插值(填充)另外的
两种颜色, 它本身的颜色就不用插了. 一般的算法是:
对于插入R和B,
Rx = ( R1 + R2 ) / 2; 或-------------取上边和下边的平均值, 或是左边和右边的平均值
Rx = ( R1 + R2 + R3 + R4 ) / 4;----取四个边的平均值
B同理. 如:
G B G
R G R
G B G
对于中间的G, 它缺少R和B, 用上下和左右的平均值进行求值.
对于
B G B
G R G
B G B
这个图呢, 中间点R, 缺少G和B, G暂时没讨论, 那么B, 就是从R的四个B角进行求平均值. ==============================================
如果插入G, 稍有些复杂.
不过一般的算法与R和B一样, 复杂的算法, 其复杂程度也提升一倍, 不过精度更高, 如果对于
视频监测系统来说, 精度相对来说不必要求太高, 用R或B的解法即可. 下面说复杂的:
对于图:
R1
G1
R4 G4 R G2 R2
G3
R3
对于中间点R, 它需要插入G和B, B不讨论, 主要讨论G, 它周围有四个点G1, G2, G3, G4. ( G1 + G3 ) / 2--------------如果|R1-R3| < |R2-R4|
G(R) = ( G2 + G4 ) / 2-------------如果|R1-R3| > |R2-R4|
( G1 + G2 + G3 + G4 ) / 4--如果|R1-R3| = |R2-R4|
如果周围出现的像素点颜色为B, 就应该比较|B1-B3|与|B2-B4|的值.
====================================================
还有关于将RGB格式转换为YUV格式的算法, 这里不想讨论了.
这里要注意的是, bayer每个像素的值是8位的. 但是有的相机的bayer格式却有10位, 12位
以及14位, 16位的, 那么如何将这些高于8位的数据转换为8位数据呢?. 拿12位数据来说, 有的人是取高8位或是低8位, 那么这样就会出现一个问题, 这张图像会有一个斜度, 不是偏亮就是偏暗, 或是出现其它乱七八糟的问题, 颜色问题总是不能令人满意. 这个时候就要去较正它, 无疑是浪费了时间.
另一种算法是使用log映射, 据老外说, 这种转换法具有较高的精度. 拿12位来说, 一般转换算法: f(in) = 2 ^ ( log(in) * 8 / 12 )
转换图为:
|8 .
| .
| .
|_______________________12
因为log256 = 8, log4096 = 12, 对了log是以2为底哦.
做得更好一点的算法, 可能根据提供的曝光等其它因素不同, 而将算法进行调整, 这样当一些意外事件发生时, 产生的图片也不会失真严重.
如有何疑问, 请致信: 414078791@。