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

【1】Robert算子:

|\bigtriangledown f(i,j)| = \sqrt{[f(i+1,j)-f(i,j)]^2+[f(i,j+1)-f(i,j)]^2}

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

|\bigtriangledown f(i,j)| =| [f(i+1,j)-f(i,j)]+[f(i,j+1)-f(i,j)]|

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

|\bigtriangledown f(i,j)| =| [f(i+1,j+1)-f(i,j)]+[f(i,j+1)-f(i+1,j)]

故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算子:

{f_{x}}'' = f(i+1,j) + f(i-1,j) - 2f(i,j);

扫描二维码关注公众号,回复: 3096755 查看本文章

{f_{y}}'' = f(i,j+1) + f(i,j-1) - 2f(i,j);

{f}'' = {f_{x}}'' + {f_{y}}'' = 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中对应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综合方向梯度图像如下:

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

laplace算子运行结果如下:

猜你喜欢

转载自blog.csdn.net/qq_24946843/article/details/82426442
今日推荐