图像bayer格式介绍以及bayer插值原理CFA

 图像bayer格式介绍

  bayer格式图片是伊士曼·柯达公司科学家Bryce Bayer发明的,Bryce Bayer所发明的拜耳阵列被广泛运用数字图像

  对于彩色图像,需要采集多种最基本的颜色,如rgb三种颜色,最简单的方法就是用滤镜的方法,红色的滤镜透过红色的波长,绿色的滤镜透过绿色的波长,蓝色的滤镜透过蓝色的波长。如果要采集rgb三个基本色,则需要三块滤镜,这样价格昂贵,且不好制造,因为三块滤镜都必须保证每一个像素点都对齐。当用bayer格式的时候,很好的解决了这个问题。bayer 格式图片在一块滤镜上设置的不同的颜色,通过分析人眼对颜色的感知发现,人眼对绿色比较敏感,所以一般bayer格式的图片绿色格式的像素是是rg像素的和。

  另外,Bayer格式是相机内部的原始图片一般后缀名为.raw。很多软件都可以查看比如PS。我们相机拍照下来存储在存储卡上的.jpeg或其它格式的图片都是从.raw格式转化过来的。如下图,为bayer色彩滤波阵列,由一半的G1/4R1/4B组成。

                      

2 bayer格式图像传感器硬件

  图像传感器的结构如下所示,每一个感光像素之间都有金属隔离层,光线通过微镜头,在色彩滤波器过滤之后,投射到相应的漏洞式硅感光元件上。

          

 

  当Image Sensor往外逐行输出数据时,像素的序列为GRGRGR.../BGBGBG...(顺序RGB)。这样阵列的Sensor设计,使得RGB传感器减少到了全色传感器的1/3,如下所示。

                        

3 bayer格式插值红蓝算法实现

  每一个像素仅仅包括了光谱的一部分,必须通过插值来实现每个像素的RGB值。为了从Bayer格式得到每个像素的RGB格式,我们需要通过插值填补缺失的2个色彩。插值的方法有很多(包括邻域、线性、3*3等),速度与质量权衡,最好的线性插值补偿算法。其中的一种算法如下: 

RB通过线性邻域插值,但这有四种不同的分布,如下图所示:

                   

                                       (a)                                   (b)

                   

                         (c)                                   (d)

在(a)与(b)中,中间像素的RB分别取左右邻域(或上下邻域)的平均值。

a:

b:

在(c)与(d)中,中间像素的B或R值取对角领域的平均值。 

c:

d:

4 bayer格式插值绿值算法实现

                          (e)                                                        (f)

  由于人眼对绿光反应最敏感,对紫光和红光则反应较弱,因此为了达到更好的画质,需要对G特殊照顾。在上述(c)与(d)中,扩展开来就是上图的(e)与(f)中间像素G的取值,者也有一定的算法要求,不同的算法效果上会有差异。经过相关的研究,

  (e)中间像素G值的算法如下: 

                   

  (f)中间像素G值的算法如下:

                   

      

  CMOS摄像头这部分转换是在内部用ADC或者ISP完成的,生产商为了降低成本必然会使得图像失真。当然用外部处理器来实现转换,如果处理器的速度足够NB,能够胜任像素的操作,用上面的算法来进行转换,皆大欢喜。不过上述算法将直接成倍提高了算法的复杂度,速度上将会有所限制。因此为了速度的提成,可以直接通过来4领域G取均值来中间像素的G值,将会降低一倍的速率,而在性能上差之甚微,算法如下: 

                   

  如果能够通过损失图像的质量,来达到更快的速度,还可以取G1G2的均值来实现,但是这样的做法会导致边沿以及跳变部分的失真。 

5 代码实现

代码展示:

原始图片

bayer格式图像(灰度图)

bayer格式图像(彩色图)

重建图像

为什么bayer格式图像会是灰度图,这是因为每一个像素上只有一个传感器,所以只能输出一个对应通道的值,而不像RGB图像有3个通道,整张图像是单通道图像,所以虽然是彩色传感器,但是以图片输出时,还是灰度图的形式。bayer格式彩色图像的处理方式是将对应像素上缺少的两个传感器的值置0,以3通道彩色图像输出。

5.1 模拟bayer格式图像

 

根据Bayer的色彩滤波阵列,即GRGRGR.../BGBGBG...,设计模板,如果像素上有某种颜色的传感器,就将像素对应R、G、B(openCV中的顺序是BGR)通道的该颜色置为1,其余两种颜色置为0(比如在这个像素上蓝色传感器,就将对应的B通道的值置为1,其余两个通道置为0)。这样就能得到跟图片颜色尺寸相同的模板,然后将原始图像与模板相乘,就可保留Bayer阵列对应的颜色值(其余值都变成0),最后将所有的颜色值提取出来,就变成了Bayer图像。

5.2 重建图像(代码太长就不单独放了,末尾有完整版代码)

