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)代码:

主函数:

[html] view plain copy print?

  1. void main()
  2. {
  3. /*******开始编写中值滤波去噪模块--2015.07.27***********/
  4. //针对R分量块进行去噪
  5. pNewDoc->m_RBlock  = new unsigned short [m_Height*m_Width/4];
  6. pNewDoc->m_G1Block = new unsigned short [m_Height*m_Width/4];
  7. pNewDoc->m_G2Block = new unsigned short [m_Height*m_Width/4];
  8. pNewDoc->m_BBlock  = new unsigned short [m_Height*m_Width/4];
  9. unsigned short* smoothR  = new unsigned short[m_Height*m_Width/4];
  10. unsigned short* smoothG1 = new unsigned short[m_Height*m_Width/4];
  11. unsigned short* smoothG2 = new unsigned short[m_Height*m_Width/4];
  12. unsigned short* smoothB  = new unsigned short[m_Height*m_Width/4];
  13. for (int i = 0; i < m_Height/2 ;i ++ )
  14. {
  15. for(int j = 0; j < m_Width/2 ; j ++ )
  16. {
  17. pNewDoc->m_RBlock [i*m_Width/2 + j] = m_RawImage[i*m_Width*2 + j*2];
  18. pNewDoc->m_G1Block[i*m_Width/2 + j] = m_RawImage[i*m_Width*2 + j*2 + 1];
  19. pNewDoc->m_G2Block[i*m_Width/2 + j] = m_RawImage[i*m_Width*2 + m_Width + j*2];
  20. pNewDoc->m_BBlock [i*m_Width/2 + j] = m_RawImage[i*m_Width*2 + m_Width + j*2 + 1];
  21. }
  22. }
  23. medianFilter(pNewDoc->m_RBlock,smoothR,m_Width/2,m_Height/2);   //针对R分量块进行去噪
  24. medianFilter(pNewDoc->m_G1Block,smoothG1,m_Width/2,m_Height/2); //针对G1分量块进行去噪
  25. medianFilter(pNewDoc->m_G2Block,smoothG2,m_Width/2,m_Height/2); //针对G2分量块进行去噪
  26. medianFilter(pNewDoc->m_BBlock,smoothB,m_Width/2,m_Height/2);   //针对B分量块进行去噪
  27. //反过来构造去噪去噪后的raw data
  28. for (int i = 0; i < m_Height/2 - 1;i ++ )
  29. {
  30. for(int j = 0; j < m_Width/2-1; j ++ )
  31. {
  32. pNewDoc->m_ImageNR[i*m_Width*2 + j*2] = smoothR[i*m_Width/2 + j];
  33. pNewDoc->m_ImageNR[i*m_Width*2 + j*2 + 1] = smoothG1[i*m_Width/2 + j];
  34. pNewDoc->m_ImageNR[i*m_Width*2 + m_Width + j*2] = smoothG2[i*m_Width/2 + j];
  35. pNewDoc->m_ImageNR[i*m_Width*2 + m_Width + j*2 + 1] = smoothB[i*m_Width/2 + j];
  36. }
  37. }
  38. /***********中值滤波模块完成--2015.07.27********************/
  39. //SaveImageData(pNewDoc->m_ImageNR, m_Height ,m_Width,"E:\\m_ImageNR.bmp");
  40. SetDisplayRawImage( pNewDoc->m_ImageNR, m_Height ,m_Width, m_RawBitType,pNewDoc->m_Image);
  41. }
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);
}

[html] view plain copy print?

  1. <pre name="code" class="html">void medianFilter (unsigned short* corrupted, unsigned short* smooth, int width, int height)
  2. {
  3. memcpy ( smooth, corrupted, width*height*sizeof(unsigned short) );
  4. for (int j=1;j<height-1;j++)
  5. {
  6. for (int i=1;i<width-1;i++)
  7. {
  8. int k = 0;
  9. unsigned short window[9];
  10. for (int jj = j - 1; jj < j + 2; ++jj)
  11. for (int ii = i - 1; ii < i + 2; ++ii)
  12. window[k++] = corrupted[jj * width + ii];
  13. //   Order elements (only half of them)
  14. for (int m = 0; m < 5; ++m)
  15. {
  16. int min = m;
  17. for (int n = m + 1; n < 9; ++n)
  18. if (window[n] < window[min])
  19. min = n;
  20. //   Put found minimum element in its place
  21. unsigned short temp = window[m];
  22. window[m] = window[min];
  23. window[min] = temp;
  24. }
  25. smooth[ j*width+i ] = window[4];
  26. }
  27. }
  28. } <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>

[html] view plain copy print?


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

去噪前后效果图:

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

时间: 2024-10-11 19:52:09

ISP模块之RAW DATA去噪(一)的相关文章

ISP模块之RAW DATA去噪(二)--BM3D算法

