OpenCV实现的高斯滤波探究_1(《学习OpenCV》练习题第五章第三题ab部分)
首先看下OpenCV 官方文档对于cvSmooth各个参数的解释:
Smooths the image in one of several ways.
C: void cvSmooth(const CvArr* src, CvArr* dst, int smoothtype=CV_GAUSSIAN, int param1=3, int param2=0, double param3=0, double param4=0)
其对于每个参数的解释如下:
param1 – The first parameter of the smoothing operation, the aperture width. Must be a positive odd number (1, 3, 5, ...)
param2 – The second parameter of the smoothing operation, the aperture height. Ignored by CV_MEDIAN and CV_BILATERAL methods. In the case of simple scaled/non-scaled and Gaussian blur if param2 is zero, it is set to param1 . Otherwise it must be a positive odd number.
param3 – In the case of a Gaussian parameter this parameter may specify Gaussian (standard deviation). If it is zero, it is calculated from the kernel size:
Using standard sigma for small kernels( to
) gives better speed. If param3 is not zero, while param1 and param2 are zeros, the kernel size is calculated from the sigma (to provide accurate enough operation).
对于参数smoothtype为CV_GAUSSIAN的高斯滤波来讲,param1和param2是高斯滤波核(Gaussian kernel)的尺寸,param3为高斯核的标准差(详见博文:http://www.cnblogs.com/pegasus/archive/2011/05/20/2052031.html)。文档里已经说了当param3或者param4为零的时候,如何根据核的大小算出标准差,那么就如本题的情况,在param1和param2为零即变换核的高宽都为零的时候,如何根据param3和param4算出param1和param2呢?在OpenCV的smooth.cpp文件中有个createGaussianFilter函数,下面的代码即为当只提供标准差(平行向或者竖直向)的时候,如何算出核的大小,代码:
// automatic detection of kernel size from sigma
if( ksize.width <= && sigma1 > )
ksize.width = cvRound(sigma1*(depth == CV_8U ? : )* + )|;
if( ksize.height <= && sigma2 > )
ksize.height = cvRound(sigma2*(depth == CV_8U ? : )* + )|;
这里的sigma1即为param3,sigma2即为param4,可以看出,当图像的数据类型为8为无符号型时,核的大小(直径)为 6 * sigma + 1,大概OpenCV认为半径为3*sigma的窗口就是高斯函数能量最集中的区域。至于在图像数据类型不为CV_8U的时候为什么核就变成了8*sigma + 1 就不得而知了。
下面回到本题。
我用来做变换的原始图像为:
param1 = param2 = 9的结果图像(这时候的param3为1):
param1 = param2 = 0的结果图像(这时候的param3为1):
上面这两幅图的视觉效果差不多,事实是这两幅图像完全一样,其峰值信噪比为正无穷大。
为什么?
上面已经说了当核大小为零的时候,OpenCV会根据你提供的sigma大小来得出核的大小,这里的sigma为1,所以得到的核大小应该是7(即param1=param2=7)
那么,核大小为9和核大小为7的高斯滤波出来的结果为什么会一模一样?
在smooth.cpp文件中的createGaussianFilter函数中,有两个矩阵(数据类型为Mat)kx和ky,在size=param1=param2的时候,这两个矩阵一样,且矩阵的大小为size行1列,因此在param1=param2=9,param3=1的时候这两个矩阵为(前面的括号表示行列索引,后面为该位置的数值):
(0, 0) - 0.000134
(1, 0) - 0.004432
(2, 0) - 0.053991
(3, 0) - 0.241971
(4, 0) - 0.398943
(5, 0) - 0.241971
(6, 0) - 0.053991
(7, 0) - 0.004432
(8, 0) - 0.000134
其对应的高斯变换核为:
在param1=param2=7,param3=1的时候这两个矩阵为:
(0, 0) - 0.004432
(1, 0) - 0.053991
(2, 0) - 0.241971
(3, 0) - 0.398943
(4, 0) - 0.241971
(5, 0) - 0.053991
(6, 0) - 0.004432
其对应的高斯变换核为:
可以看出,这两个矩阵除了第一个多了最外面的上面两行和左右两列外,里面是一模一样的,同时,多出来的行或者列除了一个数值为0.0001外,其余基本是零。这也就解释了核大小为9和核大小为7的高斯滤波出来的结果几乎是一模一样的(我这儿的例子是完全一模一样)。
param1 = param2 = 9的结果图像(这时候的param3为4):
param1 = param2 = 0的结果图像(这时候的param3为4):
可以看出这两个结果的视觉效果就不一样了,下面这个比上面那个药更模糊一点,事实也证明了这点,这两张图像的PSNR为26.565127。
在param1=param2=0,param3=4的时候,其参与运算的核大小是25(4*6+1),因此与核大小为9的结果当然有差别。
param1 = param2 = 9的结果图像(这时候的param3为6):
param1 = param2 = 0的结果图像(这时候的param3为6):
这两副图像的PSNR为22.688340,也属于差距比较大的两张图像。
可以得出,第二副图像变换核大小为37,与核大小为9的变换核滤波出来的结果当然有很大区别。
总结:1. 在OpenCV所实现的高斯滤波中,param1或者param2为零(即变换核为0的时候),将根据param3或者param4的值算出变换核的大小;对于8位单通道图像,算法是size = 6*sigma + 1;
2. 在产生高斯变换核的标准差(sigma)指定时,如果两个核大小差不多,很有可能出来的滤波结果图几乎完全一模一样;
3. 在标准差固定时,变换核越大,滤波出来的图像越模糊,丢失的细节也就越多;
4. 在变换核的尺寸固定时,标准差(即sigma,param3)越大,滤波出来的图像越模糊,丢失的细节也就越多。
OpenCV实现的高斯滤波探究_1(《学习OpenCV》练习题第五章第三题ab部分)的更多相关文章
- 《学习OpenCV》练习题第四章第三题b
#include <highgui.h> #include <cv.h> #include "opencv_libs.h" /* *<学习OpenCV ...
- 《学习OpenCV》练习题第四章第三题a
#include <highgui.h> #include <cv.h> #include "opencv_libs.h" #pragma comment ...
- 《学习OpenCV》练习题第四章第八题ab
这道题是利用OpenCV例子程序里自带的人脸检测程序,做点图像的复制操作以及alpha融合. 说明:人脸检测的程序我参照了网上现有的例子程序,没有用我用的OpenCV版本(2.4.5)的facedet ...
- 《学习OpenCV》练习题第五章第二题abc
代码: #include <stdio.h> #include <opencv/highgui.h> #include <opencv/cv.h> #include ...
- 《学习OpenCV》练习题第四章第七题abc
题外话:一直是打算把这本书的全部课后编程题写完的,中间断了几个月,一直忙于其他事.现在开始补上. 这道题我不清楚我理解的题意是不是正确的,这道题可以练习用OpenCV实现透视变换(可以用于矫正在3维环 ...
- Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第五章:渲染流水线
原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第五章:渲染流水线 学习目标 了解几个用以表达真实场景的标志和2D图像 ...
- 《学习OpenCV》练习题第五章第一题ab
这道题是载入一幅带有有趣纹理的图像并用不同的模板(窗口,核)大小做高斯模糊(高斯平滑),然后比较用5*5大小的窗口平滑图像两次和用11*11大小的窗口平滑图像一次是否接近相同. 先说下我的做法,a部分 ...
- 《学习OpenCV3》第7章第4题-SVD奇异值分解的验算
原文题目: 中文翻译: 解题过程 d.使用OpenCV编写代码 , , , , ,); Mat A = static_cast< ...
- UNP学习笔记(第五章 TCP客户/服务程序实例)
我们将在本章使用前一章中介绍的基本函数编写一个完整的TCP客户/服务器程序实例 这个简单得例子是执行如下步骤的一个回射服务器: TCP回射服务器程序 #include "unp.h" ...
随机推荐
- win7 64位系统 Oracle32bit + PL/SQL访问Orale服务,Oracle 11g的安装,中文乱码问题的解决
前几天装了个Oracle32bit客户端 + PL/SQL连接不上oracle,我安装完打开PL/SQL登录界面跟正常的界面不一样,没有那个连接为Normal.SYSDBA的选项,下面有解释,至于我为 ...
- Android 第三方应用接入微信平台(2)
微信平台开放后倒是挺火的,许多第三方应用都想试下,毕竟可以利用微信 建立起来的关系链来拓展自己的应用还是挺不错的,可以节约很多在社交方 面的开销,我最近由于实习需要也在研究这个东西,不过发现网上的相关 ...
- js控制div是否显示
<!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content ...
- 64位Ubuntu 13.04 安装Bochs 2.3.5
bochs 2.3.5源码编译 网上编译bochs的资料非常多,基本的问题都有解决方案,我重点讲不常见的问题. 基本安装步骤 tar vxzf bochs-2.3.5.tar.gz cd bochs- ...
- Jqgrid入门-Jqgrid分组的实现(八)
上一章主要说明了如果实现Jqgrid列数据拖动,这一章主要讨论在Jqgrid中如何实现分组功能. 类似于Sql语句的Group By,Jqgrid提供了属性实现数据分组,这样表现数据会 ...
- UVa 156 Ananagrams
题意:给出一些单词,在这些单词里面找出不能通过字母重排得到的单词(判断的时候不用管大小写),然后按照字典序输出. 学习的紫书的map= = 将每一个单词标准化 先都转化为小写,再排序(即满足了题目中说 ...
- AngularJS分页实现
基本思路 一开始页码为1,Service向服务器端获取对应信息:点击上/下一页/跳转,通过对应的页码向服务器端获取对应的信息. 由于后台暂时没弄好,我实现的过程中直接读取准备好的JSON文件,通过页码 ...
- 关闭oom killer
最近有位 VPS 客户抱怨 MySQL 无缘无故挂掉,还有位客户抱怨 VPS 经常死机,登陆到终端看了一下,都是常见的 Out of memory 问题.这通常是因为某时刻应用程序大量请求内存导致系统 ...
- 【英语】Bingo口语笔记(77) - 临时改变计划的表达
- 【转】session setup failed: NT_STATUS_LOGON_FAILURE -- 不错
原文网址:http://blog.sina.com.cn/s/blog_5cdb72780100l26f.html samba服务器出现“session setup failed: NT_STATUS ...