欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

opencv学习笔记十二:梯度算子

程序员文章站 2022-06-01 18:14:42
...

【1】Robert算子:

|opencv学习笔记十二:梯度算子| = opencv学习笔记十二:梯度算子

由于平方和不便于计算,故近似为绝对值形式:

|opencv学习笔记十二:梯度算子| =| opencv学习笔记十二:梯度算子|

实际应用中,经常采用的是另一种近似梯度:

|opencv学习笔记十二:梯度算子| =| opencv学习笔记十二:梯度算子

故Robert梯度模板为:

W1
-1 0
0 1
W2
0 -1
1 0


【2】sobel算子:由于一般经常使用奇数模板,所以引入了sobel模板,考虑权重

Wx
-1 0 1
-2 0 2
-1 0 1
Wy
-1 -2 -1
0 0 0
1 2 1

【3】prewitt算子:和sobel算子类似,只不过不考虑权重

Wx
-1 0 1
-1 0 1
-1 0 1
Wy
-1 -1 -1
0 0 0
1 1 1

【4】laplace算子:

opencv学习笔记十二:梯度算子 = f(i+1,j) + f(i-1,j) - 2f(i,j);

opencv学习笔记十二:梯度算子 = f(i,j+1) + f(i,j-1) - 2f(i,j);

opencv学习笔记十二:梯度算子 = opencv学习笔记十二:梯度算子 + opencv学习笔记十二:梯度算子 = f(i+1,j) +f(i-1,j) + f(i,j+1) +f(i,j-1) -4f(i,j);

故laplace模板为:

W
0 1 0
1 -4 1
0 1 0

考虑对角线:

W
1 1 1
1 -8 1
1 1 1

考虑权重:

W
1 4 1
4 -20 4
1 4 1
#include<opencv2/opencv.hpp>
using namespace cv;

Mat src,dst1,dst2;
int main(int arc, char** argv)
{   	
	src = imread("2.jpg");
	namedWindow("input",CV_WINDOW_AUTOSIZE);
	imshow("input", src);

	/*Robert算子
	Mat kernel_1 = (Mat_<int>(2, 2)<<1,0,0,-1);
	Mat kernel_2 = (Mat_<int>(2, 2)<< 0,-1,1,0);
	*/

	/*sobel算子
	Mat kernel_x = (Mat_<int>(3, 3) << -1,0,1,-2,0,2,-1,0,1);
	Mat kernel_y = (Mat_<int>(3, 3) << -1,-2,-1,0,0,0,1,2,1);
	*/

	//laplace算子
	//Mat kernel = (Mat_<int>(3, 3) << 0,1,0,1,-4,1,0,1,0);


	//filter2D(src, dst1, -1,kernel_x, Point(-1, -1),0.0);
	//filter2D(src, dst2, -1, kernel_y, Point(-1, -1), 0.0);
	//imshow("output1", dst1);
	//imshow("output2", dst2);

        //循环模糊,27是ESC的ASCLL码,当按下ESC时,程序退出
	int index = 0;
	int ksize = 3;
	while (true){
		int c = waitKey(40);
		if (c == 27) {			
		    break;
		}			        
	    ksize = 1 + (index % 20) * 2 ;
	    Mat kernel = Mat::ones(Size(ksize, ksize), CV_32F);
	    kernel = kernel/float(ksize* ksize);
	    filter2D(src, dst1, -1, kernel, Point(-1, -1));
	    index++;
	    imshow("output", dst1);
	}	
	waitKey(0);
	return 0;
}

laplace运行结果如下:

opencv学习笔记十二:梯度算子

循环模糊某一时刻运行结果如下:

opencv学习笔记十二:梯度算子

 

opencv中对应API函数:

sobel算子:Sobel(src, dst, ine deepth,dx,dy,int ksize);

参数解释:灰度原图像,目标图像,位深度(一般设置比原图像深,防止截断),x方向导数阶数,y方向导数阶数,模板尺寸。

sobel改进算子:Scharr(src, dst, ine deepth,dx,dy,int ksize);

参数和sobel一样,只不过Scharr的模板是:

 

Wx
-3 0 3
-10 0 10
-3 0 3
Wy
-3 -10 -3
0 0 0
3 10 3

laplace算子:Laplacian(src, dst, int deepth, int ksize);

参数解释:灰度原图像,位深度,模板尺寸。

#include<opencv2/opencv.hpp>
using namespace cv;

int main(int arc, char** argv)
{   
	Mat src, gray,dst;
	src= imread("1.jpg");
	namedWindow("input",CV_WINDOW_AUTOSIZE);
	imshow("input", src);
	GaussianBlur(src, src, Size(3, 3), 0, 0);
	cvtColor(src, gray, CV_BGR2GRAY);
	imshow("gray", gray);

	//【1】sobel算子
	//Mat gradient_x, gradient_y;
	//Sobel(gray, gradient_x, CV_16S,1,0,3);
	//Sobel(gray, gradient_y, CV_16S,0,1,3);

	//【2】Scharr算子
	//Scharr(gray, gradient_x, CV_16S, 1, 0, 1, 0);
	//Scharr(gray, gradient_y, CV_16S, 1, 0, 1, 0);*/

	//计算绝对值
	/*convertScaleAbs(gradient_x, gradient_x);
	convertScaleAbs(gradient_y, gradient_y);
	imshow("gradient_x", gradient_x);
	imshow("gradient_y", gradient_y);
	addWeighted(gradient_x, 1, gradient_y, 1, 0, dst);*/

	//【3】laplace算子
	//Laplacian(gray, dst, CV_16S, 3);
	//convertScaleAbs(dst, dst);*/

	
	//通过访问像素进行操作
	/*int rows = gradient_x.rows;
	int cols = gradient_x.cols;
	Mat dst1 = Mat::zeros(gradient_x.size(), gradient_x.type());
	for (int i = 0; i < rows; i++) {
		for (int j = 0; j < cols; j++) {
			dst1.at<uchar>(i,j) = saturate_cast<uchar>( gradient_x.at<uchar>(i, j) + gradient_y.at<uchar>(i, j));
		}
	}*/

	imshow("FinalResult", dst);
	waitKey(0);
	return 0;
}

sobel 算子分别在x方向,y方向,x和y综合方向梯度图像如下:

opencv学习笔记十二:梯度算子

Scharr 算子分别在x方向,y方向,x和y综合方向梯度图像如下:

opencv学习笔记十二:梯度算子

laplace算子运行结果如下:

opencv学习笔记十二:梯度算子