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)代碼:
主函數:
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);
}
<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去噪效果,謝謝。