链码跟踪算法
来源:互联网 发布:windows xp怎么升级 编辑:程序博客网 时间:2024/06/15 10:21
链码在图像提取的后期即模式识别是一个很重要的特征,比如进行数字识别或者文字识别都会用到链码的特征,而链码的提取则可以借助于边界跟踪算法获取边界序列,注意是边界序列而不是边界,边界很容易获取,但是要想把边界的点按照一定的顺序输出则要费些功夫。下面采用边界跟踪算法获取边界,并存储在堆栈中,(这里的堆栈实际是C++容器类,是虚拟堆栈)。
利用点的八邻域信息,选择下一个点作为边界点,这个算法需要选择一个开始点,可以选择图像上是目标点,在最上,最左的点。然后查看它的八邻域的点,从右下方45°的位置开始寻找,如果是目标点,将沿顺时针90°作为下一次寻找的方向,如果不是,则逆时针45°继续寻找,一旦找到重复上面的过程。
具体的步骤在算法中有讲解。
/************************************************************************//* 查找物体的边界,输出已排序的边界序列 适应于单一区域 *//************************************************************************///若能够输出边界点的序列则是比较有用的#include<cv.h>#include <highgui.h>#include <iostream>#include <stack>using namespace std;int main(){ IplImage * image,*image2; image = cvLoadImage("E:\\image\\mapleleaf.tif",0); cvNamedWindow("image",1); cvShowImage("image",image); image2 = cvCreateImage(cvSize(image->width, image->height),image->depth,1); cvZero(image2);//image2 赋值为0 //寻找区域的左上角点 CvPoint startPoint = cvPoint(0,0); bool bFindStartpoint = false; int i ,j; unsigned char * ptr,*dst; stack<int> board;//奇数位存储x坐标,偶数位存储y坐标 //当前扫描点 CvPoint currentPoint = cvPoint(0,0); //邻域的8个点的方向 int directions[8][2] = {{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1}}; int beginDirection = 0; bool bFindBoardpoint = false;//寻找到邻域的边界点的判定 for (i = 0 ; i< image->height && bFindStartpoint == false; i++) { for (j = 0 ; j< image->width && bFindStartpoint == false; j++) { ptr = (unsigned char *)(image->imageData + i*image->widthStep + j); if (*ptr == 255) { startPoint.x = j; startPoint.y = i; bFindStartpoint = true; //cout<<"x: " << j <<"y : " <<i <<endl; } } } //进行边界跟踪 每次搜索8个方向的点 找到了即停止 currentPoint = startPoint; bFindStartpoint = false; beginDirection = 0; board.push(startPoint.x); board.push(startPoint.y); while (!bFindStartpoint) { bFindBoardpoint = false; //在8个方向寻找符合条件的边界点 while (!bFindBoardpoint) { //进行出界判定 不对啊 这张图不可能出界啊 ptr = (unsigned char *)(image->imageData + (currentPoint.y + directions[beginDirection][1])* image->widthStep + currentPoint.x + directions[beginDirection][0]); if (*ptr == 255) { bFindBoardpoint = true; currentPoint.x += directions[beginDirection][0]; currentPoint.y += directions[beginDirection][1]; /************************************************************************/ /* 此处添加序列存储的代码 */ /************************************************************************/ //一、将边界存储到图片中 dst = (unsigned char *)image2->imageData + currentPoint.y * image2->widthStep + currentPoint.x; *dst = 255; //二、将边界点的序列存储到一个堆栈中 board.push(currentPoint.x); board.push(currentPoint.y); if (currentPoint.x == startPoint.x && currentPoint.y == startPoint.y ) { bFindStartpoint = true; } //改变下次首先开始扫描的方向 beginDirection -= 2; if (beginDirection < 0) { beginDirection += 8; } } else { beginDirection ++; beginDirection = beginDirection%8; } } //cout<<"currentPoint "<<currentPoint.x <<" "<< currentPoint.y<<endl; } cvNamedWindow("image2",1); cvShowImage("image2",image2); //显示堆栈中的数据 顺时针存储,逆时针显示 //注意:显示时候堆栈中已经没有数据了/* int x,y; while(!board.empty()) { y = board.top(); board.pop(); x = board.top(); board.pop(); cout<<"x "<<x<<" y "<<y<<endl; }*/ cvWaitKey(0); return 0;}
/************************************************************************//* 轮廓跟踪算法获取物体的轮廓序列 生成边界链码 *//************************************************************************/#include<cv.h>#include <highgui.h>#include <iostream>#include <stack>using namespace std;int main(){ IplImage * image,*image2,*image3; image = cvLoadImage("E:\\image\\bottle2.tif",0); cvNamedWindow("image",1); cvShowImage("image",image); image2 = cvCreateImage(cvSize(image->width, image->height),image->depth,1); image3 = cvCreateImage(cvSize(image->width, image->height),image->depth,1); cvZero(image2);//image2 赋值为0 cvZero(image3); //寻找区域的左上角点 CvPoint startPoint = cvPoint(0,0); bool bFindStartpoint = false; int i ,j; unsigned char * ptr,*dst; stack<int> board;//奇数位存储x坐标,偶数位存储y坐标 //当前扫描点 CvPoint currentPoint = cvPoint(0,0); //邻域的8个点的方向 int directions[8][2] = {{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1}}; int beginDirection = 0; bool bFindBoardpoint = false;//寻找到邻域的边界点的判定 for (i = 0 ; i< image->height && bFindStartpoint == false; i++) { for (j = 0 ; j< image->width && bFindStartpoint == false; j++) { ptr = (unsigned char *)(image->imageData + i*image->widthStep + j); if (*ptr == 255) { startPoint.x = j; startPoint.y = i; bFindStartpoint = true; //cout<<"x: " << j <<"y : " <<i <<endl; } } } //进行边界跟踪 每次搜索8个方向的点 找到了即停止 currentPoint = startPoint; bFindStartpoint = false; beginDirection = 0; board.push(startPoint.x); board.push(startPoint.y); while (!bFindStartpoint) { bFindBoardpoint = false; //在8个方向寻找符合条件的边界点 while (!bFindBoardpoint) { //进行出界判定 不对啊 这张图不可能出界啊 ptr = (unsigned char *)(image->imageData + (currentPoint.y + directions[beginDirection][1])* image->widthStep + currentPoint.x + directions[beginDirection][0]); if (*ptr == 255) { bFindBoardpoint = true; currentPoint.x += directions[beginDirection][0]; currentPoint.y += directions[beginDirection][1]; /************************************************************************/ /* 此处添加序列存储的代码 */ /************************************************************************/ //一、将边界存储到图片中 dst = (unsigned char *)image2->imageData + currentPoint.y * image2->widthStep + currentPoint.x; *dst = 255; //二、将边界点的序列存储到一个堆栈中 board.push(currentPoint.x); board.push(currentPoint.y); if (currentPoint.x == startPoint.x && currentPoint.y == startPoint.y ) { bFindStartpoint = true; } //改变下次首先开始扫描的方向 beginDirection -= 2; if (beginDirection < 0) { beginDirection += 8; } } else { beginDirection ++; beginDirection = beginDirection%8; } } //cout<<"currentPoint "<<currentPoint.x <<" "<< currentPoint.y<<endl; } cvNamedWindow("image2",1); cvShowImage("image2",image2); //显示堆栈中的数据 顺时针存储,逆时针显示 //注意:显示时候堆栈中已经没有数据了/* int x,y; while(!board.empty()) { y = board.top(); board.pop(); x = board.top(); board.pop(); cout<<"x "<<x<<" y "<<y<<endl; }*/ //Board中存储着边界的序列 转化为8邻域链码,每隔10个点取样 显示 int lianmaLength = (board.size()+5)/10; int* lianma = new int[lianmaLength]; for (i = 0 ; i< lianmaLength && !board.empty();i += 2) { lianma[i+1] = board.top(); board.pop(); lianma[i] = board.top(); board.pop(); for (j = 0; j< 18 && !board.empty();j++) { board.pop(); } } //将数据在image3中显示 int t; for ( t = 0; t < lianmaLength;t += 2) { i = lianma[t+1]; j = lianma[t]; ptr = (unsigned char *)image3->imageData + i*image->widthStep + j; *ptr = 255; } cvNamedWindow("image3",1); cvSaveImage("E:\\image\\bottle2lianma.bmp",image3); cvShowImage("image3",image3); cvWaitKey(0); return 0;}
阅读全文
0 0
- 链码跟踪算法
- 图像八方向链码的边界跟踪算法
- 跟踪算法
- 跟踪算法(一)光流法跟踪
- 跟踪算法->Meanshift算法
- 跟踪算法之:TLD跟踪算法
- 视频跟踪算法--TLD跟踪算法介绍
- 光笔笔迹跟踪算法
- 光线跟踪的算法
- camShift跟踪算法介绍
- camShift跟踪算法介绍
- 视频跟踪算法简介
- CamShift跟踪算法
- 算法跟踪实践
- TLD跟踪算法
- TLD跟踪算法介绍
- meanShift跟踪算法概述
- camshift跟踪算法介绍
- spring实战笔记1 spring概览
- “不会聊天”这病如何治?
- HA集群-资源约束
- Markdown-新手上路
- OpenCV2学习笔记(十二):特征提取算法SIFT与SURF
- 链码跟踪算法
- 第一人称<ReactiveTarget >
- 搬家啦
- 《Inside C#》笔记(四) 类
- 数据重塑,以及长宽数据的相互转化
- POJ 1006代码实现收获
- 第一人称<Rotate>
- 2017.06.18 总结近一周学习
- 基于android的Socket通信