链码跟踪算法

来源:互联网 发布: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;}
原创粉丝点击