本文共 2537 字,大约阅读时间需要 8 分钟。
从均值滤波开始,着手实现各种常用的滤波算法。均值滤波是一种线性滤波。图像的空域滤波无非分为两种,线性滤波和非线性滤波。由于我之前对线性、非线性理解不够清晰,这次就好好总结一下吧。
线性滤波对邻域中的像素的计算为线性运算时,如利用窗口函数进行平滑加权求和的运算,或者某种卷积运算,都可以称为线性滤波。常见的线性滤波有:均值滤波、高斯滤波、盒子滤波、拉普拉斯滤波等等,通常线性滤波器之间只是模版系数不同。
非线性滤波利用原始图像跟模版之间的一种逻辑关系得到结果,如最值滤波器,中值滤波器。比较常用的有中值滤波器和双边滤波器。
根据冈萨雷斯书中的描述,均值模糊可以模糊图像以便得到感兴趣物体的粗略描述,也就是说,去除图像中的不相关细节,其中“不相关”是指与滤波器模板尺寸相比较小的像素区域,从而对图像有一个整体的认知。即为了对感兴趣的物体得到一个大致的整体的描述而模糊一幅图像,忽略细小的细节。
均值滤波本身存在着固有的缺陷,即它不能很好地保护图像细节,在图像去噪的同时也破坏了图像的细节部分,从而使图像变得模糊,不能很好地去除噪声点。特别是椒盐噪声。
均值滤波的原理很简单,一般是用下面的系数模版与图像做卷积运算,公式表示为:
$$g(x,y) = \frac{1}{n} \sum_{(x',y') \in D} f(x',y')$$
其中 (D) 是一个 (k \times k) 的邻域,(n) 是邻域中像素的数量,(g(x,y)) 是滤波后的像素值,(f(x',y')) 是原图像对应位置的像素值。
常见的模板大小有 (3 \times 3)、(5 \times 5)、(7 \times 7) 等,图像边界可以通过扩充处理(如扩充为0或邻近像素值)。
如果采用常规方法,随着模板尺寸的增大,求和计算量也急剧增大,而且模板是逐像素移动的,可见这种效率上的代价是巨大的。下一篇将介绍一种采用积分图处理的快速均值滤波方法,会大大提高执行效率,可以说是工程应用的首选!
#include#include #include #include void MeanFilter(cv::Mat& src, cv::Mat& dst, cv::Size wsize) { int hh = (wsize.height - 1) / 2; int hw = (wsize.width - 1) / 2; cv::Mat newsrc; cv::copyMakeBorder(src, newsrc, hh, hh, hw, hw, cv::BORDER_REFLECT_101); dst = cv::Mat::zeros(src.size(), src.type()); int sum = 0; int mean = 0; for (int i = hh; i < src.rows + hh; ++i) { for (int j = hw; j < src.cols + hw; ++j) { for (int r = i - hh; r <= i + hh; ++r) { for (int c = j - hw; c <= j + hw; ++c) { sum = newsrc.at (r, c) + sum; } } mean = sum / wsize.area(); dst.at (i - hh, j - hw) = mean; sum = 0; mean = 0; } }}int main() { cv::Mat src = cv::imread("I:\\Learning-and-Practice\\2019Change\\Image process algorithm\\Img\\Fig0334(a)(hubble-original).tif"); if (src.empty()) { return -1; } if (src.channels() > 1) { cv::cvtColor(src, src, CV_RGB2GRAY); } cv::Mat dst; cv::Mat dst1; cv::Size wsize(7, 7); double t2 = (double)cv::getTickCount(); MeanFilter(src, dst, wsize); t2 = (double)cv::getTickCount() - t2; double time2 = (t2 * 1000.) / ((double)cv::getTickFrequency()); std::cout << "FASTmy_process=" << time2 << " ms. " << std::endl << std::endl; cv::namedWindow("src"); cv::imshow("src", src); cv::namedWindow("dst"); cv::imshow("dst", dst); cv::imwrite("I:\\Learning-and-Practice\\2019Change\\Image process algorithm\\Image Filtering\\MeanFilter\\Mean_hubble.jpg", dst); cv::waitKey(0);}
以上代码实现了常规均值滤波算法,通过对图像边界扩充和卷积操作实现均值滤波效果。
转载地址:http://rrrfk.baihongyu.com/