根据上面得到Bayer图像(实质是二维的矩阵),重建彩色图像。首先先要将二维矩阵恢复成Bayer彩色图像,接下来就是对该图像进行插值。除了上面提到的几种情况,还有:

对这种情况,我直接将第二行的值赋给第一行

类似地,将倒数第二列的数赋值给最后一列。

对于G分量,如果顶点处值为0,直接计算两个邻域的平均值。

对于边缘缺失值的情况,直接计算三邻域的平均值。

对于第二行/列或者倒数第二行/列,如果缺失值,直接计算四邻域的平均值。(更多细节详见代码)

5.3 完整代码

# -*- coding: utf-8 -*-

"""

Created on Sat Jul  6 11:10:12 2019

@author: Carl

"""

import cv2

import numpy as np

def Bayer(img_rgb):

    #模拟bayer格式图像

    mask = np.zeros(img_rgb.shape)

    #Blue channel

    mask[:, :, 0][1::2, ::2] = 1

    #Green channel

    mask[:, :, 1][::2, ::2] = 1

    mask[:, :, 1][1::2, 1::2] = 1

    #Red channel

    mask[:, :, 2][::2, 1::2] = 1

    bayer = mask * img_rgb

    #convert tuple to list

    size = list(img_rgb.shape)

    #remove the the last element

    size.pop()

    #calculate the bayer image

    img = np.zeros(tuple(size))

    for i in range(size[0]):

        for j in range(size[1]):

            img[i][j] = np.max((bayer[:,:,0][i][j], bayer[:,:,1][i][j], bayer[:,:,2][i][j]))

    img = img.astype(np.uint8)

    bayer = bayer.astype(np.uint8)

    return img, bayer

