zoukankan      html  css  js  c++  java
  • 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去噪效果,谢谢。

  • 相关阅读:
    Windows系统Nessus离线(Offline) 版的安装
    Openstack中keystone与外部LDAP Server的集成
    MySQL常用指令
    关于RequestParam在不同的Spring版本上,接口在controller重载时注解可能失效的踩坑记录
    利用反射注册SpringCache的RedisCacheManager缓存信息
    缩减项目代码中的大面积if策略
    Pentaho Report Designer 报表系统
    五种设计模式的分享
    反射的实践测试
    关于内外网分离情况下双网卡访问速度问题的解决
  • 原文地址:https://www.cnblogs.com/whw19818/p/5765967.html
Copyright © 2011-2022 走看看