图像处理(五):八邻域边缘跟踪与区域生长算法
来源:互联网 发布:斗鱼裴语燕 知乎 编辑:程序博客网 时间:2024/06/05 05:38
通常在进行边缘检测之后,需要通过边缘跟踪来将离散的边缘串接起来,常使用的方法为:边缘跟踪和区域生长两种方法。边缘跟踪又分为八邻域和四邻域两种,具体原理可以参考残影、的博客:点击打开链接。
实现步骤:
1、灰度化并进行Canny边缘检测
2、按照预先设定的跟踪方向(顺时针)进行边缘跟踪
3、每次跟踪的终止条件为:8邻域都不存在轮廓
代码如下:
#include <opencv2/opencv.hpp>#include <vector>#include <time.h>using namespace cv;using namespace std;// 8 neighborsconst Point directions[8] = { { 0, 1 }, {1,1}, { 1, 0 }, { 1, -1 }, { 0, -1 }, { -1, -1 }, { -1, 0 },{ -1, 1 } };int main(){// 生成随机数RNG rng(time(0));Mat src = imread("1.jpg");Mat gray;cvtColor(src, gray, CV_BGR2GRAY);Mat Edge;// Canny边缘检测Canny(gray, Edge, 50, 100);vector<Point> edge_t;vector<vector<Point>> edges;// 边缘跟踪int i, j, counts = 0, curr_d = 0;for (i = 1; i < Edge.rows - 1; i++)for (j = 1; j < Edge.cols - 1; j++){// 起始点及当前点//Point s_pt = Point(i, j);Point b_pt = Point(i, j);Point c_pt = Point(i, j);// 如果当前点为前景点if (255 == Edge.at<uchar>(c_pt.x, c_pt.y)){edge_t.clear();bool tra_flag = false;// 存入edge_t.push_back(c_pt);Edge.at<uchar>(c_pt.x, c_pt.y) = 0; // 用过的点直接给设置为0// 进行跟踪while (!tra_flag){// 循环八次for (counts = 0; counts < 8; counts++){// 防止索引出界if (curr_d >= 8){curr_d -= 8;}if (curr_d < 0){curr_d += 8;}// 当前点坐标// 跟踪的过程,应该是个连续的过程,需要不停的更新搜索的root点c_pt = Point(b_pt.x + directions[curr_d].x, b_pt.y + directions[curr_d].y);// 边界判断if ((c_pt.x > 0) && (c_pt.x < Edge.cols - 1) &&(c_pt.y > 0) && (c_pt.y < Edge.rows - 1)){// 如果存在边缘if (255 == Edge.at<uchar>(c_pt.x, c_pt.y)){curr_d -= 2; // 更新当前方向edge_t.push_back(c_pt);Edge.at<uchar>(c_pt.x, c_pt.y) = 0;// 更新b_pt:跟踪的root点b_pt.x = c_pt.x;b_pt.y = c_pt.y;//cout << c_pt.x << " " << c_pt.y << endl;break; // 跳出for循环}}curr_d++;} // end for// 跟踪的终止条件:如果8邻域都不存在边缘if (8 == counts ){// 清零curr_d = 0;tra_flag = true;edges.push_back(edge_t);break;}} // end if} // end while}// 显示一下Mat trace_edge = Mat::zeros(Edge.rows, Edge.cols, CV_8UC1);Mat trace_edge_color;cvtColor(trace_edge, trace_edge_color, CV_GRAY2BGR);for (i = 0; i < edges.size(); i++){Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));//cout << edges[i].size() << endl;// 过滤掉较小的边缘if (edges[i].size() > 5){for (j = 0; j < edges[i].size(); j++){trace_edge_color.at<Vec3b>(edges[i][j].x, edges[i][j].y)[0] = color[0];trace_edge_color.at<Vec3b>(edges[i][j].x, edges[i][j].y)[1] = color[1];trace_edge_color.at<Vec3b>(edges[i][j].x, edges[i][j].y)[2] = color[2];}}}imshow("edge", trace_edge_color);waitKey();return 0;}
效果如下:
至于区域生长算法可以直接参考博文点击打开链接,代码写的很棒!
该勤快的时候不能懒,好吧,还是自己实现了一遍,代码如下:
#include <opencv2/opencv.hpp>#include <vector>#include <time.h>using namespace cv;using namespace std;// 8邻域const Point neighbors[8] = { { 0, 1 }, { 1, 1 }, { 1, 0 }, { 1, -1 }, { 0, -1 }, { -1, -1 }, { -1, 0 }, {-1, 1} };int main(){// 生成随机数 RNG rng(time(0));Mat src = imread("1.jpg");Mat gray;cvtColor(src, gray, CV_BGR2GRAY);Mat edges;Canny(gray, edges, 30, 100);vector<Point> seeds;vector<Point> contour;vector<vector<Point>> contours;int i, j, k;for (i = 0; i < edges.rows; i++)for (j = 0; j < edges.cols; j++){Point c_pt = Point(i, j);//如果当前点为轮廓点if (edges.at<uchar>(c_pt.x, c_pt.y) == 255){contour.clear();// 当前点清零edges.at<uchar>(c_pt.x, c_pt.y) = 0;// 存入种子点及轮廓seeds.push_back(c_pt);contour.push_back(c_pt);// 区域生长while (seeds.size() > 0){// 遍历8邻域for (k = 0; k < 8; k++){// 更新当前点坐标c_pt.x = seeds[0].x + neighbors[k].x;c_pt.y = seeds[0].y + neighbors[k].y;// 边界界定if ((c_pt.x >= 0) && (c_pt.x <= edges.rows - 1) &&(c_pt.y >= 0) && (c_pt.y <= edges.cols - 1)){if (edges.at<uchar>(c_pt.x, c_pt.y) == 255){// 当前点清零edges.at<uchar>(c_pt.x, c_pt.y) = 0;// 存入种子点及轮廓seeds.push_back(c_pt);contour.push_back(c_pt);}// end if}} // end for// 删除第一个元素seeds.erase(seeds.begin());}// end whilecontours.push_back(contour);}// end if}// 显示一下 Mat trace_edge = Mat::zeros(edges.rows, edges.cols, CV_8UC1);Mat trace_edge_color;cvtColor(trace_edge, trace_edge_color, CV_GRAY2BGR);for (i = 0; i < contours.size(); i++){Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));//cout << edges[i].size() << endl; // 过滤掉较小的边缘 if (contours[i].size() > 5){for (j = 0; j < contours[i].size(); j++){trace_edge_color.at<Vec3b>(contours[i][j].x, contours[i][j].y)[0] = color[0];trace_edge_color.at<Vec3b>(contours[i][j].x, contours[i][j].y)[1] = color[1];trace_edge_color.at<Vec3b>(contours[i][j].x, contours[i][j].y)[2] = color[2];}}}imshow("edge", trace_edge_color);waitKey();return 0;}
效果如下:
阅读全文
0 0
- 图像处理(五):八邻域边缘跟踪与区域生长算法
- 图像处理算法—区域生长
- 图像处理算法1——区域生长法
- 图像处理算法1——区域生长法
- opencv 八邻域轮廓跟踪算法
- 图像分割(区域生长)
- 数字图像处理的区域生长算法
- 数字图像处理—图像分割—串行区域(区域生长)(分裂合并)
- 【matlab 图像处理】五种边缘检测算法比较
- 图像处理算法(四)---边缘检测
- 区域生长(冈萨雷斯数字图像处理)
- 数字图像处理----区域生长
- 图像增强处理之:同态滤波与Retinex算法(三)Retinex邻域算法:SSR,MSR,MSRCR
- 区域生长(基于区域的图像分割)
- 区域生长算法:
- 区域生长算法代码
- 区域生长算法
- 区域生长算法
- flume介绍与原理
- ajax 跨域 headers JavaScript ajax 跨域请求 +设置headers 实践
- 曲海佳:我是如何用PTENGINE提升信息流广告投放效果的
- 求绝对值最大值
- 网站分析的“十字箴言”
- 图像处理(五):八邻域边缘跟踪与区域生长算法
- 国外值得关注的十三家大数据与分析公司
- iOS开发Push和Present混用返回指定控制器
- 沃达丰:2017物联网市场晴雨表(附下载)
- web前端-HTML常用链接图像标签
- <meta name="" content="">的作用
- GSMA:2026年欧洲联网能源市场将达到260亿美元
- hdu 1238 Substrings
- 一个简单的注册表单验证保持原来输入的内容实例