def Interpolation(img):

    mask1 = np.zeros(img.shape)

    mask1[1::2, ::2] = 1

    img_b = img * mask1

    size = list(img_b.shape)

    flag = np.zeros(img_b.shape)

    flag[1::2, ::2] = 1

    for i in range(1, size[0]-1):

        for j in range(1, size[1]-1):

            if(img_b[i][j] == 0):

                if(img_b[i][j-1] != 0):

                    flag[i][j] = -1

                elif(img_b[i][j-1] == 0 and img_b[i-1][j] != 0):

                    flag[i][j] = 2

                else:

                    flag[i][j] = -2

            else:

                flag[i][j] = 1

   

    for i in range(size[0]):

        for j in range(size[1]):

            if(flag[i][j] == -1):

                img_b[i][j] = (img_b[i][j-1] + img_b[i][j+1]) / 2

            if(flag[i][j] == 2):

                img_b[i][j] = (img_b[i-1][j] + img_b[i+1][j]) / 2

            if(flag[i][j] == -2):

                img_b[i][j] = (img_b[i-1][j-1] + img_b[i-1][j+1] + img_b[i+1][j-1] + img_b[i+1][j+1]) / 4

   

    #直接复制

    for i in range(size[1]):

        if(img_b[0][i] == 0):

            img_b[0][i] = img_b[1][i]

   

    #直接复制   

    for i in range(size[0]):

        if(img_b[i][size[1]-1] == 0):

            img_b[i][size[1]-1] = img_b[i][size[1]-2]

       

    for i in range(size[0]):

        if(img_b[i][0] == 0):

            img_b[i][0] = (img_b[i-1][0] + img_b[i+1][0]) / 2

   

    for i in range(size[1]):

        if(img_b[size[0]-1][i] == 0):

            img_b[size[0]-1][i] = (img_b[size[0]-1][i-1] + img_b[size[0]-1][i+1]) / 2

           

    mask3 = np.zeros(img.shape)

    mask3[::2, 1::2] = 1

    img_r = img * mask3

   

    size = list(img_r.shape)

    flag = np.zeros(img_r.shape)

    flag[::2, 1::2] = 1 

    for i in range(1, size[0]-1):

        for j in range(1, size[1]-1):

            if(img_r[i][j] == 0):

                if(img_r[i][j-1] != 0):

                    flag[i][j] = -1

                elif(img_r[i-1][j] != 0):

                    flag[i][j] = 2

                else:

                    flag[i][j] = -2

            else:

                flag[i][j] = 1

   

    for i in range(size[0]):

        for j in range(size[1]):

            if(flag[i][j] == -1):

                img_r[i][j] = (img_r[i][j-1] + img_r[i][j+1]) / 2

            if(flag[i][j] == 2):

                img_r[i][j] = (img_r[i-1][j] + img_r[i+1][j]) / 2

            if(flag[i][j] == -2):

                img_r[i][j] = (img_r[i-1][j-1] + img_r[i-1][j+1] + img_r[i+1][j-1] + img_r[i+1][j+1]) / 4

   

    for i in range(size[0]):

        if(img_r[i][0] == 0):

            img_r[i][0] = img_r[i][1]

       

    for i in range(size[1]):

        if(img_r[size[0]-1][i] == 0):

            img_r[size[0]-1][i] = img_r[size[0]-2][i]

       

   

   

    for i in range(size[1]):

        if(img_r[0][i] == 0):

            img_r[0][i] = (img_r[0][i-1] + img_r[0][i+1]) / 2

           

    for i in range(size[0]):

        if(img_r[i][size[0]-1] == 0):

            img_r[i][size[0]-1] = (img_r[i-1][size[0]-1] + img_r[i+1][size[0]-1]) / 2

   

   

    mask2 = np.zeros(img.shape)

    mask2[::2, ::2] = 1

    mask2[1::2, 1::2] = 1

    img_g = img * mask2

    size = list(img_g.shape)

    flag = np.zeros(img_g.shape)

    mask2[::2, ::2] = 1

    mask2[1::2, 1::2] = 1

    for i in range(2, size[0]-2):

        for j in range(2, size[1]-2):

            if(img_g[i][j] == 0):

                if(mask1[i][j] == 1):

                    if(abs(img_b[i][j-2]-img_b[i][j+2]) < abs(img_b[i][j+2]-img_b[i][j-2])):

                        img_g[i][j] = (img_g[i-1][j] + img_g[i+1][j]) / 2

                    elif(abs(img_b[i][j-2]-img_b[i][j+2]) > abs(img_b[i][j+2]-img_b[i][j-2])):

                        img_g[i][j] = (img_g[i][j-1] + img_g[i+1][j]) / 2

                    else:

                        img_g[i][j] = (img_g[i-1][j] + img_g[i+1][j] + img_g[i][j-1] + img_g[i][j+1]) / 4

                if(mask3[i][j] == 1):

                    if(abs(img_r[i][j-2]-img_r[i][j+2]) < abs(img_r[i][j+2]-img_r[i][j-2])):

                        img_g[i][j] = (img_g[i-1][j] + img_g[i+1][j]) / 2

                    elif(abs(img_r[i][j-2]-img_r[i][j+2]) > abs(img_r[i][j+2]-img_r[i][j-2])):

                        img_g[i][j] = (img_g[i][j-1] + img_g[i+1][j]) / 2

                    else:

                        img_g[i][j] = (img_g[i-1][j] + img_g[i+1][j] + img_g[i][j-1] + img_g[i][j+1]) / 4

   

    if(img_g[0][size[1]-1] == 0):

        img_g[0][size[1]-1] = (img_g[0][size[1]-2] + img_g[1][size[1]-1] ) / 2

       

    if(img_g[size[0]-1][0] == 0):

        img_g[size[0]-1][0] = (img_g[size[0]-2][0] + img_g[size[0]-1][1]) / 2

   

    if(img_g[size[0]-1][size[0]-1] == 0):

        img_g[size[0]-1][size[0]-1] = (img_g[size[0]-1][size[0]-2] + img_g[size[0]-2][size[0]-1]) / 2

   

    for i in range(size[0]):

        if(img_g[i][0] == 0):

            img_g[i][0] = (img_g[i-1][0] + img_g[i+1][0] + img_g[i][1]) / 3

    for i in range(size[1]):

        if(img_g[0][i] == 0):

            img_g[0][i] = (img_g[0][i-1] + img_g[0][i+1] + img_g[1][i]) / 3

           

    for i in range(size[0]):

        if(img_g[i][size[1]-1] == 0):

            img_g[i][size[1]-1] = (img_g[i-1][size[1]-1] + img_g[i+1][size[1]-1] + img_g[i][size[1]-2]) / 3

           

    for i in range(size[1]):

        if(img_g[size[0]-1][i] == 0):

            img_g[size[0]-1][i] = (img_g[size[0]-1][i-1] + img_g[size[0]-1][i+1] + img_g[size[0]-2][i]) / 3

   

    for i in range(size[0]):

        for j in range(size[1]):

            if(img_g[i][j] == 0):

                img_g[i][j] = (img_g[i-1][j] + img_g[i+1][j] + img_g[i][j-1] + img_g[i][j+1]) / 4

   

    return img_b, img_g, img_r

if __name__ == '__main__' :

    img_rgb = cv2.imread(r'..\image\bg6.jpg')

    img, ori_img = Bayer(img_rgb)

    img_b, img_g, img_r = Interpolation(img)

    int_img = np.zeros(img_rgb.shape)

    int_img[:, :, 0] = img_b

    int_img[:, :, 1] = img_g

    int_img[:, :, 2] = img_r

    int_img = int_img.astype(np.uint8)

   

    cv2.imshow('ori', img_rgb)

    cv2.imshow('img2', ori_img)

    cv2.imwrite('gray.jpg', img)

    cv2.imwrite('ori_img.jpg', ori_img)

    cv2.imshow('img3', int_img)

    cv2.imwrite('int_img.jpg', int_img)

    #hmerge = np.hstack((img_rgb, ori_img, int_img))

    #cv2.imshow('merge', hmerge)

   

    cv2.waitKey(0)

    cv2.destroyAllWindows()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值