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. /*******开始编写中值滤波去噪模块--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);
}
  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>


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

去噪前后效果图:

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

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

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

    在正式开始本篇文章之前,让我们一起回顾一下CFA图像去噪的一些基本思路与方法.接着我会详细地和大家分享自己学习理解的BM3D算法,操作过程,它的优缺点,最后会给出算法效果图供参考. 在ISP模块里,研 ...

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

    本文转载自:http://blog.csdn.net/southcamel/article/details/8305873 简单来说,YUV: luma (Y) + chroma (UV) 格式, 一 ...

  3. Sensor信号输出YUV、RGB、RAW DATA、JPEG 4种方式区别

    简单来说,YUV: luma (Y) + chroma (UV) 格式, 一般情况下sensor支持YUV422格式,即数据格式是按Y-U-Y-V次序输出的RGB: 传统的红绿蓝格式,比如RGB565 ...

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

    简单来说,YUV: luma (Y) + chroma (UV) 格式, 一般情况下sensor支持YUV422格式,即数据格式是按Y-U-Y-V次序输出的RGB: 传统的红绿蓝格式,比如RGB565 ...

  5. IPC网络高清摄像机基础知识4(Sensor信号输出YUV、RGB、RAW DATA、JPEG 4种方式区别) 【转】

    转自:http://blog.csdn.net/times_poem/article/details/51682785 [-] 一 概念介绍 二 两个疑问 三 RAW和JPEG的区别 1 概念说明 3 ...

  6. 17.1.1.6 Creating a Data Snapshot Using Raw Data Files 创建一个数据快照使用 Raw Data Files

    17.1.1.6 Creating a Data Snapshot Using Raw Data Files 创建一个数据快照使用 Raw Data Files 如果数据库是大的, 复制raw 数据文 ...

  7. Using the FutureRequestExecutionService Based on classic (blocking) I/O handle a great number of concurrent connections is more important than performance in terms of a raw data throughput

    Chapter 7. Advanced topics http://hc.apache.org/httpcomponents-client-ga/tutorial/html/advanced.html ...

  8. perl模块 Compress::Raw::Lzma 的安装

    perl模块 Compress::Raw::Lzma 的安装 用 cpan 安装任意perl模块总是提示 Couldn't untar Compress-Raw-Lzma-2.070.tar: 'Ca ...

  9. DICOM设备Raw Data与重建

    DICOM设备Raw Data与重建      现在的医疗影像设备基本都已DICOM为标准.但现在许多医院的技术人员都以为只要支持DICOM就一切OK,其实不然.DICOM中有Storage.Prin ...

随机推荐

  1. 圆盘自动机 cell

    圆盘自动机 cell 一个n-m圆盘自动机,包含n个排列成一圈的方格,它们按1至n编号.每个方格中有一个整数,范围[0,m-1] .圆盘会进行d操作,每次d操作会使得每个方格中的数同时变换,变换为与其 ...

  2. 电阻 (resistance)

    电阻 (resistance) 题目描述 每次小x物理作业没做完时,总是会去和老师交流感情,他们之间由此建立起来良好的师生关系.于是有一天,老师带着一道物理难题来见小x. 这道题给出了一个有n个电阻的 ...

  3. 类复制 MemberwiseClone与Clone(深 浅 Clone)

    MemberwiseClone 方法创建一个浅表副本,具体来说就是创建一个新对象,然后将当前对象的非静态字段复制到该新对象.如果字段是值类型的,则对该字段执行逐位复制.如果字段是引用类型,则复制引用但 ...

  4. php5.3.3以上重启php-fpm的方法

    http://www.cnblogs.com/GaZeon/p/5421906.html

  5. Python实现求矩阵路径最小和,使用动态规划

    题目: 给定一些NxN的矩阵,对于任意的路线,定义其[和]为其线路上所有节点的数字的和,计算从左上角到右下角的路线和最小值.每条路线只能从某一点到其周围(上下左右)的点,不可斜行.例如: 4,6 2, ...

  6. 整数拆分问题_C++

    一.问题背景  整数拆分,指把一个整数分解成若干个整数的和 如 3=2+1=1+1+1  共2种拆分 我们认为2+1与1+2为同一种拆分 二.定义 在整数n的拆分中,最大的拆分数为m,我们记它的方案数 ...

  7. 【原创】Linux环境下的图形系统和AMD R600显卡编程(8)——AMD显卡DRM驱动初始化过程

    前面几个blog对DRM驱动.显卡的显存管理机制.中断机制都进行了一些描述,现在阅读AMD drm驱动的初始化过程应该会轻松许多. 下面是一AMD的开发人员编写的文章(先暂时放在这里,后续有时间再添加 ...

  8. Git 的使用教程

    Git是一个开源的分布式版本控制系统,用以有效.高速的处理从很小到非常大的项目版本管理. 安装Git 1.方法一:安装homebrew,然后通过homebrew安装Git. 第一步:在终端输入如下命令 ...

  9. 最近有点把b/s架构什么的,和web发展搞晕了,现在来总结总结

    Web是一种典型的分布式应用架构 分布式计算技术的架构:目前成熟的技术包括J2EE, CORBA和.NET(DCOM) 在流行c/s的1992年, OMG组织提出CORBA,很大程度的提高了分布式应用 ...

  10. win7下提权代码

    inline BOOL SetPrivilege() { HANDLE hProcess, hToken; TOKEN_PRIVILEGES NewState; LUID luidPrivilegeL ...