图像处理(四):边缘检测(二):sobel和canny
来源:互联网 发布:js实现局部刷新div 编辑:程序博客网 时间:2024/06/05 18:16
具体原理,参考博客点击打开链接,最常用的边缘检测算子有:sobel、canny、prewitt、Roberts等,sobel算子模板为:
sobel算子考虑了邻域信息,相当于对图像先做加权平均,然后再做微分运算。
Canny算子:
1、使用Gassian滤波器平滑处理;
2、使用sobel算子分别计算x,y方向梯度分量及梯度方向;
3、对梯度进行非极大值抑制;
4、使用双阈值对边缘进一步检测和增强;
实现代码如下:
#include <opencv2/opencv.hpp> #include <math.h> #include <iostream> using namespace cv;using namespace std;// define sobel kernel const int sobel_kernel_y[9] = { -1, -2, -1, 0, 0, 0, 1, 2, 1 };const int sobel_kernel_x[9] = { -1, 0, 1, -2, 0, 2, -1, 0, 1 };// 3x3 位置 const int locations[9][2] = { { -1, -1 }, { -1, 0 }, { -1, 1 },{ 0, -1 }, { 0, 0 }, { 0, 1 },{ 1, -1 }, { 1, 0 }, { 1, 1 } };// 8领域 const int neighbors[8][2] = { { -1, -1 }, { -1, 0 }, { -1, 1 }, { 0, -1 }, { 0, 1 }, { 1, -1 }, { 1, 0 }, { 1, 1 } };int main(){Mat src = imread("lena.jpg");Mat image = src.clone();GaussianBlur(src, image, Size(3, 3), 1.5);Mat gray;cvtColor(image, gray, CV_BGR2GRAY);Mat sobel_x = Mat::zeros(gray.rows, gray.cols, CV_8UC1);Mat sobel_y = Mat::zeros(gray.rows, gray.cols, CV_8UC1);Mat sobel_xy = Mat::zeros(gray.rows, gray.cols, CV_64FC1);int i, j, k;// compute sobel_x, sobel_y for (i = 1; i < gray.rows - 1; i++)for (j = 1; j < gray.cols - 1; j++){int temp_x = 0, temp_y = 0;for (k = 0; k < 9; k++){temp_x += sobel_kernel_x[k] * gray.at<uchar>(i + locations[k][0], j + locations[k][1]);temp_y += sobel_kernel_y[k] * gray.at<uchar>(i + locations[k][0], j + locations[k][1]);}sobel_x.at<uchar>(i, j) = temp_x;sobel_y.at<uchar>(i, j) = temp_y;//sobel_xy.at<double>(i, j) = sqrt(temp_x * temp_x + temp_y * temp_y);sobel_xy.at<double>(i, j) = abs(temp_x) + abs(temp_y);}Mat directions = Mat::zeros(gray.rows, gray.cols, CV_64FC1);// compute direction for (i = 1; i < gray.rows - 1; i++)for (j = 1; j < gray.cols - 1; j++){// atan2的取值范围为[-pi,pi] float t = atan2(sobel_y.at<uchar>(i, j), sobel_x.at<uchar>(i, j));if (t < 0){t += CV_PI;}directions.at<double>(i, j) = t;}float t = 0;// 非极大值抑制 for (i = 1; i < gray.rows - 1; i++)for (j = 1; j < gray.cols - 1; j++){t = directions.at<double>(i, j);// 0 - 22.5, if (((t >= 0) && (t < CV_PI / 8.0)) || ((t >= 7.0 * CV_PI / 8.0) && (t < CV_PI))){if ((sobel_xy.at<double>(i, j) < sobel_xy.at<double>(i, j + 1)) ||(sobel_xy.at<double>(i, j) < sobel_xy.at<double>(i, j - 1))){sobel_xy.at<double>(i, j) = 0;}}// 22.5 - 67.5 else if ((t >= CV_PI / 8.0) && (t < 3.0 * CV_PI / 8.0)){if ((sobel_xy.at<double>(i, j) < sobel_xy.at<double>(i - 1, j + 1)) ||(sobel_xy.at<double>(i, j) < sobel_xy.at<double>(i + 1, j - 1))){sobel_xy.at<double>(i, j) = 0;}}// 67.5 - 112.5 else if ((t >= 3.0 * CV_PI / 8.0) && (t < 5.0 * CV_PI / 8.0)){if ((sobel_xy.at<double>(i, j) < sobel_xy.at<double>(i - 1, j)) ||(sobel_xy.at<double>(i, j) < sobel_xy.at<double>(i + 1, j))){sobel_xy.at<double>(i, j) = 0;}}// 112.5 - 157.5 else if ((t >= 5.0 * CV_PI / 8.0) && (t < 7.0 * CV_PI / 8.0)){if ((sobel_xy.at<double>(i, j) < sobel_xy.at<double>(i - 1, j - 1)) ||(sobel_xy.at<double>(i, j) < sobel_xy.at<double>(i + 1, j + 1))){sobel_xy.at<double>(i, j) = 0;}}}// 双阈值滤波 float lower_t = 30;float upper_t = 100;Mat My_canny = Mat::zeros(sobel_xy.rows, sobel_xy.cols, CV_8UC1);Mat sobel_xy_mask = Mat::zeros(sobel_xy.rows, sobel_xy.cols, CV_32FC1);sobel_xy.copyTo(sobel_xy_mask);// 将两个阈值能够判断的进行判断for (i = 1; i < sobel_xy_mask.rows - 1; i++)for (j = 1; j < sobel_xy_mask.cols - 1; j++){if (sobel_xy_mask.at<double>(i, j) > upper_t){My_canny.at<uchar>(i, j) = 255;sobel_xy_mask.at <double> (i, j) = 0; // 用完就置0,方便后面的检测}if (sobel_xy_mask.at<double>(i, j) < lower_t){sobel_xy.at<double>(i, j) = 0;}}// 对两个阈值中间的部分进行增强for (i = 1; i < sobel_xy_mask.rows - 1; i++)for (j = 1; j < sobel_xy_mask.cols - 1; j++){if (sobel_xy_mask.at<double>(i, j ) >= lower_t){// 遍历八领域 ,看八邻域是否有255for (k = 0; k < 8; k++){if (My_canny.at<uchar>(i + neighbors[k][0], j + neighbors[k][1]) == 255){My_canny.at<uchar>(i, j) = 255;sobel_xy_mask.at<double>(i, j) = 0;break;}}}}Mat canny_sys;Canny(gray, canny_sys, 30, 100);namedWindow("gray", 0);resizeWindow("sobel_x", 300, 300);namedWindow("sobel_x", 0);resizeWindow("sobel_y", 300, 300);namedWindow("sobel_y", 0);resizeWindow("sobel_xy", 300, 300);namedWindow("sobel_xy", 0);resizeWindow("sobel_xy", 300, 300);namedWindow("My_canny", 0);resizeWindow("My_canny", 300, 300);namedWindow("canny_sys", 0);resizeWindow("canny_sys", 300, 300);imshow("gray", gray);imshow("sobel_x", sobel_x);imshow("sobel_y", sobel_y);imshow("sobel_xy", sobel_xy);imshow("My_canny", My_canny);imshow("canny_sys", canny_sys);waitKey();return 0;}
效果如下:
跟opencv自带的canny效果好像存在一定偏差,具体原因等过段时间研究一下源代码~
阅读全文
0 0
- 图像处理(四):边缘检测(二):sobel和canny
- 图像处理-Canny算子、Sobel算子边缘检测
- 图像边缘检测Sobel,Laplace,Canny
- 边缘检测:Canny边缘检测和sobel边缘检测比较
- opencv边缘检测Sobel和Canny
- 基于Sobel和Canny边缘检测
- 【MATLAB图像处理3】 canny边缘检测 (附源码)
- 【MATLAB图像处理3】 canny边缘检测 (附源码)
- 图像处理------Canny边缘检测
- OpenCV之imgproc 模块. 图像处理(2)实现自己的线性滤波器 给图像添加边界 Sobel 导数 Laplace 算子 Canny 边缘检测
- 边缘检测(Sobel算子,拉普拉斯算子,Canny算子)
- opencv边缘检测(robert,prewitt,sobel,canny,laplacian)
- opencv3学习之边缘检测(Canny/Sobel/Laplacian算子)
- 【OpenCV】图像变换(二)边缘检测:梯度算子、Sobel算子和Laplace算子
- OpenCV图像边缘检测(sobel算法)
- 图像处理中各种边缘检测的微分算子简单比较(Sobel,Robert, Prewitt,Laplacian,Canny)
- 图像处理中各种边缘检测的微分算子简单比较(Sobel,Robert, Prewitt,Laplacian,Canny)
- 图像处理中各种边缘检测的微分算子简单比较(Sobel,Robert, Prewitt,Laplacian,Canny)
- Jquery LigerUI-表格的使用
- STM32+CC1101 低功耗2
- 新手学习promise踩的坑
- Mac Python服务器搭建遇到的问题
- Python time strftime()方法
- 图像处理(四):边缘检测(二):sobel和canny
- excel中使用VBA将单元格的内容转为多行
- idea报错:……are only available on JDK 1.5 and higher
- java并发编程(一)-从入门到吐血
- 五、list和tuple
- 宏观理解RESTful架构
- 自动生成awr报告shell脚本--每天早8点到晚12点每四个小时生成一次
- spring中事务的aop实现
- shell学习整理(7)-别名&获取终端信息