演示代码:
#include <opencv2/opencv.hpp> #include <iostream> #include <math.h> using namespace cv; int main(int argc, char** argv) { Mat src, dst,dst2,dst3,dst4,dst5,dst6,dst7; src = imread("e:/girl.png"); if (!src.data) { printf("could not load image...\n"); return -1; } Mat gray; GaussianBlur(src, dst, Size(3, 3), 0, 0); cvtColor(dst, gray, CV_BGR2GRAY); imshow("gray", gray); //测试Sobel Mat xgrad, ygrad; Sobel(gray, xgrad, CV_16S, 1, 0,3); Sobel(gray, ygrad, CV_16S, 0, 1,3); //如果没有下面两句,则Sobel的结果太暗,看不到效果 convertScaleAbs(xgrad, xgrad); convertScaleAbs(ygrad, ygrad); Mat xygrad = Mat(xgrad.size(), xgrad.type()); //合并出xygrad addWeighted(xgrad, 0.5, ygrad, 0.5, 0, xygrad); imshow("xgrad", xgrad); imshow("ygrad", ygrad); imshow("xygrad", xygrad); //手工实现xgrad,ygrad混合 Mat xygrad3 = Mat(xgrad.size(), xgrad.type()); for (int x = 0; x < xgrad.rows; x++) { for (int y = 0; y < xgrad.cols; y++) { int xg = xgrad.at<uchar>(x, y); int yg = xgrad.at<uchar>(x, y); int xy = xg + yg; xygrad3.at<uchar>(x, y) = saturate_cast<uchar>(xy); } } imshow("手工实现addWeighted", xygrad3); //测试Scharr,OpenCV中增强版的Sobel Mat xgrad2, ygrad2, xygrad2; Scharr(gray, xgrad2, CV_16S, 1, 0); Scharr(gray, ygrad2, CV_16S, 0, 1); convertScaleAbs(xgrad2, xgrad2); convertScaleAbs(ygrad2, ygrad2); addWeighted(xgrad2, 0.5, ygrad2, 0.5, 0, xygrad2); imshow("xgrad2", xgrad2); imshow("ygrad2", ygrad2); imshow("xygrad2", xygrad2); waitKey(0); return 0; }
(高斯滤波后的灰度图)
(Sobel算子求出的, x梯度、y梯度、 addWeighted函数混合后的xy梯度)
(手工实现的x,y梯度混合)
(算子Scharr实现的增强Sobel效果:x梯度、y梯度、xy混合梯度)
代码解释:
卷积应用-图像边缘提取
边缘是什么 – 是像素值发生跃迁的地方,是图像的显著特征之一,在图像特征提取、对象检测、模式识别等方面都有重要的作用。
如何捕捉/提取边缘 – 对图像求它的一阶导数
delta = f(x) – f(x-1), delta越大,说明像素在X方向变化越大,边缘信号越强,
Sobel算子
是离散微分算子(discrete differentiation operator),用来计算图像灰度的近似梯度
Soble算子功能集合高斯平滑和微分求导
又被称为一阶微分算子,求导算子,在水平和垂直两个方向上求导,得到图像X方法与Y方向梯度图像
水平梯度
垂直梯度
最终图像梯度
两个公式都可以用,最下面绝对值相加是为了加快执行速度的选择。
求取导数的近似值,kernel=3时不是很准确,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 )
cv::Scharr ( InputArray Src // 输入图像 OutputArray dst// 输出图像,大小与输入图像一致 int depth // 输出图像深度. Int dx. // X方向,几阶导数 int dy // Y方向,几阶导数. double scale = 1 double delta = 0 int borderType = BORDER_DEFAULT )
其它API
GaussianBlur( src, dst, Size(3,3), 0, 0, BORDER_DEFAULT );
cvtColor( src, gray, COLOR_RGB2GRAY );
addWeighted( A, 0.5,B, 0.5, 0, AB);
convertScaleAbs(A, B)// 计算图像A的像素绝对值,输出到图像B
---------------------
作者:hackpig
来源:www.skcircle.com
版权声明:本文章代码及资料部分或全部来自贾志刚老师的视频,勇哥只是在个人理解的基础上做学习笔记,转载请附上博文链接!

