canny边缘检测C\C++实现
来源:互联网 发布:液晶电视怎样连接网络 编辑:程序博客网 时间:2024/06/08 06:18
这个是主函数
#define PI 3.1415926#define EDGE_VALUE 235#define NON_EDGE_VALUE 16typedef unsigned char uint8;enum {HOR = 0, VER, POS45, NEG45};const int row_table[4] = {0, 1, 1, 1};const int col_table[4] = {1, 0, 1, -1};void CannyEdge(const uint8* img, int width, int height, int pitch, int low_thr, int high_thr, uint8 *edge){uint8 *lpf_img = new uint8[pitch * height];int *grad = new int[pitch * height];int *max_grad = new int[pitch * height];GaussianFilter(img, width, height, pitch, lpf_img);CalcGrad(lpf_img, width, height, pitch, grad);SuppressNonMax(grad, width, height, pitch, max_grad);GetEdge(max_grad, width, height, pitch, low_thr, high_thr, edge);delete [] lpf_img;delete [] grad;delete [] max_grad;}对图像做高斯低通滤波,这里用一个7tap的滤波器,滤波器尺寸可以根据需要做调整
二维高斯滤波可以分解成两个一维的高斯滤波,先做水平滤波,再做垂直滤波
void GaussianFilter(const uint8* srcp, int width, int height, int pitch, uint8 *dstp){int filter[7] = {1, 6, 19, 27, 19, 6, 1};int weight_sum = 79;int *fltp = filter + 3;uint8 *midp = new uint8[pitch * height];memcpy(dstp, srcp, pitch * height);memcpy(midp, srcp, pitch * height);// hor filterfor(int ver = 0; ver < height; ++ver) {for(int hor = radius; hor < width - radius; ++hor) {int sum = 0;for(int x = -radius; x <= radius; ++x) {sum += srcp[ver * pitch + hor + x] * fltp[x];}midp[ver * pitch + hor] = sum / weight_sum;}}// ver filterfor(int ver = radius; ver < height - radius; ++ver) {for(int hor = 0; hor < width; ++hor) {int sum = 0;for(int y = -radius; y <= radius; ++y) {sum += midp[(ver + y) * pitch + hor] * fltp[y];}dstp[ver * pitch + hor] = sum / weight_sum;}}delete [] midp;}
计算梯度值和法线方向
void CalcGrad(uint8 *img, int width, int height, int pitch, int *grad){const double tan225 = tan(PI / 8);const double tan675 = tan(PI * 3 / 8);memset((void*)grad, 0, pitch * height * sizeof(int));for(int ver = 0; ver < height - 1; ++ver) {for(int hor = 0; hor < width - 1; ++hor) {int offset = ver * pitch + hor;int diff_x = img[offset + 1] - img[offset];int diff_y = img[offset + pitch] - img[offset];int dir;double tanv = diff_y / (diff_x + 0.0001);if(tanv < tan225 && tanv >= -tan225) dir = HOR;else if(tanv < tan675 && tanv >= tan225) dir = POS45;else if(tanv < -tan675 || tanv >= tan675) dir = VER;else dir = NEG45;int gradient = (int)sqrt(double(diff_x * diff_x + diff_y * diff_y) );grad[offset] = (gradient << 2) + dir; // 低2位放方向,高位放梯度值}}}非最大值抑制
void SuppressNonMax(int *grad, int width, int height, int pitch, int *max_grad){memset((void*)max_grad, 0, pitch * height * sizeof(int));for(int ver = 1; ver < height - 1; ++ver) {for(int hor = 1; hor < width - 1; ++hor) {int offset = ver * pitch + hor;int dir = grad[offset] & 0x3;int row = row_table[dir];int col = col_table[dir];int offset1 = (ver + row) * pitch + hor + col;int offset2 = (ver - row) * pitch + hor - col;int grad0 = grad[offset] >> 2;int grad1 = grad[offset1] >> 2;int grad2 = grad[offset2] >> 2;if(grad0 >= grad1 && grad0 >= grad2) {max_grad[offset] = grad0;}}}}利用双阈值得到边缘,连接线
阈值可以根据需要进行设置,这里设置low_thr = 7,high_thr = 14
void GetEdge(int *max_grad, int width, int height, int pitch, int low_thres, int high_thres, uint8 *edge){memset(edge, NON_EDGE_VALUE, pitch * height);for(int ver = 1; ver < height-1; ++ver) {for(int hor = 1; hor < width-1; ++hor) {int offset = ver * pitch + hor;if(max_grad[offset] >= high_thres) { edge[offset] = EDGE_VALUE;}else if(max_grad[offset] >= low_thres) {for(int row = -1; row <= 1; ++row) {for(int col = -1; col <= 1; ++col) {if(max_grad[(ver + row) * pitch + hor + col] >= high_thres) {edge[offset] = EDGE_VALUE;break;}}}}}}}
左边是原图,右边是得到的边缘
0 2
- canny边缘检测C\C++实现
- Canny 边缘检测算法的C实现
- canny边缘检测算法原理与C语言实现
- opencv读图像C语言实现canny边缘检测
- C/C++ OpenCV之Canny边缘检测
- 网上流传的一个Canny边缘检测算法C语言实现的bug
- canny边缘检测C++实现
- OpenCV 实现canny边缘检测
- Win8 Metro(C#)数字图像处理--2.48Canny边缘检测算法
- Canny边缘检测基本原理与C++实现
- Opencv实现Canny算子边缘检测
- Opencv实现Canny算子边缘检测
- Linux上实现canny边缘检测
- Canny 边缘检测算子 MATLAB实现
- Canny边缘检测及C++实现
- Canny边缘检测详解及编程实现
- Canny边缘检测算法的实现
- Canny边缘检测算法的实现
- spring mvc 的数据校验
- 设计模式之单例模式的多重实现
- Markdown编辑器Typora和Latex常用命令
- 配置u-boot 參數,構造NFS啓動Beaglebone Black板的操作系統
- 文章标题
- canny边缘检测C\C++实现
- Android学习之自己需要提高和巩固的知识
- OC NSString的定义方法
- java获取路径
- uva 1218 完美服务器 树形dp 染色问题
- Ubuntu16.04下安装ns2.35
- Hust oj 1629 统计图(水题)
- OSGI 框架搭建
- Hibernate使用注解配置映射