1. 平滑处理
“平滑处理“(smoothing)也称“模糊处理”(bluring),是一项简单且使用频率很高的图像处理方法。平滑处理的用途有很多,最常见的是用来减少图像上的噪点或者失真。在涉及到降低图像分辨率时,平滑处理是非常好用的方法。
2. 图像滤波与滤波器
图像滤波,即在尽量保留图像细节特征的条件下对目标图像的噪声进行抑制,是图像预处理中不可缺少的操作,其处理效果的好坏将直接影响到后续图像处理和分析的有效性和可靠性。消除图像中的噪声成分叫作图像的平滑化或滤波操作。
信号或图像的能量大部分集中在幅度谱的低频和中频段是很常见的,而在较高频段,感兴趣的信息经常被噪声淹没。因此一个能降低高频成分幅度的滤波器就能够减弱噪声的影响。图像滤波的目的有两个:一是抽出对象的特征作为图像识别的特征模式;另一个是为适应图像处理的要求,消除图像数字化时所混入的噪声。而对滤波处理的要求也有两条:一是不能损坏图像的轮廓及边缘等重要信息;二是使图像清晰视觉效果好。平滑滤波是低频增强的空间域滤波技术。它的目的有两类:一类是模糊;另一类是消除噪音。(各种“两",:))
空间域的平滑滤波一般采用简单平均法进行,就是求邻近像元点的平均亮度值。邻域的大小与平滑的效果直接相关,邻域越大平滑的效果越好,但邻域过大,平滑会使边缘信息损失的越大,从而使输出的图像变得模糊,因此需合理选择邻域的大小。关于滤波器,一种形象的比喻法是:我们可以把滤波器想象成一个包含加权系数的窗口,当使用这个滤波器平滑处理图像时,就把这个窗口放到图像之上,透过这个窗口来看我们得到的图像。
3. 邻域算子与线性邻域滤波
邻域算子(局部算子)是利用给定像素周围的像素值的决定此像素的最终输出值的一种算子。而线性邻域滤波是一种常用的邻域算子,像素的输出值取决于输入像素的加权和,具体过程如下图。邻域算子除了用于局部色调调整以外,还可以用于图像滤波,实现图像的平滑和锐化,图像边缘增强或者图像噪声的去除。本篇文章,我们介绍的主角是线性邻域滤波算子,即用不同的权重去结合一个小邻域内的像素,来得到应有的处理效果。
图注:邻域滤波(卷积):左边图像与中间图像的卷积产生右边图像。目标图像中蓝色标记的像素是利用原图像中红色标记的像素计算得到的。
线性滤波处理的输出像素值是输入像素值的加权和 :
其中的加权和为 ,我们称其为“核”,滤波器的加权系数,即滤波器的“滤波系数”。
4. 均值滤波
均值就是平均的意思,对邻近的像素做个平均:x[i][j]=1/9(y[i-1][j-1]+y[i-1][j]+y[i-1][j+1]+y[i][j-1]+y[i][j]+y[i][j+1]+y[i+1][j-1]+y[i+1][j]+y[i+1][j+1]);
存在缺陷:即它不能很好地保护图像细节,在图像去噪的同时也破坏了图像的细节部分,从而使图像变得模糊,不能很好地去除噪声点。特别是椒盐噪声;
可以i通过下面看出:
using namespace std; using namespace cv; #define SRCIMAGE "原图" #define SLATIMAGE "盐焦噪声原图" #define MEANFILTER "自定义均值滤波" #define MEANFILTER1 "OpenCV 均值滤波" void salt(Mat& image, int num); void AverFiltering(const Mat& src, Mat& dst); void AverFiltering1(const Mat& src, Mat& dst); void main() { Mat srcImage = imread("E:\欣奕华\项目\OPENCV\Filter\2.jpg", 1); imshow(SRCIMAGE, srcImage); salt(srcImage, 1000); imshow(SLATIMAGE, srcImage); double tick = getTickCount(); Mat dstImage; dstImage.create(srcImage.rows, srcImage.cols, srcImage.type()); blur(srcImage, dstImage, Size(3, 3)); imshow(MEANFILTER1, dstImage); tick = static_cast<double>(getTickCount() - tick) / getTickFrequency(); cout << tick; cout << endl << endl; tick = getTickCount(); AverFiltering1(srcImage, dstImage); imshow(MEANFILTER, dstImage); tick = static_cast<double>(getTickCount() - tick) / getTickFrequency(); cout << tick; waitKey(0); } void salt(Mat& image, int num) { if (image.data == NULL) return; else { int i, j; srand(time(NULL)); for (int x = 0; x < num; x++) { i = rand() % image.rows; j = rand() % image.cols; for (int n = 0; n < image.channels(); n++) { image.at<Vec3b>(i, j)[n] = 255; } } } } void AverFiltering1(const Mat& src, Mat& dst) { if (src.data == NULL) return; else { //dst.create(src.rows, src.cols, src.type()); for (int i = 1; i < src.rows; i++) { for (int j = 1; j < src.cols; j++) { if ((i - 1) >= 0 && (j - 1) >= 0 && (i + 1) < src.rows && (j + 1) < src.cols) { dst.at<Vec3b>(i, j)[0] = (src.at<Vec3b>(i, j)[0] + src.at<Vec3b>(i - 1, j)[0] + src.at<Vec3b>(i + 1, j)[0] + src.at<Vec3b>(i - 1, j - 1)[0] + src.at<Vec3b>(i, j - 1)[0] + src.at<Vec3b>(i + 1, j - 1)[0] + src.at<Vec3b>(i - 1, j + 1)[0] + src.at<Vec3b>(i, j + 1)[0] + src.at<Vec3b>(i + 1, j + 1)[0]) / 9; dst.at<Vec3b>(i, j)[1] = (src.at<Vec3b>(i, j)[1] + src.at<Vec3b>(i - 1, j)[1] + src.at<Vec3b>(i + 1, j)[1] + src.at<Vec3b>(i - 1, j - 1)[1] + src.at<Vec3b>(i, j - 1)[1] + src.at<Vec3b>(i + 1, j - 1)[1] + src.at<Vec3b>(i - 1, j + 1)[1] + src.at<Vec3b>(i, j + 1)[1] + src.at<Vec3b>(i + 1, j + 1)[1]) / 9; dst.at<Vec3b>(i, j)[2] = (src.at<Vec3b>(i, j)[2] + src.at<Vec3b>(i - 1, j)[2] + src.at<Vec3b>(i + 1, j)[2] + src.at<Vec3b>(i - 1, j - 1)[2] + src.at<Vec3b>(i, j - 1)[2] + src.at<Vec3b>(i + 1, j - 1)[2] + src.at<Vec3b>(i - 1, j + 1)[2] + src.at<Vec3b>(i, j + 1)[2] + src.at<Vec3b>(i + 1, j + 1)[2]) / 9; } else { dst.at<Vec3b>(i, j)[0] = src.at<Vec3b>(i, j)[0]; dst.at<Vec3b>(i, j)[1] = src.at<Vec3b>(i, j)[1]; dst.at<Vec3b>(i, j)[2] = src.at<Vec3b>(i, j)[2]; } } } } }
2. 方框滤波
3 .中值滤波
4.高斯滤波
…………
后面还有很多滤波器,等后期使用时候再进一步学习,现阶段了解滤波这一概念!!!