ISP模块之RAW DATA去噪(一)

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

    RAW DATA可以理解为: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)代码:

主函数:

 

  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. }  
void main()
{

	/*******开始编写中值滤波去噪模块--2015.07.27***********/
	//针对R分量块进行去噪
	pNewDoc->m_RBlock  = new unsigned short [m_Height*m_Width/4];
	pNewDoc->m_G1Block = new unsigned short [m_Height*m_Width/4];
	pNewDoc->m_G2Block = new unsigned short [m_Height*m_Width/4];
	pNewDoc->m_BBlock  = new unsigned short [m_Height*m_Width/4];

	unsigned short* smoothR  = new unsigned short[m_Height*m_Width/4];
	unsigned short* smoothG1 = new unsigned short[m_Height*m_Width/4];
	unsigned short* smoothG2 = new unsigned short[m_Height*m_Width/4];
	unsigned short* smoothB  = new unsigned short[m_Height*m_Width/4];
	for (int i = 0; i < m_Height/2 ;i ++ )
	{
		for(int j = 0; j < m_Width/2 ; j ++ )
		{
			pNewDoc->m_RBlock [i*m_Width/2 + j] = m_RawImage[i*m_Width*2 + j*2];
			pNewDoc->m_G1Block[i*m_Width/2 + j] = m_RawImage[i*m_Width*2 + j*2 + 1];
			pNewDoc->m_G2Block[i*m_Width/2 + j] = m_RawImage[i*m_Width*2 + m_Width + j*2];
			pNewDoc->m_BBlock [i*m_Width/2 + j] = m_RawImage[i*m_Width*2 + m_Width + j*2 + 1];
		}
	}
	medianFilter(pNewDoc->m_RBlock,smoothR,m_Width/2,m_Height/2);   //针对R分量块进行去噪
	medianFilter(pNewDoc->m_G1Block,smoothG1,m_Width/2,m_Height/2); //针对G1分量块进行去噪
	medianFilter(pNewDoc->m_G2Block,smoothG2,m_Width/2,m_Height/2); //针对G2分量块进行去噪
	medianFilter(pNewDoc->m_BBlock,smoothB,m_Width/2,m_Height/2);   //针对B分量块进行去噪

	//反过来构造去噪去噪后的raw data
	for (int i = 0; i < m_Height/2 - 1;i ++ )
	{
		for(int j = 0; j < m_Width/2-1; j ++ )
		{
			pNewDoc->m_ImageNR[i*m_Width*2 + j*2] = smoothR[i*m_Width/2 + j];
			pNewDoc->m_ImageNR[i*m_Width*2 + j*2 + 1] = smoothG1[i*m_Width/2 + j]; 
			pNewDoc->m_ImageNR[i*m_Width*2 + m_Width + j*2] = smoothG2[i*m_Width/2 + j];
			pNewDoc->m_ImageNR[i*m_Width*2 + m_Width + j*2 + 1] = smoothB[i*m_Width/2 + j];

		}
	}
	/***********中值滤波模块完成--2015.07.27********************/
	//SaveImageData(pNewDoc->m_ImageNR, m_Height ,m_Width,"E:\\m_ImageNR.bmp");
	SetDisplayRawImage( pNewDoc->m_ImageNR, m_Height ,m_Width, m_RawBitType,pNewDoc->m_Image);
}
  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>  
<pre name="code" class="html">void medianFilter (unsigned short* corrupted, unsigned short* smooth, int width, int height)  
{  
      
    memcpy ( smooth, corrupted, width*height*sizeof(unsigned short) );  
    for (int j=1;j<height-1;j++)  
    {  
        for (int i=1;i<width-1;i++)  
        {  
            int k = 0;  
            unsigned short window[9];  
            for (int jj = j - 1; jj < j + 2; ++jj)  
                for (int ii = i - 1; ii < i + 2; ++ii)  
                    window[k++] = corrupted[jj * width + ii];  
            //   Order elements (only half of them)  
            for (int m = 0; m < 5; ++m)  
            {  
                int min = m;  
                for (int n = m + 1; n < 9; ++n)  
                    if (window[n] < window[min])  
                        min = n;  
                //   Put found minimum element in its place  
                unsigned short temp = window[m];  
                window[m] = window[min];  
                window[min] = temp;  
            }
			smooth[ j*width+i ] = window[4];  
        }  
    }  
} <span style="font-family: Arial, Helvetica, sans-serif;"> </span>

  1.   

中值滤波函数是在网上找的代码,由于比较基础,就直接拿过来用了,侵删吐舌头

去噪前后效果图:

 

    下一篇文章,我将主要给大家展示一下BM3D算法RAW DATA去噪效果,谢谢。

posted @ 2016-08-12 18:06  老拙  阅读(5508)  评论(0编辑  收藏  举报