滤波、形态学腐蚀与卷积(合集)

https://blog.csdn.net/qq_36285879/article/details/82810705

S1.1 滤波、形态学腐蚀与卷积(合集)

参考:《学习OpenCV3》、《数字图像处理编程入门》
文章目录

S1.1 滤波、形态学腐蚀与卷积(合集)
滤波器
简单模糊与方形滤波
中值滤波
高斯滤波
双边滤波
导数和梯度
Sobel算子
Scharr滤波器
拉普拉斯变换
图像形态学
膨胀&腐蚀
通用形态学函数
开操作与闭操作
形态学梯度
顶帽和黑帽
滤波器

毛星云那本有滤波器源码解析。

简单模糊与方形滤波

用blur函数实现
在imgproc中我们找到定义:(为了大家训练英文,就不翻译了,其实是我懒-。-)

/*
The call `blur(src, dst, ksize, anchor, borderType)` is equivalent to `boxFilter(src, dst, src.type(), anchor, true, borderType)`.和boxFilter相等,待会会讲

@param src input image; it can have any number of channels, which are processed independently, but the depth should be CV_8U, CV_16U, CV_16S, CV_32F or CV_64F.
@param dst output image of the same size and type as src.
@param ksize blurring kernel size.
@param anchor anchor point; default value Point(-1,-1) means that the anchor is at the kernel
center.默认为中心
@param borderType border mode used to extrapolate pixels outside of the image, see #BorderTypes
@sa boxFilter, bilateralFilter, GaussianBlur, medianBlur
*/
CV_EXPORTS_W void blur( InputArray src, OutputArray dst,
Size ksize, Point anchor = Point(-1,-1),
int borderType = BORDER_DEFAULT );
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <opencv2/opencv.hpp>
#include <iostream>
#include <cstdio>

using namespace std;
using namespace cv;

