Bayer 模式图像(bggr ,grbg, gbrg)转rgb888

news/2024/7/21 5:46:39 标签: 图像处理

1.Bayer 模式图像

Bayer 模式是一种用于数字图像捕捉的常见模式,特别是在单个传感器摄像头中广泛使用。Bayer 模式是一种通过排列红、绿、蓝滤色阵列以及插值算法来捕捉彩色图像的技术。

Bayer 模式图像是由一个仅包含红、绿、蓝三种颜色中的一种的滤色阵列构成的,其中每个像素只能感知其中一种颜色的光。这种滤色阵列的排列方式通常遵循一种固定的模式,比如 BGGR、RGGB 或者类似的方式。

对于一个 Bayer 模式的图像,每个像素只有一种颜色的信息,而其他两种颜色的信息需要通过插值算法来估算得到。插值算法会利用附近像素的颜色信息来推测缺失的颜色信息,从而生成完整的彩色图像。

要将 Bayer 模式图像转换为完整的彩色图像,需要进行一系列的处理步骤,如色彩插值、白平衡校正、色彩校正等。这些处理步骤根据每个像素的原始数据和相邻像素的信息来计算出最终的彩色值。最终的图像会包含完整的 RGB 信息,使我们能够看到真实的彩色图像。

2.bayer模式下的排列方式说明

Bayer 模式图像的排列方式通常用四个字母的缩写来表示,其中每个字母代表一个颜色通道(红、绿、蓝)。

以下是一些常见的 Bayer 模式排列方式的说明:

  1. RGGB:在 RGGB Bayer 模式中,第一行的第一个像素是红色(R),第一行的第二个像素是绿色(G),第二行的第一个像素是绿色(G),第二行的第二个像素是蓝色(B)。这种排列方式在许多传感器中被广泛使用。

  2. GRBG:在 GRBG Bayer 模式中,第一行的第一个像素是绿色(G),第一行的第二个像素是红色(R),第二行的第一个像素是蓝色(B),第二行的第二个像素是绿色(G)。这种排列方式也常见于许多传感器中。

  3. BGGR:在 BGGR Bayer 模式中,第一行的第一个像素是蓝色(B),第一行的第二个像素是绿色(G),第二行的第一个像素是绿色(G),第二行的第二个像素是红色(R)。这种排列方式也是常见的。

 3.Bayer 模式图像转换rgb888的常用方式

将 Bayer 模式图像转换为 RGB888 图像的常用方式是色彩插值。这种方法使用插值算法来完成缺失的颜色通道的估算。

常见的色彩插值算法有两种:

  1. 线性插值:在这种插值算法中,缺失的颜色像素将使用其邻近像素的值进行插值。例如,对于 BGGR Bayer 模式图像,缺失的绿色像素可以通过其周围的四个相邻像素的平均值来得到。对于缺失的红色或蓝色像素,可以使用相邻行或相邻列的值计算。

  2. 修正的 bilinear 插值:这是一种更精确的插值算法,它对线性插值进行了改进。在这种算法中,缺失的颜色像素将使用邻近像素和它们的邻近像素来进行插值。这种算法在处理高畸变图像时可以提供更好的效果。

4.线性插值方法详细介绍

线性插值是一种简单的插值算法,它通常用于将 Bayer 模式图像转换为 RGB 图像。它通过使用邻近像素的值来计算缺失的值。

具体来说,在 BGGR Bayer 模式中,绿色通道的缺失值可以通过使用周围的绿色像素值(左侧、右侧、上方和下方)的平均值进行线性插值。同样的方法也适用于红色和蓝色通道的情况,但需要使用相邻列或相邻行的值进行插值。

下面是一个简单的示意图,说明在绿色通道的情况下如何进行线性插值。假设绿色像素(绿点)的周围只有四个相邻像素(蓝点),则可以使用这些像素的平均值来计算该像素的值(黄点):

B G B G B G
G * G * G *     *(待计算的像素)
B G B G B G
G * G * G *
B G B G B G

在红色和蓝色通道的情况下也是类似的,在确定相邻像素方向之后,使用这些像素的值进行插值计算即可。

 5.实现

这里用了两种方法的结合,即 “101 方法” 和 “RGB 插值方法” 来处理图像数据。

首先,根据输入图像的宽度和高度,计算出源图像的宽度和高度,并创建一个新的数组 src_data,其大小为源图像的宽度乘以高度。

接下来,在 “101 方法” 中,使用双层循环将原始图像的像素数据复制到 src_data 数组中,使用一定的偏移位置来确保每个像素的正确位置。

然后,根据 “RGB 插值方法” 对 src_data 数组进行边界的填充。具体的操作是:将第二行的像素复制到第一行,将倒数第二行的像素复制到倒数第一行;将第二列的像素复制到第一列,将倒数第二列的像素复制到倒数第一列。这样做可以确保边界的像素也可以参与后续的插值计算。

