影象處理基礎及OpenCV實現(四)
阿新 • • 發佈:2018-12-22
四、 影象去噪
1、 影象的卷積核心
影象的空域處理一般利用卷積實現,影象二維卷積方式如下:
選定一種卷積模板,下圖是典型的矩形模板和十字形模板,
然後遍歷整幅影象,假設影象在i、j處的灰度值為I_ij,那麼按矩形模板卷積後的值為
即根據模板的係數對原灰度值進行操作,根據模板的形狀和引數的不同而獲得不同的結果。這種模板也稱為影象的卷積核(kernel)。模板大小一般為奇數如33、55、7*7等,對於影象邊界一般不操作或者複製邊界擴大影象來處理。
2、 影象濾波
影象濾波是為了減小或消除影象中的噪聲,opencv中提供如下幾種濾波方式:
1) 均值濾波
將目標點和周圍的點的灰度值相加取平均,即模板的係數全部相同。使得影象更加平滑,但會減少影象邊緣高頻部分,使影象變模糊。
根據距離中心的距離設定權重,稱為加權中值濾波如下
後面高斯濾波就是一種加權濾波。
2) 中值濾波
選取模板中位於中間的灰度值作為濾波後的值,可以很好的抑制脈衝椒鹽噪聲,但同樣會弱化影象邊緣高頻部分。
3) 高斯濾波
模板是一個高斯二維影象的形狀,加重中心畫素的比例,即距離目標畫素越近,我們認為它對合成的新的灰度值貢獻越大,可以一定程度上保留影象細節和高頻部分。
上圖是19*19大小的高斯模板。
4) 雙邊濾波
雙邊濾波類似高斯濾波,但除了像高斯濾波那樣考慮位置對權重的影響,還考慮了模板畫素中顏色強度,即包含了空間域和顏色域的加權,詳細可參考這篇文章 https://blog.csdn.net/piaoxuezhong/article/details/78302920
OpenCV 提供了濾波函式:
CVAPI(void) cvSmooth( const CvArr* src, CvArr* dst,
int smoothtype CV_DEFAULT(CV_GAUSSIAN),
int size1 CV_DEFAULT(3),
int size2 CV_DEFAULT(0),
double sigma1 CV_DEFAULT(0),
double sigma2 CV_DEFAULT(0));
引數src:輸入影象
引數dst:輸出影象(注:opencv不支援原影象和輸出影象相同地址)
引數smoothtype:平滑方式
enum SmoothMethod_c
{
CV_BLUR_NO_SCALE =0, /* 對模板下的每個畫素求和*/
CV_BLUR =1,/* 均值濾波 */
CV_GAUSSIAN =2,/* 高斯平滑*/
CV_MEDIAN =3,/* 中值濾波 */
CV_BILATERAL =4/** 雙向濾波 */
};
引數size1:模板大小,預設為3
引數size2:模板大小,為0時模板大小就為size1* size1
引數sigma1:高斯引數的標準差,為0時sigma=(size/2-1)*0.3+0.8
引數sigma2:雙向濾波時色域的標準差
IplImage* addNoise(IplImage* src, int noise_type, uint noise_count)
{
IplImage *dst = cvCreateImage(cvGetSize(src), src->depth, src->nChannels);
IplImage *noise = cvCreateImage(cvGetSize(src), src->depth, src->nChannels);
CvRNG rng = cvRNG(-1);
switch (noise_type)
{
case 1: //高斯噪聲
cvRandArr(&rng, noise, CV_RAND_NORMAL, cvScalarAll(0), cvScalarAll(25));
cvAdd(src, noise, dst);
break;
case 0: //椒鹽噪聲
cvCopy(src, dst);
for (int k = 0; k<noise_count; k++)
{
//CvRNG rng = cvRNG(-1);
int i = cvRandInt(&rng) % src->height;
int j = cvRandInt(&rng) % src->width;
int m = cvRandInt(&rng) % 2;
CvScalar s = cvGet2D(src, i, j);
if (src->nChannels == 1)
{
if (m == 0)
{
s.val[0] = 255;
}
else
{
s.val[0] = 0;
}
}
else if (src->nChannels == 3)
{
if (m == 0)
{
s.val[0] = 255;
s.val[1] = 255;
s.val[2] = 255;
}
else
{
s.val[0] = 0;
s.val[1] = 0;
s.val[2] = 0;
}
}
cvSet2D(dst, i, j, s);
}
break;
default:
break;
}
cvReleaseImage(&noise);
return dst;
}
void COpenPictureDlg::OnBnClickedMedian()
{
// TODO: Add your control notification handler code here
IplImage *src = cvCreateImage(cvGetSize(m_ipl), IPL_DEPTH_8U, 3);
IplImage *src2 = cvCreateImage(cvGetSize(m_ipl), IPL_DEPTH_8U, 3);
IplImage *dst = cvCreateImage(cvGetSize(m_ipl), IPL_DEPTH_8U, 3);
cvCopy(m_ipl, src);
UpdateData(TRUE);
src2 = addNoise(src, m_nNoiseType,m_ipl->height*m_ipl->width/25);
cvSmooth(src2, dst, CV_MEDIAN, 3, 3);
// cvSmooth(src2, dst, CV_BLUR, 3, 3);
// cvSmooth(src2, dst, CV_GAUSSIAN, 5, 5);
// cvSmooth(src2, dst, CV_BILATERAL, 7, 0, 50, 10);
cvNamedWindow(_T("濾波前的影象"));
cvShowImage(_T("濾波前的影象"), src2);
cvNamedWindow(_T("濾波後的影象"));
cvShowImage(_T("濾波後的影象"), dst);
cvReleaseImage(&src);
cvReleaseImage(&src2);
cvReleaseImage(&dst);
}
程式結果:(分別在椒鹽噪聲和高斯噪聲下的表現)
1) 均值濾波
2) 中值濾波
3) 高斯濾波
4) 雙邊濾波