【OpenCv】边缘处理

原理:

边缘是像素值发生跃迁的地方,是图像的显著特征之一,一般对图像求取导数求得,运用卷积操作进行运算。常用的算子有Robert算子、Sobel算子、拉普拉斯算子。

                      【OpenCv】边缘处理_第1张图片【OpenCv】边缘处理_第2张图片          【OpenCv】边缘处理_第3张图片            【OpenCv】边缘处理_第4张图片

                                Robert算子                                                Sobel算子                                         拉普拉斯算子

                                                         

                                                                                           Scharr算子

在图像卷积的时候边界像素,由于边界像素不能跟卷积核(kernel)完全重叠,不能被卷积操作,所以当3*3滤波时候有一个像素的边缘没被处理,5*5滤波的时候有2个像素的边缘没有被处理。所以在卷积的时候需要对边缘部分进行处理,一般使用填充法处理,在边缘部分增加像素,一般增加的像素值填充为0或者255,如:对于3*3的卷积核,需要在图像的四周边缘填充一个像素0或者255,对5*5的卷积核,需要在图像的四周边缘填充两个像素0或者255,卷积处理之后再去掉这些边缘。常用的Opencv填充法有以下几种:

BORDER_DEFAULT:Opencv默认的处理方法,将就近的像素进行映射

BORDER_CONSTANT:常量法,以一个常量像素值(由参数value给定)填充扩充的边界

BORDER_REPLICATE:复制法,复制最边缘的像素值

BORDER_REFLECT_101:对称法,以最边缘像素为轴,对称复制

BORDER_WRAP:用另一边的像素来补偿填充

给图像添加边缘的API:

copyMakeBorder(Mat src//输入图像,Mat dst//添加边缘后的图像,int top//边缘长度,一般上下左右取相同值,下面三个参数分别为下、左、右,int bottom,int left,int right,int borderType//填充边缘的方法,Scalar value//填充值)

Sobel算子的API:

Sobel(src//输入图像,dst//输出图像,大小和输入图像一致,int depth//输出图像深度,int dx//x方向的几阶导数,int dy//y方向的几阶导数,int ksize//sobel算子kernel大小,必须是1、3、5、7...奇数,double scale=1,double delta=0,int borderType=  //边缘填充方式自己选)

Opencv使用改进Sobel算子版本的API:

Scharr(src//输入图像,dst//输出图像,int depth//输出图像深度,int dx//x方向,几阶导数,int dy//y方向,几阶导数,double scale=1.0,double delta=0.0,int borderType=  //边缘填充方式,自己选)

Laplacian(拉普拉斯算子)的API:

Laplacian(src,dst,depth,ksize,double scale=1.0,double delta=0.0,int borderType=4)里面的参数含义和上面一致。

示例

边缘填充

#include 
#include 
#include 

using namespace cv;
int main(int argc, char** argv) {
	Mat src, dst;
	src = imread("D:/test.png");
	if (!src.data) {
		printf("could not load image...\n");
		return -1;
	}
	char INPUT_WIN[] = "input image";
	char OUTPUT_WIN[] = "Border Demo";
	namedWindow(INPUT_WIN, CV_WINDOW_AUTOSIZE);
	namedWindow(OUTPUT_WIN, CV_WINDOW_AUTOSIZE);
	imshow(INPUT_WIN, src);

	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;

	int c = 0;
	while (true) {
		c = waitKey(500);
		// ESC
		if ((char)c == 27) {
			break;
		}
		if ((char)c == 'r') {
			borderType = BORDER_REPLICATE;
		} else if((char)c == 'w') {
			borderType = BORDER_WRAP;
		} else if((char)c == 'c') {
			borderType = BORDER_CONSTANT;
		} 
		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);
	}
	

	GaussianBlur(src, dst, Size(5, 5), 0, 0);
	imshow(OUTPUT_WIN, dst);

	waitKey(0);
	return 0;
}

填充后的效果

【OpenCv】边缘处理_第5张图片【OpenCv】边缘处理_第6张图片

左面原图,右面填充后的效果图

Soble算子操作

#include 
#include 
#include 

using namespace cv;
int main(int argc, char** argv) {
	Mat src, dst;
	src = imread("D:/test.png");
	if (!src.data) {
		printf("could not load image...\n");
		return -1;
	}

	char INPUT_TITLE[] = "input image";
	char OUTPUT_TITLE[] = "sobel-demo";
	namedWindow(INPUT_TITLE, CV_WINDOW_AUTOSIZE);
	namedWindow(OUTPUT_TITLE, CV_WINDOW_AUTOSIZE);
	imshow(INPUT_TITLE, src);
	/*灰度转换*/
	Mat gray_src;
	GaussianBlur(src, dst, Size(3, 3), 0, 0);
	cvtColor(dst, gray_src, CV_BGR2GRAY);
	imshow("gray image", gray_src);

	Mat xgrad, ygrad;
	Scharr(gray_src, xgrad, CV_16S, 1, 0);//x方向上的改进soble操作
	Scharr(gray_src, ygrad, CV_16S, 0, 1);//y方向上的改进soble操作

	// Sobel(gray_src, xgrad, CV_16S, 1, 0, 3);
	// Sobel(gray_src, ygrad, CV_16S, 0, 1, 3);
	convertScaleAbs(xgrad, xgrad);//数据转化到0-255区间
	convertScaleAbs(ygrad, ygrad);
	imshow("xgrad", xgrad);
	imshow("ygrad", ygrad);
	/*x、y方向上的改进soble操作*/
	Mat xygrad = Mat(xgrad.size(), xgrad.type());
	printf("type : %d\n", xgrad.type());
	int width = xgrad.cols;
	int height = ygrad.rows;
	for (int row = 0; row < height; row++) {
		for (int col = 0; col < width; col++) {
			int xg = xgrad.at(row, col);//在坐标(row,col)处的像素点值赋给xg
			int yg = ygrad.at(row, col);
			int xy = xg + yg;
			xygrad.at(row, col) = saturate_cast(xy);//saturate_cast防止数据溢出
		}
	}
	//addWeighted(xgrad, 0.5, ygrad, 0.5, 0, xygrad);
	imshow(OUTPUT_TITLE, xygrad);

	waitKey(0);
	return 0;
}

结果图

【OpenCv】边缘处理_第7张图片【OpenCv】边缘处理_第8张图片【OpenCv】边缘处理_第9张图片【OpenCv】边缘处理_第10张图片【OpenCv】边缘处理_第11张图片

Laplcian方法处理同Soble方法,不再做示例。

你只要微笑,生活就很好!

你可能感兴趣的:(【OpenCv】边缘处理)