【opencv4.3.0教程】11之调整图像边缘(copyMakeBorder 与 borderInterpolate)

目录

前言

一、调整边缘

1、调整的目的

2、调整的方式

1.BORDER_CONSTANT

2.BORDER_REPLICATE

3.BORDER_REFLECT

4.BORDER_WRAP

5.BORDER_REFLECT_101

6.BORDER_ISOLATED   

二、边缘处理API-copyMakeBorder

1、API原型

2、参数

3、borderInterpolate

三、代码与结果


前言

其实,每个内心强大的人,都有其柔弱的地方吧!也希望每个人都能越来越好,能够正视自己的柔弱,不要否定自我,也不要因此而做了错事。

坚持对的事很难,但是不要因为太难,就选择放弃。放弃很容易,但是也会让你悔恨终身。

鸡汤说完,让我们走进今天的文章吧,今天带领大家了解的是调整图像的边缘。

一、调整边缘

图像边缘这个东西,我觉得大家能够理解,就是一幅图像上下左右四个边缘,选定一定的尺寸进行修改,就是调整。

1、调整的目的

既然要调整图像边缘,我们就要弄清楚,我们调整的目的是什么?

其实调整边框就是修改边框位置的像素,在修改的过程中,我们并不会修改原有位置,而是在其外添加一定像素的边框,所以我们最重要的一个就是可以调整图像的尺寸。

我们在调整边框的过程中,可以自由设置边框的样式,所以我们也可以利用调整来美化图案,给图像添加一个独特的,锦上添花的边框。

当我们对图像做某些操作可能会修改图像的尺寸,为了修改后还能再还原回原来的大小,所以我们需要调整图像的边界。

2、调整的方式

针对不同的场景,我们调整图像边界的方式也不同,在opencv中,提供了如下几种方式:

enum BorderTypes {
    BORDER_CONSTANT    = 0, //!< `iiiiii|abcdefgh|iiiiiii`  with some specified `i`
    BORDER_REPLICATE   = 1, //!< `aaaaaa|abcdefgh|hhhhhhh`
    BORDER_REFLECT     = 2, //!< `fedcba|abcdefgh|hgfedcb`
    BORDER_WRAP        = 3, //!< `cdefgh|abcdefgh|abcdefg`
    BORDER_REFLECT_101 = 4, //!< `gfedcb|abcdefgh|gfedcba`
    BORDER_TRANSPARENT = 5, //!< `uvwxyz|abcdefgh|ijklmno`

    BORDER_REFLECT101  = BORDER_REFLECT_101, //!< same as BORDER_REFLECT_101
    BORDER_DEFAULT     = BORDER_REFLECT_101, //!< same as BORDER_REFLECT_101
    BORDER_ISOLATED    = 16 //!< do not look outside of ROI
};

这几种方式是什么意思呢?让我们分别看一下吧!假如我们有如下的一幅单通道图:

 

1.BORDER_CONSTANT

这个是使用指定像素值来填充边缘,需要额外指定的像素。

如果我们指定像素值为6,那我们使用这种方式得到的边缘就是:

当然我们在实际使用中一般都是彩色图像,所以我们指定像素一般使用Scalar类型定义。

2.BORDER_REPLICATE

这个是使用用已知的边缘像素值来填充边缘。比如顶端填充的像素,使用的就是最上面一行的像素值进行填充。如果是四个角,那就用原图像中四个角的四个像素分别赋值:

3.BORDER_REFLECT

这个是使用用已知的边缘像素值来反转填充边缘。和上面的不同,我们四边是通过边缘对称反转填充,四个角是通过原图像四个顶点中心对称反转填充:

4.BORDER_WRAP

用另外一边的像素来补偿填充,就是顶部和底部的像素互相填充,左边和右边的像素互相填充,对角的像素互相填充:

 

5.BORDER_REFLECT_101

这个是使用用已知的边缘像素值来反转填充边缘。上面也有一个反转填充,这两个有什么区别呢?

我们发现这个的名字也只是在上面的基础上添加了_101,也就是说这两个是类似的。我们先看一下执行完的效果,然后大家来看一下区别:

我想大家应该能够知道这两个的区别了,就是我们反转,上面的是使用边做反转,这里使用边界像素做反转,边界的像素是不会填充到外部边缘的。当然,这只有一个像素的差距,所以对于一个正常的图像来说,我们很难看到其细微差别。

