自定义滤波器
代码演示:
//Sboel算子 Mat kernel_x = (Mat_<int>(3, 3) << -1, 0, 1, -2, 0, 2, -1 ,0, 1); //X方向 Mat kernel_y = (Mat_<int>(3, 3) << -1, -2, -1, 0, 0, 0, 1, 2, 1); //Y方向 filter2D(src, dst, -1, kernel_x, Point(-1, -1), 0.0);
自定义高斯滤波
// 5*5大小的高斯核 Mat kernel = Mat::ones(Size(5, 5), CV_32F) / (float)(5* 5); filter2D(src, dst, -1, kernel, Point(-1, -1));
边缘处理
在卷积开始之前增加边缘像素,填充的像素值为0或者RGB黑色,比如3x3在四周各填充1个像素的边缘,这样就确保图像的边缘被处理,在卷积处理之后再去掉这些边缘。
openCV中默认的处理方法是: BORDER_DEFAULT,
此外常用的还有如下几种:
- BORDER_CONSTANT – 填充边缘用指定像素值
- BORDER_REPLICATE – 填充边缘像素用已知的边缘像素值。
- BORDER_WRAP – 用另外一边的像素来补偿填充
API:
copyMakeBorder( - Mat src, // 输入图像 - Mat dst, // 添加边缘图像 - int top, // 边缘填充长度,一般上下左右都取相同值, - int bottom, - int left, - int right, - int borderType // 边缘类型 - Scalar value )
几种填充类型:
enum BorderTypes { BORDER_CONSTANT = 0, //常值填充 BORDER_REPLICATE = 1, //原图边缘复制 BORDER_REFLECT = 2, // BORDER_WRAP = 3, //原图的另一边复制到这边 BORDER_REFLECT_101 = 4, // BORDER_TRANSPARENT = 5, // BORDER_REFLECT101 = BORDER_REFLECT_101, // BORDER_DEFAULT = BORDER_REFLECT_101, // BORDER_ISOLATED = 16 // };
边缘算子
如下图所示,相邻像素之间发生较大改变时,它它们方向上的导数值也会很大
Sobel算子
是离散微分算子(discrete differentiation operator),用来计算图像灰度的近似梯度
Soble算子功能集合高斯平滑和微分求导
又被称为一阶微分算子,求导算子,在水平和垂直两个方向上求导,得到图像X方向与Y方向梯度图像
opencv中使用改进版Scharr的算子如下:
API:
cv::Sobel ( InputArray Src // 输入图像 OutputArray 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 = BORDER_DEFAULT )
Scharr:
cv::Scharr ( InputArray Src // 输入图像 OutputArray dst// 输出图像,大小与输入图像一致 int depth // 输出图像深度. int dx. // X方向,几阶导数 int dy // Y方向,几阶导数. double scale = 1 double delta = 0 int borderType = BORDER_DEFAULT )
代码演示:
思路:
高斯平滑
转灰度
求X、Y方向梯度
梯度图融合
int sobel_boder(Mat src) { Mat blur_src, gray_src, dst; Mat xgrad, ygrad; GaussianBlur(src, blur_src, Size(3, 3), 0, 0); //高斯模糊 cvtColor(blur_src, gray_src, COLOR_BGR2GRAY); //转灰度 Sobel(gray_src, xgrad, CV_16S, 1, 0, 3); //X方向求梯度 Sobel(gray_src, ygrad, CV_16S, 0, 1, 3); //Y方向求梯度 //Scharr(gray_src, xgrad, CV_16S, 1, 0, 3); //Y方向求梯度 //Scharr(gray_src, ygrad, CV_16S, 0, 1, 3); //Y方向求梯度 convertScaleAbs(xgrad, xgrad); //计算图像的像素绝对值,输出到图像B convertScaleAbs(ygrad, ygrad); imshow("x grad", xgrad); imshow("y grad", ygrad); addWeighted(xgrad, 0.5, ygrad, 0.5,0,dst); // X Y方向梯度融合 imshow("x y add result", dst); //标准的Sobel最后梯度计算 Mat xygrad = Mat(xgrad.size(), xgrad.type()); printf("type: %d\n", xgrad.type()); for (int row = 0; row < xgrad.rows; row++) { for (int col = 0; col < xgrad.cols; col++) { int xg = xgrad.at<uchar>(row, col); int yg = ygrad.at<uchar>(row, col); int xyg = xg + yg; xygrad.at<uchar>(row, col) = saturate_cast<uchar>(xyg); } } imshow("final image", xygrad); waitKey(0); return 0; }