最后,通过两层嵌套的循环遍历源图像的每个像素。对于每个像素,根据其在源图像中的位置和相邻像素的值,使用 “RGB 插值方法” 来计算出 R、G、B 三个分量的值。具体的计算方式取决于源图像中像素的位置和颜色排列方式。

最终,将计算得到的 R、G、B 分量的值写入到目标图像的 image_rgb_data_888 数组中,并更新 dataIndex 的值,以便下一次写入。

根据不同的颜色排列方式(例如 “BGGR”、“GRBG”、“GBRG”),计算 R、G、B 分量的顺序不完全相同。每个分量的值是根据源图像中相邻像素的值进行插值计算得到的。这样处理后,最终得到的 image_rgb_data_888 数组即为转换后的 RGB 图像数据。

    int src_width = width + 2;
    int src_height = height + 2;

    unsigned char *src_data = new unsigned char [src_width * src_height];
    /*  101填充法(例子)
         R  G  R  G  R G
         G *B *G *B *G B
         R *G *R *G *R G
         G *B *G *B *G B
         R *G *R *G *R G
         G  B  G  B  G B
    */

    for(int i = 0; i < height; i++)
    {
        for(int j = 0; j < width; j++)
        {
            src_data[src_width*(i + 1) + 1 + j] = data[width*i + j];
        }
    }

    /* 填充2行 */
    for(int i = 0; i < width; i++)
    {
        /*第1行*/
        src_data[1 + i] = src_data[src_width*2 + 1 + i];

        /*倒数第1行*/
        src_data[src_width*(src_height - 1) + 1 + i] = src_data[src_width*(src_height - 3) + 1 + i];
    }

    /* 填充2列 */
    for(int i = 0; i < src_height; i++)
    {
        /*第1列*/
        src_data[i * src_width + 0] = src_data[i * src_width + 2];

        /*倒数第1列*/
        src_data[i * src_width + src_width - 1] = src_data[i * src_width + src_width - 3];
    }

    int dataIndex = 0;  // 记录数据索引
    for(int i = 0; i < height; i++)
    {
        for(int j = 0; j < width; j++)
        {
            int index_1 = src_data[i*src_width + j];
            int index_2 = src_data[i*src_width + j + 1];
            int index_3 = src_data[i*src_width + j + 2];
            int index_4 = src_data[(i + 1)*src_width + j];
            int index_5 = src_data[(i + 1)*src_width + j + 1];
            int index_6 = src_data[(i + 1)*src_width + j + 2];
            int index_7 = src_data[(i + 2)*src_width + j];
            int index_8 = src_data[(i + 2)*src_width + j + 1];
            int index_9 = src_data[(i + 2)*src_width + j + 2];

            unsigned char index_r = 0;
            unsigned char index_g = 0;
            unsigned char index_b = 0;
/*bggr*/
            if((i % 2 == 0) && (j % 2 == 0)) //B
            {
                 //r
                 index_r = (index_1 + index_3 + index_7 + index_9)/4;
                 //g
                 index_g = (index_2 + index_4 + index_6 + index_8)/4;
                 //b
                 index_b = index_5;
            }
            if((i % 2 == 0) && (j % 2 != 0)) //g
           {
                //r
                index_r = (index_2 + index_8)/2;
                //g
                index_g = (index_1 + index_3 + index_5 + index_7 + index_9)/5;
                //b
                index_b = (index_4 + index_6)/2;
            }
           if((i % 2 != 0) && (j % 2 == 0)) //g
            {
                //r
                index_r = (index_4 + index_6)/2;
                //g
                index_g = (index_1 + index_3 + index_5 + index_7 + index_9)/5;
                //b
                index_b = (index_2 + index_8)/2;
           }
            if((i % 2 != 0) && (j % 2 != 0)) //r
          {
                //r
                index_r = index_5;
                //g
                index_g = (index_2 + index_4 + index_6 + index_8)/4;
                //b
                index_b = (index_1 + index_3 + index_7 + index_9)/4;
            }
/*grbg*/
            if((i % 2 == 0) && (j % 2 == 0)) //g
            {
                 //r
                 index_r = (index_4 + index_6)/2;
                 //g
                 index_g = (index_1 + index_3 + index_5 + index_7 + index_9)/5;
                 //b
                 index_b = (index_2+ index_8)/2;
            }
            if((i % 2 == 0) && (j % 2 != 0)) //r
            {
                //r
                index_r = index_5;
                //g
                index_g = (index_2 + index_4 + index_6 + index_8)/4;
                //b
                index_b = (index_1 + index_3 + index_5 + index_7)/4;
            }
            if((i % 2 != 0) && (j % 2 == 0)) //b
            {
                //r
                index_r = (index_1 + index_3 + index_5 + index_7)/4;
                //g
                index_g = (index_2 + index_4 + index_6 + index_8)/4;
                //b
                index_b = index_5;
            }
            if((i % 2 != 0) && (j % 2 != 0)) //g
            {
                //r
                index_r = (index_2 + index_8)/2;
                //g
                index_g = (index_1 + index_3 + index_5 + index_7 + index_9)/5;
                //b
                index_b = (index_4 + index_6)/2;
            }
 /*gbrg*/
            if((i % 2 == 0) && (j % 2 == 0)) //g
            {
                 //r
                 index_r = (index_2 + index_8)/2;
                 //g
                 index_g = (index_1 + index_3 + index_5 + index_7 + index_9)/5;
                 //b
                index_b = (index_4+ index_6)/2;
            }
            if((i % 2 == 0) && (j % 2 != 0)) //b
           {
               //r
                index_r = (index_1 + index_3 + index_7 + index_9)/4;
                //g
                index_g = (index_2 + index_4 + index_6 + index_8)/4;
                //b
                index_b = index_5;
            }
           if((i % 2 != 0) && (j % 2 == 0)) //r
            {
                //r
                index_r = index_5;
               //g
                index_g = (index_2 + index_4 + index_6 + index_8)/4;
                //b
                index_b = (index_1 + index_3 + index_7 + index_9)/4;
            }
            if((i % 2 != 0) && (j % 2 != 0)) //g
            {
               //r
               index_r = (index_4 + index_6)/2;
               //g
               index_g = (index_1 + index_3 + index_5 + index_7 + index_9)/5;
               //b
                index_b = (index_2 + index_8)/2;
           }
            image_rgb_data_888[dataIndex] = index_r;
            image_rgb_data_888[dataIndex + 1] = index_g;
            image_rgb_data_888[dataIndex + 2] = index_b;


            dataIndex += 3;  // 数据索引递增3,因为 RGB888 数据每个像素占用3个字节

        }


http://www.niftyadmin.cn/n/5158614.html

相关文章

计算机毕设 基于大数据的高校校园学生一卡通数据分析

文章目录 0 项目简介任务 1数据导入与预处理任务 1.1 探查数据质量并进行缺失值和异常值处理1.1.2检查重复值1.1.3数据内容总览1.1.4数据分布总览1.1.5消费金额和消费次数观察消费金额和消费次数的散点图1.1.6观察 CardCount 特征的分布情况 任务2 食堂就餐行为分析任务 2.2 食…

关于python中全局变量报错解决办法

在函数外面可声明全局变量&#xff0c;如下所示&#xff0c;其中a为全局变量。 a 0 def bbbb():a 1函数处在全局变量声明范围内 若函数处在全局变量声明范围内&#xff0c;则不需要在函数中加global&#xff0c;可直接在函数中使用&#xff0c;如上所示。若强行加了&#x…

搅拌站排队叫号系统 | 混凝土智慧物流管理平台

思伟软件 智慧物流管理平台 混凝土 用砼行 在线下单。工地通过砼行小程序下单&#xff0c;搅拌站通过砼行APP接单。 智能调度。手机打卡&#xff0c;自动排队。大小车自动分列&#xff0c;拌台生产随时看。电子小票直达司机手机。自动收到砼行APP推送的电子小票与广播发车提…

el-date-picker 日期时间选择器 限时时间范围 精确到时分秒

官方的disabledDate属性&#xff1a;设置禁用状态&#xff0c;参数为当前日期&#xff0c;要求返回 Boolean&#xff0c;它只能禁用日期&#xff0c;对于时间并不能直接禁用&#xff0c;总结以下两个方法解决禁用时间&#xff1a; 1.通过watch去监听源数据&#xff1a; 1.1 组…

汽车工业生产线数字孪生可视化管理平台,赋予工厂车间数字化智慧化管理

在工业4.0 的时代背景下&#xff0c;随着企业数字化进程的推进&#xff0c;数字孪生可视化技术逐渐在汽车行业得到广泛应用&#xff0c;数字孪生智慧工厂的建设也成为了汽车行业数字化转型的趋势之一。汽车制造业属于典型的离散制造行业&#xff0c;汽车生产包含冲压、焊接、涂…

[CISCN 2023 初赛]go_session

文章目录 考点代码审计main.goroute.goIndex函数Admin函数Flask函数 解题过程伪造session获取server.py构造payload覆盖server.py命令执行 考点 session伪造&#xff0c;pongo2模板注入&#xff0c;debug模式覆盖源文件 代码审计 main.go package mainimport ("github.c…

Linux应用开发基础知识——Makefile 的使用(二)

前言&#xff1a; 在 Linux 中使用 make 命令来编译程序&#xff0c;特别是大程序&#xff1b;而 make 命令所执 行的动作依赖于 Makefile 文件。最简单的 Makefile 文件&#xff1a; hello: hello.c 、gcc -o hello hello.c 、clean:、 rm -f hello 将上述 4 行存为 Makefile …

2214-30SLOTT DCS和SCADA在数字化转型中的角色演变

2214-30SLOTT DCS和SCADA在数字化转型中的角色演变 DCS和SCADA系统都在根据更广泛的数字化转型趋势进行转型&#xff0c;如工业物联网(IIoT)。这种转变带来了提高工业自动化能力和过程制造商价值的承诺。 终端用户带来的新挑战促使供应商考虑如何使用COTS和信息技术(it)组件重…