那这种方式有什么好处呢?

一方面,我们原图像边界的像素只使用了一次,不会出现两次;另一方面,我们图像的边缘拓展更加自然。

这种方式和另外两种方式是一致的,它们分别是:BORDER_REFLECT101 BORDER_DEFAULT

 

6.BORDER_ISOLATED   

这个是使用黑色进行填充,本质上就是填充0。

二、边缘处理API-copyMakeBorder

opencv提供了专门的API来帮助我们进行边缘处理。

1、API原型

我们使用的API原型如下:

void copyMakeBorder( 
    InputArray src, 
    OutputArray dst, 
    int top, 
    int bottom, 
    int left, 
    int right,
    int borderType,
    const Scalar& value = Scalar()
);

 

2、参数

具体的参数如下:

(1)InputArray类型的src ,输入图像。

(2)OutputArray类型的dst ,输出图像,图像的类型和输入图像相同,尺寸为:Size(src.cols+left+right, src.rows+top+bottom)。也就是在上下左右分别添加了尺寸。

(3)int类型的top,

(4)int类型的bottom,

(5)int类型的left,

(6)int类型的right,上面四个参数是图像要增加的边缘的像素大小。

(7)int类型的borderType,边缘的类型。参照 borderInterpolate。

(8)Scalar类型的value,borderType==BORDER_CONSTANT时的边界值

3、borderInterpolate

在上面,我们看到在边缘类型,他让参照borderInterpolate。具体如下:

int borderInterpolate(int p, int len, int borderType);

这个函数一般不会单独使用,一般都是上面的函数会默认调用该函数,来设置边缘。这个函数的作用是计算外推像素的源位置。也就是计算图像向外扩张的大小以及扩张的方式。

该函数的参数如下:

(1)int类型的p,沿其中一个轴外推像素的基于0的坐标,可能小于0或等于len。

(2)int类型的len,数组沿相应轴的长度。

(3)int类型的borderType,边缘的类型。除了cv::BORDER_TRANSPARENT 和 cv::BORDER_ISOLATED,当borderType==cv::BORDER_CONSTANT时,不管p和len为多少,函数总是返回-1。

三、代码与结果

接下来我们看一下代码和得到的结果。

/*
	作者:水亦心
	内容:core-调整图像边缘
	时间:2020年5月27日
*/

#include<iostream>
#include<opencv2\opencv.hpp>

using namespace std;
using namespace cv;


int main() {

	Mat YT = imread("./image/YiTian1.jpg");
	
	if (!YT.data)
	{
		cout << "ERROR : could not load image.\n";
		return -1;
	}
	imshow("倚天屠龙记", YT);
		
	Mat YT_new;
	int top = 30;
	int bottom = 30;
	int left = 20;
	int right = 20;
	copyMakeBorder(YT, YT_new, top, bottom, left, right, BORDER_CONSTANT, Scalar(21, 222, 214));	
	imshow("调整边框-BORDER_CONSTANT-倚天屠龙记", YT_new);

	copyMakeBorder(YT, YT_new, top, bottom, left, right, BORDER_REPLICATE);
	imshow("调整边框-BORDER_REPLICATE-倚天屠龙记", YT_new);

	copyMakeBorder(YT, YT_new, top, bottom, left, right, BORDER_REFLECT);
	imshow("调整边框-BORDER_REFLECT-倚天屠龙记", YT_new);

	copyMakeBorder(YT, YT_new, top, bottom, left, right, BORDER_WRAP);
	imshow("调整边框-BORDER_WRAP-倚天屠龙记", YT_new);

	copyMakeBorder(YT, YT_new, top, bottom, left, right, BORDER_REFLECT_101);
	imshow("调整边框-BORDER_REFLECT_101-倚天屠龙记", YT_new);

	copyMakeBorder(YT, YT_new, top, bottom, left, right, BORDER_ISOLATED);
	imshow("调整边框-BORDER_ISOLATED-倚天屠龙记", YT_new);

	waitKey(0);
	return 0;
}

得到的结果如下:

原图

 

猜你喜欢

转载自blog.csdn.net/shuiyixin/article/details/106472722