int main()
{
Mat src = imread("images/favorite/Lena.jpg", 0);
Mat dst0, dst1, dst2, dst3;

blur(src, dst0, Size(5,5), Point(-1,-1), BORDER_DEFAULT);

imshow("src", src);
imshow("blur5x5,default", dst0);

waitKey(0);
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
这是一种低通滤波器(low pass filter),把中间像素值替换为21x21个像素的平均值。

在链接中就讲到:

在灰度连续变化的图象中,如果出现了与相邻象素的灰度相差很大的点,比如说一片暗区中突然出现了一个亮点,人眼能很容易觉察到。就象看老电影时,由于胶片太旧,屏幕上经常会出现一些亮斑。这种情况被认为是一种噪声。灰度突变在频域中代表了一种高频分量,低通滤波器的作用就是滤掉高频分量,从而达到减少图象噪声的目的。当然这种方法会对原本的图像造成伤害。

用boxFilter函数实现
多了一个ddepth参数(图像深度),一个normalize参数(归不归一化,就是除不除滤波器面积)

#include <opencv2/opencv.hpp>
#include <iostream>
#include <cstdio>

using namespace std;
using namespace cv;

int main()
{
Mat src = imread("images/favorite/Lena.jpg", 0);
Mat dst0, dst1, dst2, dst3;

blur(src, dst0, Size(11,11), Point(-1,-1), BORDER_DEFAULT);
boxFilter(src, dst1, CV_8U, Size(11, 11), Point(-1, -1), true, BORDER_DEFAULT);
boxFilter(src, dst2, CV_8U, Size(11, 11), Point(-1, -1), false, BORDER_DEFAULT);
boxFilter(src, dst3, CV_16U, Size(11, 11), Point(-1, -1), false, BORDER_DEFAULT);

imshow("src", src);
imshow("blur11x11,default", dst0);
imshow("boxFilter11x11,default", dst1);
imshow("boxFilter11x11,false,default", dst2);
imshow("boxFilter11x11,16U,default", dst3);

waitKey(0);
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

中值滤波

之前找的是平均值,现在找的是中值。这也是一种低通滤波器

参数类型Size也变为了int,只能处理正方形区域。(不知道为啥要这样改)

#include <opencv2/opencv.hpp>
#include <iostream>
#include <cstdio>

using namespace std;
using namespace cv;

int main()
{
Mat src = imread("images/favorite/Lena.jpg", 0);
Mat dst0, dst1, dst2, dst3;

blur(src, dst0, Size(11,11), Point(-1,-1), BORDER_DEFAULT);
medianBlur(src, dst1, 11);

imshow("src", src);
imshow("blur11x11,default", dst0);
imshow("medianBlur11", dst1);

waitKey(0);
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

很有艺术风格呀。可能就是因为中值滤波是实实在在的图像原有的像素值的原因。

高斯滤波

是一种有效的滤波器。

因为以模板中心位置为原点,所以二维高斯公式中的μ1与μ2 \mu_1与\mu2μ
1
?
与μ2都等于0。

σ \sigmaσ越大,高斯函数越不凸,对应的卷积模板大小也就是越大。

/*
@param src input image; the image can have any number of channels, which are processed
independently, but the depth should be CV_8U, CV_16U, CV_16S, CV_32F or CV_64F.输入
@param dst output image of the same size and type as src.输出
@param ksize Gaussian kernel size. ksize.width and ksize.height can differ but they both must be positive and odd. Or, they can be zero‘s and then they are computed from sigma.

@param sigmaX Gaussian kernel standard deviation in X direction.
@param sigmaY Gaussian kernel standard deviation in Y direction; if sigmaY is zero, it is set to be equal to sigmaX, if both sigmas are zeros, they are computed from ksize. width and ksize.height, respectively (see #getGaussianKernel for details); to fully control the result regardless of possible future modifications of all this semantics, it is recommended to specify all of ksize, sigmaX, and sigmaY.如果sigmaY=0,(默认也是0),就和sigmaX相等。如果sigmaX=sigmaY=0,sigmaX和sigmaY自动适应ksize。具体看getGaussianKernel函数

@param borderType pixel extrapolation method, see #BorderTypes

@sa sepFilter2D, filter2D, blur, boxFilter, bilateralFilter, medianBlur
*/
CV_EXPORTS_W void GaussianBlur( InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY = 0, int borderType = BORDER_DEFAULT );
1
2
3
4
5
6
7
8
9
10
11
12
13
14
getGaussianKernel函数
getGaussianKernel返回一个高斯核矩阵,不过它输出的是一维矩阵。。。具体可以看这篇blog:

https://blog.csdn.net/u012633319/article/details/80921023

CV_EXPORTS_W Mat getGaussianKernel( int ksize, double sigma, int ktype = CV_64F );
1
高斯滤波演示
#include <opencv2/opencv.hpp>
#include <iostream>
#include <cstdio>

using namespace std;
using namespace cv;

int main()
{
Mat src = imread("images/favorite/Lena.jpg", 0);
Mat dst0, dst1, dst2, dst3;

blur(src, dst0, Size(11,11), Point(-1,-1), BORDER_DEFAULT);
medianBlur(src, dst1, 11);
GaussianBlur(src, dst2, Size(11,11), 0, 0);

imshow("src", src);
imshow("blur11x11,default", dst0);
imshow("medianBlur11", dst1);
imshow("GraussianBlur11,1,1", dst2);

waitKey(0);
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

可以看出,由于加强与邻域的关系,高斯滤波更不模糊。(也有可能是参数的原因)

高斯模糊把边缘也模糊了,边缘变粗。

双边滤波

能解决高斯不能解决的边缘问题。

《学习OpenCV》说能产生卡通效果,我感觉看不出来,如果调的好,说不定能产生倩女幽魂的效果。

#include <opencv2/opencv.hpp>
#include <iostream>
#include <cstdio>

using namespace std;
using namespace cv;

int main()
{
Mat src = imread("images/favorite/Lena.jpg", 0);
Mat dst0, dst1, dst2, dst3;

blur(src, dst0, Size(11,11), Point(-1,-1), BORDER_DEFAULT);
medianBlur(src, dst1, 11);
GaussianBlur(src, dst2, Size(11,11), 2, 0);
bilateralFilter(src, dst3, 16, 150, 150);

imshow("src", src);
imshow("blur11x11,default", dst0);
imshow("medianBlur11", dst1);
imshow("GraussianBlur11,1,1", dst2);
imshow("bilateralFilter11", dst3);

waitKey(0);
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

导数和梯度

卷积可以近似计算导数,当然这个涉及时域的知识。

从梯度图我们可以观察到图像的边缘了。

Sobel算子

百度百科就可以理解Sobel算子是怎么回事了:

https://baike.baidu.com/item/Sobel算子/11000092?fr=aladdin

其实就是常用的两个固定模板。

当然还是强烈推荐好书:《数字图像处理编程入门》:微盘数字图像处理编程入门 里面用很简洁的方法解释了Sobel为啥能检测边缘。

#include <opencv2/opencv.hpp>
#include <iostream>
#include <cstdio>

using namespace std;
using namespace cv;

int main()
{

Mat src = imread("images/favorite/Lena.jpg", 0);
Mat dst0, dst1, dst2, dst3, dst4;

Sobel(src, dst0, CV_8U, 1, 1);
Sobel(src, dst1, CV_8U, 0, 1);
Sobel(src, dst2, CV_8U, 1, 0);
Sobel(src, dst3, CV_8U, 1, 2);
Sobel(src, dst4, CV_8U, 2, 1);

imshow("src", src);
imshow("Sobel,1,1", dst0);
imshow("Sobel,0,1", dst1);
imshow("Sobel,1,0", dst2);
imshow("Sobel,1,2", dst3);
imshow("Sobel,2,1", dst4);

waitKey(0);
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

我们对x求导则得到竖的边缘,对y求导得到横的边缘。

Sobel算子的缺点是核较小的时候准确率不高。对于大型的核,精度不太显著。(用Scharr滤波器可以解决)【不是很理解】

Scharr滤波器

同Sobel一样,是常用的固定模板。

把Sobel函数的ksize设置为CV_SCHARR即可。

可以自己试一下,感觉没差。

拉普拉斯变换

经典变换

这是一种高通滤波器。(中间为负数)

直接上代码好了:

#include <opencv2/opencv.hpp>
#include <iostream>
#include <cstdio>

using namespace std;
using namespace cv;

int main()
{
Mat src = imread("images/favorite/Lena.jpg");
Mat dst0, dst1, dst2, dst3, dst4;

Laplacian(src, dst0, CV_8U, 1);
Laplacian(src, dst2, CV_8U, 3);

imshow("src", src);
imshow("Laplacian,1", dst0);
imshow("Laplacian,3", dst2);

waitKey(0);
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

效果的确很好。

图像形态学

图像形态学能做出好玩的一些操作。

膨胀&腐蚀

膨胀和腐蚀是相反的一组操作。它依据图像的亮度。

在OpenCV中,膨胀和腐蚀的边界用的的空白常量填充(BORDER_CONSTANT)。

#include <opencv2/opencv.hpp>
#include <iostream>
#include <cstdio>

using namespace std;
using namespace cv;

int main()
{
Mat src;
Mat dst0, dst1;

src = imread("images/favorite/Lena.jpg");

// int g_nStructElementSize = 3;

// Mat element0 = getStructuringElement(MORPH_RECT,
// Size(2*g_nStructElementSize+1, 2*g_nStructElementSize+1),
// Point(g_nStructElementSize, g_nStructElementSize));
// Mat element = getStructuringElement(MORPH_RECT, Size(15, 15));

erode(src, dst0, Mat());
dilate(src, dst1, Mat());

imshow("erode", dst0);
imshow("dilate", dst1);

waitKey(0);
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

左边杨幂,右边白眼妞。哈哈哈。

另外,膨胀操作能把一张小狗图变成毛绒小狗图。

通用形态学函数

这个函数包含了多种形态学方法,由参数op决定:

操作值 形态学操作名 是否需要零时图像
cv::MOP_OPEN 开操作 否
cv::MOP_CLOSE 闭操作 否
cv::MOP_GRADIENT 形态学梯度 总是需要
cv::MOP_TOPHAT 顶帽操作 就地需要
cv::MOP_BACKHAT 底帽操作 就地需要
开操作与闭操作

开操作就把图像先腐蚀后膨胀。闭操作反之。

当你设定多次迭代的时候,实际顺序是:膨胀-膨胀-腐蚀-腐蚀

#include <opencv2/opencv.hpp>
#include <iostream>
#include <cstdio>

using namespace std;
using namespace cv;

int main()
{
Mat src;
Mat dst0, dst1, dst2, dst3;

src = imread("images/favorite/Lena.jpg");

morphologyEx(src, dst0, CV_MOP_OPEN, Mat(), Point(-1, -1), 2);
morphologyEx(src, dst1, CV_MOP_OPEN, Mat(), Point(-1, -1), 3);
morphologyEx(src, dst2, CV_MOP_CLOSE, Mat(), Point(-1, -1), 2);
morphologyEx(src, dst3, CV_MOP_CLOSE, Mat(), Point(-1, -1), 3);

imshow("open2", dst0);
imshow("open3", dst1);
imshow("close2", dst2);
imshow("close3", dst3);

waitKey(0);
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

形态学梯度

gradient(src)=dilate(src)−erode(src) gradient(src) = dilate(src) - erode(src)
gradient(src)=dilate(src)−erode(src)

//
//// cout << src;
// cvtColor(src, src, CV_HSV2BGR);
// imshow("src", src);
//
// waitKey(0);
// return 0;
//}

//16.腐蚀与膨胀
#include <opencv2/opencv.hpp>
#include <iostream>
#include <cstdio>

using namespace std;
using namespace cv;

int main()
{
Mat src;
Mat dst0, dst1, dst2, dst3;

src = imread("images/favorite/Lena.jpg", 0);

morphologyEx(src, dst0, CV_MOP_GRADIENT, Mat());

imshow("gradient", dst0);

waitKey(0);
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

有点像粉笔画。

顶帽和黑帽

TopHat(src)=src−open(src)BackHat(src)=close(src)−src TopHat(src) = src-open(src)\\BackHat(src)= close(src) - src
TopHat(src)=src−open(src)
BackHat(src)=close(src)−src

---------------------
作者:nerd呱呱
来源:CSDN
原文:https://blog.csdn.net/qq_36285879/article/details/82810705
版权声明:本文为博主原创文章,转载请附上博文链接!

原文地址:https://www.cnblogs.com/jukan/p/10947321.html

时间: 2024-10-29 16:35:04

滤波、形态学腐蚀与卷积(合集)的相关文章

转载:2013计算机视觉代码合集

转载,原文地址http://blog.csdn.net/daoqinglin/article/details/23607079 -------------------------------------------------------------------------- 来源: http://www.yuanyong.org/cv/cv-code-one.html http://www.yuanyong.org/cv/cv-code-two.html http://www.yuanyong

图像拼接 SIFT资料合集

图像拼接SIFT资料合集 转自 http://blog.csdn.net/stellar0/article/details/8741780 分类: 最近也注意一些图像拼接方面的文章,很多很多,尤其是全景图拼接的,实际上类似佳能相机附加的软件,好多具备全景图拼接,多幅图像自动软件实现拼接,构成(合成)一幅全景图像(风景).Sift算法,我略知一二,无法仔细描述(刚也贴了2个最近的资料).      当就尺度空间(scale space),我想,其在计算机视觉(Computer Vision)\图像

机器学习和深度学习资料合集

机器学习和深度学习资料合集 注:机器学习资料篇目一共500条,篇目二开始更新 希望转载的朋友,你可以不用联系我.但是一定要保留原文链接,因为这个项目还在继续也在不定期更新.希望看到文章的朋友能够学到更多.此外:某些资料在中国访问需要梯子. <Brief History of Machine Learning> 介绍:这是一篇介绍机器学习历史的文章,介绍很全面,从感知机.神经网络.决策树.SVM.Adaboost到随机森林.Deep Learning. <Deep Learning in

Matlab命令合集 妈妈再也不用担心我不会用matlab了

matlab命令 一.常用对象操作:除了一般windows窗口的常用功能键外.1.!dir 可以查看当前工作目录的文件. !dir& 可以在dos状态下查看.2.who 可以查看当前工作空间变量名, whos 可以查看变量名细节.3.功能键:功能键 快捷键 说明方向上键 Ctrl+P 返回前一行输入方向下键 Ctrl+N 返回下一行输入方向左键 Ctrl+B 光标向后移一个字符方向右键 Ctrl+F 光标向前移一个字符Ctrl+方向右键 Ctrl+R 光标向右移一个字符Ctrl+方向左键 Ctr

重磅福利!!机器学习和深度学习学习资料合集

比較全面的收集了机器学习的介绍文章,从感知机.神经网络.决策树.SVM.Adaboost到随机森林.Deep Learning. <机器学习经典论文/survey合集> 介绍:看题目你已经知道了是什么内容,没错. 里面有非常多经典的机器学习论文值得细致与重复的阅读. <Brief History of Machine Learning>2 介绍:这是一篇介绍机器学习历史的文章.介绍非常全面.从感知机.神经网络.决策树.SVM.Adaboost到随机森林.Deep Learning.

Vim命令合集

来源:Vim命令合集 命令历史 以:和/开头的命令都有历史纪录,可以首先键入:或/然后按上下箭头来选择某个历史命令. 启动vim 在命令行窗口中输入以下命令即可 vim 直接启动vim vim filename 打开vim并创建名为filename的文件 文件命令 打开单个文件 vim file 同时打开多个文件 vim file1 file2 file3 ... 在vim窗口中打开一个新文件 :open file 在新窗口中打开文件 :split file 切换到下一个文件 :bn 切换到上一

[转载]VIM命令合集

Vim命令合集 http://www.cnblogs.com/softwaretesting/archive/2011/07/12/2104435.html 命令历史 以:和/开头的命令都有历史纪录,可以首先键入:或/然后按上下箭头来选择某个历史命令. 启动vim 在命令行窗口中输入以下命令即可 vim 直接启动vim vim filename 打开vim并创建名为filename的文件 文件命令 打开单个文件 vim file 同时打开多个文件 vim file1 file2 file3 ..

前端资源教程合集

综合类 前端知识体系 前端知识结构 Web前端开发大系概览 Web前端开发大系概览-中文版 Web Front-end Stack v2.2 En类资源汇总 免费的编程中文书籍索引 前端书籍 前端免费书籍大全 前端知识体系 免费的编程中文书籍索引 智能社 - 精通JavaScript开发 重新介绍 JavaScript(JS 教程) 麻省理工学院公开课:计算机科学及编程导论 JavaScript中的this陷阱的最全收集--没有之一 JS函数式编程指南 JavaScript Promise迷你书

减肥视频合集

薄荷味视频合集 http://www.boohee.com/posts/view/222199/1?sub_id=3 我最爱练习Insanity http://www.bilibili.com/video/av3596373/