OpenCV计算机图像视觉基础学习笔记9——处理边缘

对边缘的处理还涉及到一些卷积的计算问题。它主要解决的是在卷积计算过程中边缘像素的处理问题。在普通的卷积计算中边缘像素是处理不到的,这里就来处理一下之前处理不到的边缘。

嗯。。。虽然效果上暂时这样不会看的太明显就是了。。


卷积边界问题

图像卷积的时候边界像素,不能被卷积操作。原因在于边界像素没有完全跟kernel重叠,所以当3×3滤波的时候会有1个像素的边缘没有被处理,5×5滤波的时候会有2个像素的边缘没有被处理。

(Emmmmm。。具体原因也许我会再探究一下,对卷积的计算原理上感觉消化的不是很透彻)

处理边缘

在卷积开始之前增加边缘像素, 填充的像素值为0或者RGB黑色,比如3×3在四周各填充1个像素的边缘,这样就能确保图像的边缘被处理。在卷积处理之后,再把这些边缘去掉。openCV中有一个默认的处理方法,即BORDER_DEFAULT,此外还有BORDER_CONSTANT可以用指定像素值填充边缘,BORDER_REPLICATE用已知的边缘像素值填充边缘,BORDER_WRAP用另外一边的像素来补偿填充。

相关API:给图像添加边缘

1
2
3
4
5
6
7
8
9
10
copyMakeBorder {
Mat src, // 输入图像
Mat dst, // 输出图像
int top, // 边缘长度,一般来说上下左右都取相同值
int bottom,
int left,
int right,
int borderType, // 边缘类型
Scalar value // 颜色
}

简单测试

这里通过按键来控制使用哪一个边缘类型。不难看出,不同的borderType总会让dst的长和宽增加(边缘),只是增加的形式不同。

这是default:

这是wrap:

这是constant:

(由于采用了随机颜色,其实这个颜色是在不断变化的)

这是replicate:

代码:

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main() {
Mat src, dst;
int ksize = 0;

src = imread("D:/pic.png");
if (!src.data) {
cout << "could not load image..." << endl;
return -1;
}
char input_WIN[] = "input image";
char output_WIN[] = "output image";

int top = (int)(0.05 * src.rows);
int bottom = (int)(0.05 * src.rows);
int left = (int)(0.05 * src.cols);
int right = (int)(0.05 * src.cols);

// 采用随机数以得到随机划线的效果
RNG rng(12345);

int borderType = BORDER_DEFAULT;
imshow(input_WIN, src);
int c = 0;
while (true) {
c = waitKey(500);
if ((char)c == 27) // esc
break;
else {
if ((char)c == 'r')
borderType = BORDER_REPLICATE;
else if ((char)c == 'w')
borderType = BORDER_WRAP;
else if ((char)c == 'c')
borderType = BORDER_CONSTANT;
else
borderType = BORDER_DEFAULT;
Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
copyMakeBorder(src, dst, top, bottom, left, right, borderType, color);
imshow(output_WIN, dst);

}
}

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main() {
Mat src, dst, dst2, dst3;
int ksize = 0;

src = imread("D:/pic.png");
if (!src.data) {
cout << "could not load image..." << endl;
return -1;
}
char input_WIN[] = "input image";
char output_WIN[] = "output image";
char no_border_output_WIN[] = "no border output image";

int top = (int)(0.05 * src.rows);
int bottom = (int)(0.05 * src.rows);
int left = (int)(0.05 * src.cols);
int right = (int)(0.05 * src.cols);

// 采用随机数以得到随机划线的效果
RNG rng(12345);

int borderType = BORDER_DEFAULT;
imshow(input_WIN, src);
int c = 0;
while (true) {
c = waitKey(500);
if ((char)c == 27) // esc
break;
else {
if ((char)c == 'r')
borderType = BORDER_REPLICATE;
else if ((char)c == 'w')
borderType = BORDER_WRAP;
else if ((char)c == 'c')
borderType = BORDER_CONSTANT;
else
borderType = BORDER_DEFAULT;
Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
copyMakeBorder(src, dst, top, bottom, left, right, borderType, color);
GaussianBlur(dst, dst2, Size(5, 5), 0, 0);
GaussianBlur(src, dst3, Size(5, 5), 0, 0);
imshow(no_border_output_WIN, dst3);
imshow(output_WIN, dst2);

}
}

waitKey(0);
return 0;
}

-------------本文结束,感谢您的阅读转载请注明原作者及出处-------------


本文标题:OpenCV计算机图像视觉基础学习笔记9——处理边缘

文章作者:Shawn Zhou

发布时间:2019年08月24日 - 10:08

最后更新:2019年08月24日 - 21:08

原始链接:http://shawnzhou.xyz/2019/08/24/19-08-24-01/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

知识无价,码字不易。对您有用,敬请打赏。金额随意,感谢关心。
0%