图像平滑算法

图像平滑与图像模糊是同一概念,主要用于图像的去噪。平滑要使用滤波器。为不改变图像的相位信息,一般使用线性滤波器,其统一形式例如以下:

%20\Large%20g(i,j)=\sum_{k,l}f(i+k,j+l)h(k,l)" data-bd-imgshare-binded="1" style="margin: 0px; padding: 0px; border: 0px; max-width: 100%;" alt="" />

当中h称为滤波器的核函数。说白了就是权值。不同的核函数代表不同的滤波器,有不同的用途。

在图像处理中。常见的滤波器包含:

  1. 归一化滤波器(Homogeneous blur)

    也是均值滤波器,用输出像素点核窗体内的像素均值取代输出点像素值。

  2. 高斯滤波器(Guassian blur)

    是实际中最经常使用的滤波器。高斯滤波是将输入数组的每个像素点与 高斯内核 卷积将卷积和当作输出像素值。高斯核相当于对输出像素的邻域赋予不同的权值,输出像素点所在位置的权值最大(相应高斯函数的均值位置)。二维高斯函数为,

    %20\Large%20G(x,y)%20=%20Ae^{\frac{-(x-u_x)^2}{2\delta_x^2}+\frac{-(y-y_x)^2}{2\delta_y^2}" data-bd-imgshare-binded="1" style="margin: 0px; padding: 0px; border: 0px; max-width: 100%;" alt="" />

  1. 中值滤波器(median blur)

    中值滤波将图像的每个像素用邻域(以当前像素为中心的正方形区域)像素的中值取代。

    对椒盐噪声最有效的滤波器,去除跳变点很有效。

  2. 双边滤波器(Bilatrial blur)

    为避免滤波器平滑图像去噪的同一时候使边缘也模糊,这样的情况下使用双边滤波器。关于双边滤波器的解释參见http://homepages.inf.ed.ac.uk/rbf/CVonline/LOCAL_COPIES/MANDUCHI1/Bilateral_Filtering.html

以下的程序将先给标准Lena图像加入椒盐噪声。分别使用4种不同的滤波器进行平滑操作,请注意观察不同滤波器对椒盐噪声的去噪效果。

程序分析及结果

/*
* FileName : image_smoothing.cpp
* Author : xiahouzuoxin @163.com
* Version : v1.0
* Date : Wed 17 Sep 2014 08:30:25 PM CST
* Brief :
*
* Copyright (C) MICL,USTB
*/
#include "cv.h"
#include "imgproc/imgproc.hpp"
#include "highgui/highgui.hpp" using namespace std;
using namespace cv; const int MAX_KERNEL_LENGTH = 10; const char *wn_name = "Smoothing"; static void salt(Mat &I, int n);
static void disp_caption(const char *wn_name, Mat src, const char *caption);
static void disp_image(const char *wn_name, Mat I); /*
* @brief
* @inputs
* @outputs
* @retval
*/
int main(int argc, char *argv[])
{
if (argc<2) {
cout<<"Usage: ./image_smoothing [file name]"<<endl;
return -1;
} Mat I = imread(argv[1], CV_LOAD_IMAGE_GRAYSCALE);
salt(I, 6000);
imshow(wn_name, I);
waitKey(0); Mat dst; // Result /* Homogeneous blur */
disp_caption(wn_name, I, "Homogeneous blur");
for (int i=1; i<MAX_KERNEL_LENGTH; i+=2) {
blur(I, dst, Size(i, i), Point(-1,-1));
disp_image(wn_name, dst);
} /* Guassian blur */
disp_caption(wn_name, I, "Gaussian blur");
for (int i=1; i<MAX_KERNEL_LENGTH; i+=2) {
GaussianBlur(I, dst, Size(i, i), 0, 0);
disp_image(wn_name, dst);
} /* Median blur */
disp_caption(wn_name, I, "Median blur");
for (int i=1; i<MAX_KERNEL_LENGTH; i+=2) {
medianBlur(I, dst, i);
disp_image(wn_name, dst);
} /* Bilatrial blur */
disp_caption(wn_name, I, "Bilatrial blur");
for (int i=1; i<MAX_KERNEL_LENGTH; i+=2) {
bilateralFilter(I, dst, i, i*2, i/2);
disp_image(wn_name, dst);
}
waitKey(0); return 0;
} /*
* @brief 显示提示文字(滤波方法)
* @inputs
* @outputs
* @retval
*/
static void disp_caption(const char *wn_name, Mat src, const char *caption)
{
Mat dst = Mat::zeros(src.size(), src.type()); putText(dst, caption, Point(src.cols/4, src.rows/2), CV_FONT_HERSHEY_COMPLEX, 1, Scalar(255,255,255)); imshow(wn_name, dst);
waitKey(0);
} /*
* @brief 显示图像
* @inputs
* @outputs
* @retval
*/
static void disp_image(const char *wn_name, Mat I)
{
imshow(wn_name, I);
waitKey(1000);
} /*
* @brief 加入椒盐噪声
* @inputs
* @outputs
* @retval
*/
static void salt(Mat &I, int n=3000)
{
for (int k=0; k<n; k++) {
int i = rand() % I.cols;
int j = rand() % I.rows; if (I.channels()) {
I.at<uchar>(j,i) = 255;
} else {
I.at<Vec3b>(j,i)[0] = 255;
I.at<Vec3b>(j,i)[1] = 255;
I.at<Vec3b>(j,i)[2] = 255;
}
}
}

上面程序的逻辑很清晰:

  1. 读入灰度图,并加入椒盐噪声(6000个噪声点):

    Mat I = imread(argv[1], CV_LOAD_IMAGE_GRAYSCALE);
    salt(I, 6000);

  2. disp_captiondisp_image函数各自是用于显示提示文字和平滑过程中的变化图像的,平滑过程中图像的变化例如以下图:

    注意观察上面的图。中值滤波(Median Blur)对椒盐噪声的效果最好!

  3. 四种滤波方法分别使用到4个OpenCV函数,这些函数的声明都在imgproc.hpp中。这些函数的前2个參数都是原图像和滤波后图像。

    归一化滤波器blur的第3个參数为滤波核窗体的大小。Size(i,i)表示ixi大小的窗体。

    高斯滤波器GaussianBlur第3个參数也是滤波核窗体的大小,第4、第5个參数分辨表示x方向和y方向的δ。

    中值滤波器medianBlur第3个參数是滤波器的长度,该滤波器的窗体为正方形。

    双边滤波器的函数原型例如以下:

    //! smooths the image using bilateral filter
    CV_EXPORTS_W void bilateralFilter( InputArray src, OutputArray dst, int d,
    double sigmaColor, double sigmaSpace,
    int borderType=BORDER_DEFAULT );
  4. 本程序使用的Makefile文件为:

     TARG=image_smoothing
    SRC=image_smoothing.cpp
    LIB=-L/usr/local/lib/
    INC=-I/usr/local/include/opencv/ -I/usr/local/include/opencv2
    CFLAGS= $(TARG):$(SRC)
    g++ -g -o $@ ${CFLAGS} $(LIB) $(INC) \
    -lopencv_core -lopencv_highgui -lopencv_imgproc \
    $^ .PHONY:clean clean:
    -rm $(TARG) tags -f

OpenCV图像处理篇之图像平滑的更多相关文章

  1. OpenCV图像处理篇之边缘检测算子

    OpenCV图像处理篇之边缘检测算子 转载: http://xiahouzuoxin.github.io/notes/ 3种边缘检测算子 一阶导数的梯度算子 高斯拉普拉斯算子 Canny算子 Open ...

  2. OpenCV图像处理篇之边缘检測算子

    3种边缘检測算子 灰度或结构等信息的突变位置是图像的边缘,图像的边缘有幅度和方向属性.沿边缘方向像素变化缓慢,垂直边缘方向像素变化剧烈.因此,边缘上的变化能通过梯度计算出来. 一阶导数的梯度算子 对于 ...

  3. OpenCV图像处理篇之腐蚀与膨胀

    转载请注明出处:http://xiahouzuoxin.github.io/notes 腐蚀与膨胀 腐蚀和膨胀是图像的形态学处理中最主要的操作,之后遇见的开操作和闭操作都是腐蚀和膨胀操作的结合运算. ...

  4. OpenCV图像处理篇之阈值操作函数

    阈值操作类型 这5种阈值操作类型保留opencv tutorials中的英文名称.依次为: Threshold Binary:即二值化,将大于阈值的灰度值设为最大灰度值.小于阈值的值设为0. Thre ...

  5. OPENCV第一篇

    了解过之前老版本OpenCV的童鞋们都应该清楚,对于OpenCV1.0时代的基于 C 语言接口而建的图像存储格式IplImage*,如果在退出前忘记release掉的话,就会照成内存泄露.而且用起来超 ...

  6. 《OpenCV图像处理编程实例》

    <OpenCV图像处理编程实例>例程复现 随书代码下载:http://www.broadview.com.cn/28573 总结+遇到的issue解决: 第一章 初识OpenCV 1.VS ...

  7. 【OpenCV第一篇】安装OpenCV

    [OpenCV第一篇]安装OpenCV 本篇主要介绍如何下载OpenCV安装程序,如何在VS2008下安装配置OpenCV,文章最后还介绍了一个使用OpenCV的简单小例子. <OpenCV入门 ...

  8. Python+OpenCV图像处理(一)

    Python+OpenCV图像处理(一): 读取,写入和展示图片 调用摄像头拍照 调用摄像头录制视频 1. 读取.写入和展示图片 图像读入:cv2.imread() 使用函数cv2.imread() ...

  9. Python+OpenCV图像处理(一)——读取显示一张图片

    先在此处先声明,后面学习python+opencv图像处理时均参考这位博主的博文https://blog.csdn.net/u011321546/article/category/7495016/2? ...

随机推荐

  1. 牛客noip前集训营(第一场)提高T1

    链接:https://www.nowcoder.com/acm/contest/172/A来源:牛客网 题目描述 小N得到了一个非常神奇的序列A.这个序列长度为N,下标从1开始.A的一个子区间对应一个 ...

  2. UVa-340-猜数字

    #include <stdio.h> char ans[1000],gus[1000]; int num[10]; int main() { int n,cnt=1; while (sca ...

  3. 解决 【xshell 5 不能使用退格键和Delete建】的问题

    ###按照图片操作即可 1,打开[文件],选择[打开]选项 2.在会话中,打开[属性] 3.点击左边[终端]下的[键盘]选项,按照如下设置 即可.

  4. 南邮CTF--md5_碰撞

    南邮CTF--难题笔记 题目:md5 collision (md5 碰撞) 解析: 经过阅读源码后,发现其代码是要求 a !=b 且 md5(a) == md5(b) 才会显示flag,利用PHP语言 ...

  5. 07 mongodb

    mongodb mongodb简介 简介 MongoDB是一个基于分布式文件存储的数据库.由C++语言编写.旨在为Web应用提供可扩展的高性能数据存储解决方案.    MongoDB是一个介于关系数据 ...

  6. LeetCode(73)Set Matrix Zeroes

    题目 Given a m x n matrix, if an element is 0, set its entire row and column to 0. Do it in place. cli ...

  7. 【HDU 6006】Engineer Assignment(状压DP)

    Problem Description In Google, there are many experts of different areas. For example, MapReduce exp ...

  8. 【HDU 3037】Saving Beans(卢卡斯模板)

    Problem Description Although winter is far away, squirrels have to work day and night to save beans. ...

  9. sed之h;H和:a;N;ba使用精解(对段落进行操作)

    1) 文本: Handle 0x0058, DMI type 20, 19 bytes Memory Device Mapped Address         Starting Address: 0 ...

  10. 使用MyBatista----上传图像

    使用MyBatis上传图像,使用的是Oracle的数据库表,有一个TEACHER表,有7列,有1列是存储图片的,类型用BLOB,最大容量是4G,以二进制的形式写入数据库表. 建立这个表的对应实体类Te ...