在正式开始本篇文章之前,让我们一起回顾一下CFA图像去噪的一些基本思路与方法.接着我会详细地和大家分享自己学习理解的BM3D算法,操作过程,它的优缺点,最后会给出算法效果图供参考. 在ISP模块里,研究者们会讨论去噪模块(Noise Reduction)到底是在去马赛克模块(Demosaic)之前还是之后进行.如果在之前处理的话,随着去噪过程的进行,噪声点消除的同时,伴随着彩色信息的损失:如果在之后,复杂的插值过程将会改变噪声的统计模型,使其变得很复杂并且难以计算.所以,更多的情况是选择在Dem

Sensor信号输出YUV、RGB、RAW DATA、JPEG【转】

本文转载自:http://blog.csdn.net/southcamel/article/details/8305873 简单来说,YUV: luma (Y) + chroma (UV) 格式, 一般情况下sensor支持YUV422格式,即数据格式是按Y-U-Y-V次序输出的RGB: 传统的红绿蓝格式,比如RGB565,其16-bit数据格式为5-bit R + 6-bit G + 5-bit B.G多一位,原因是人眼对绿色比较敏感.RAW RGB: sensor的每一像素对应一个彩色滤光片

嵌入式开发之davinci--- 8148/8168/8127 中的图像采集格式Sensor信号输出YUV、RGB、RAW DATA、JPEG 4种方式区别

简单来说,YUV: luma (Y) + chroma (UV) 格式, 一般情况下sensor支持YUV422格式,即数据格式是按Y-U-Y-V次序输出的RGB: 传统的红绿蓝格式,比如RGB565,其16-bit数据格式为5-bit R + 6-bit G + 5-bit B.G多一位,原因是人眼对绿色比较敏感.RAW RGB: sensor的每一像素对应一个彩色滤光片,滤光片按Bayer pattern分布.将每一个像素的数据直接输出,即RAW RGB dataJPEG: 有些sensor

Raw Data from Figures

有时候我们经常会在文献中看到许多图表,特别是一些表示两个变量关系的散点图,但作者往往不一定提供原始数据,我们当然可以想办法联系作者获取原始数据,但有时候这样不但成功率不高,而且像一些早年的文献,可能作者无法联系,甚至原始数据已经无法获得了. 那么有什么办法么?今天看到Wu Lingfei写了一个文章,讲"摄影法"求原始数据,说白了就是拍(或扫描)一张无透视的图片,稍加处理便可得到其相对准确的原始数据.我在这里改良了一下原始方法,发挥建院同学的优势,可以前期用PS辅助处理一下,以增加准确

DICOM设备Raw Data与重建

DICOM设备Raw Data与重建     现在的医疗影像设备基本都已DICOM为标准.但现在许多医院的技术人员都以为只要支持DICOM就一切OK,其实不然.DICOM中有Storage.Print.Worklist.Storage Commitment等很多部分.影像传输其实只用到了Storage部分. 分清楚了不同DICOM功能,每一个功能中还分SCU/SCP.U是User,P是Provider.某项功能动作的发起者就是User,反之是Provider.例如:Storage.设备要往其他服

ISP模块之色彩增强算法--HSV空间Saturation通道调整 .

色彩增强不同于彩色图像增强,图像增强的一般处理方式为直方图均衡化等,目的是为了增强图像局部以及整体对比度.而色彩增强的目的是为了使的原有的不饱和的色彩信息变得饱和.丰富起来.对应于Photoshop里面的“色相/饱和度”调节选项里面对饱和度的操作.色彩增强的过程,并不改变原有彩色图像的颜色以及亮度信息. 在我的色彩增强算法模块里面,始终只针对色彩饱和度(Saturation)信息做研究,调整.这样的话,那就不得不介绍HSV颜色空间了,H代表Hue(色彩),S代表Saturation(饱和度),V

vooya --- a YUV player and a generic raw data player

vooya是一个raw数据播放器,可播放yuv数据,兼容win.linex以及mac平台. 下载地址:https://www.offminor.de/(见最下面) ubuntu需要安装依赖: apt -f install libqt4-core libqt4-gui apt install libqt5core5a libqt5gui5 libqt5widgets5 libqt5network5 libqt5xml5 原文地址:https://www.cnblogs.com/jiu0821/p/

ISP模块之彩色图像增强--ACE算法 .

ACE(Automatic Color Enhancement),自动色彩增强算法,是一种对于彩色图像增强十分行之有效的方法.它的改进算法以及快速实现在文章Automatic Color Enhancement (ACE) and its Fast Implementation,2012中提出. 在NxN的图像上,ACE算法的算法复杂度为O(N^4),文章提出的新的ACE算法采取了两种近似的方法,一是采用多项式函数逼近坡度函数(Slope function)降低卷积计算量,二是采用不同程度的插值

kitti raw data development kit的使用

run_demoVelodyne.m使用:http://blog.csdn.net/qq_33801763/article/details/78959205   https://www.cnblogs.com/zoucheng/p/7860827.html   https://www.zhihu.com/question/67428995/answer/253652303 原文地址:https://www.cnblogs.com/ymjyqsx/p/8337969.html