搜索
 找回密码
 立即注册

简单一步 , 微信登陆

ISP模块之RAW DATA去噪

作者:laowai_love | 时间:2016-10-8 14:06:30 | 阅读:3660| 只看该作者

ISP(ImageSignal Processor),图像信号处理器,主要用来对前端图像传感器输出信号处理的单元,主要用于手机,监控摄像头等设备上。

RAWDATA,可以理解为:RAW图像就是CMOS或者CCD图像感应器将捕捉到的光源信号转化为数字信号的原始数据,是无损的,包含了物体原始的颜色信息等。RAW数据格式一般采用的是Bayer排列方式,通过滤波光片,产生彩色滤波阵列(CFA),鉴于人眼对绿色波段的色彩比较敏感,Bayer数据格式中包含了50%的绿色信息,以及各25%的红色和蓝色信息。

Bayer排列格式有以下4种:

  1.| R | G |  2.| B| G |   3.| G | R |   4.| G | B |

   | G | B |   | G | R |    | B | G |    | R | G |

在ISP处理模块的第一部分,就是需要对CFA DATA进行去噪操作。普通的去噪方式针对Bayer数据格式是不合适的,需要进行变换后才能进行处理。

一、中值滤波CFA(Color Filter Array)Data去噪方法

首先,让我们一起来回顾一下中值滤波的算法原理以及优缺点,然后给出示意的算法效果图。

中值滤波,顾名思义就是将滤波器里面所有像素值进行排序,然后用中间值替代当前像素点值。常用的中值滤波器有3X3,5X5等。

中值滤波的有点在于,实现简单,能够有效的消除椒盐噪声以及其他脉冲型噪声。缺点也是所有去噪算法所共有的,就是平滑模糊了图像的内容,有些角点以及边缘的信息损失。

对CFA DATA进行去噪时,需要将不同的颜色通道分开进行处理,这样是为了防止在平滑过程中将有用的颜色信息丢掉,比如说,由绿色信息包围的蓝色像素值与其相差很大时,此时就会被认为是噪声被处理掉,然而真实情况是,该区域的蓝色信息都是很大的。所以各通道单独处理的话是有利于保护颜色信息的。在我的处理过程中,是将原CFA DATA分成4块-R,G1,G2,B,分块去噪完成后再重新恢复到原来的位置,这样整个过程就完成了。

下面给出参考的中值滤波和主程序的C++(MFC)代码:

主函数:

[html] view plain copy

1.    void main()  

2.    {  

3.      

4.        /*******开始编写中值滤波去噪模块--2015.07.27***********/  

5.        //针对R分量块进行去噪  

6.        pNewDoc->m_RBlock  = new unsigned short [m_Height*m_Width/4];  

7.        pNewDoc->m_G1Block = new unsigned short [m_Height*m_Width/4];  

8.        pNewDoc->m_G2Block = new unsigned short [m_Height*m_Width/4];  

9.        pNewDoc->m_BBlock  = new unsigned short [m_Height*m_Width/4];  

10.   

11.      unsigned short* smoothR  = new unsigned short[m_Height*m_Width/4];  

12.      unsigned short* smoothG1 = new unsigned short[m_Height*m_Width/4];  

13.      unsigned short* smoothG2 = new unsigned short[m_Height*m_Width/4];  

14.      unsigned short* smoothB  = new unsigned short[m_Height*m_Width/4];  

15.      for (int i = 0; i < m_Height/2 ;i ++ )  

16.      {  

17.          for(int j = 0; j < m_Width/2 ; j ++ )  

18.          {  

19.              pNewDoc->m_RBlock [i*m_Width/2 + j] = m_RawImage[i*m_Width*2 + j*2];  

20.              pNewDoc->m_G1Block[i*m_Width/2 + j] = m_RawImage[i*m_Width*2 + j*2 + 1];  

21.              pNewDoc->m_G2Block[i*m_Width/2 + j] = m_RawImage[i*m_Width*2 + m_Width + j*2];  

22.              pNewDoc->m_BBlock [i*m_Width/2 + j] = m_RawImage[i*m_Width*2 + m_Width + j*2 + 1];  

23.          }  

24.      }  

25.      medianFilter(pNewDoc->m_RBlock,smoothR,m_Width/2,m_Height/2);   //针对R分量块进行去噪  

26.      medianFilter(pNewDoc->m_G1Block,smoothG1,m_Width/2,m_Height/2); //针对G1分量块进行去噪  

27.      medianFilter(pNewDoc->m_G2Block,smoothG2,m_Width/2,m_Height/2); //针对G2分量块进行去噪  

28.      medianFilter(pNewDoc->m_BBlock,smoothB,m_Width/2,m_Height/2);   //针对B分量块进行去噪  

29.   

30.      //反过来构造去噪去噪后的raw data  

31.      for (int i = 0; i < m_Height/2 - 1;i ++ )  

32.      {  

33.          for(int j = 0; j < m_Width/2-1; j ++ )  

34.          {  

35.              pNewDoc->m_ImageNR[i*m_Width*2 + j*2] = smoothR[i*m_Width/2 + j];  

36.              pNewDoc->m_ImageNR[i*m_Width*2 + j*2 + 1] = smoothG1[i*m_Width/2 + j];   

37.              pNewDoc->m_ImageNR[i*m_Width*2 + m_Width + j*2] = smoothG2[i*m_Width/2 + j];  

38.              pNewDoc->m_ImageNR[i*m_Width*2 + m_Width + j*2 + 1] = smoothB[i*m_Width/2 + j];  

39.   

40.          }  

41.      }  

42.      /***********中值滤波模块完成--2015.07.27********************/  

43.      //SaveImageData(pNewDoc->m_ImageNR, m_Height ,m_Width,"E:\\m_ImageNR.bmp");  

44.      SetDisplayRawImage( pNewDoc->m_ImageNR, m_Height ,m_Width, m_RawBitType,pNewDoc->m_Image);  

45.  }  

[html] view plain copy

1.    <pre name="code" class="html">void medianFilter (unsigned short* corrupted, unsigned short* smooth, int width, int height)   

2.    {   

3.            

4.        memcpy ( smooth, corrupted, width*height*sizeof(unsigned short) );   

5.        for (int j=1;j<height-1;j++)   

6.        {   

7.            for (int i=1;i<width-1;i++)   

8.            {   

9.                int k = 0;   

10.              unsigned short window[9];   

11.              for (int jj = j - 1; jj < j + 2; ++jj)   

12.                  for (int ii = i - 1; ii < i + 2; ++ii)   

13.                      window[k++] = corrupted[jj * width + ii];   

14.              //   Order elements (only half of them)   

15.              for (int m = 0; m < 5; ++m)   

16.              {   

17.                  int min = m;   

18.                  for (int n = m + 1; n < 9; ++n)   

19.                      if (window[n] < window[min])   

20.                          min = n;   

21.                  //   Put found minimum element in its place   

22.                  unsigned short temp = window[m];   

23.                  window[m] = window[min];   

24.                  window[min] = temp;   

25.              }  

26.              smooth[ j*width+i ] = window[4];   

27.          }   

28.      }   

29.  } <span style="font-family: Arial, Helvetica, sans-serif;"> </span>  


收藏
收藏0
分享
分享
点赞
点赞0
反对
反对0
该会员没有填写今日想说内容.
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册
手机版