找回密码
 用户注册

QQ登录

只需一步,快速开始

查看: 3628|回复: 0

图像处理基本算法 链码 边界跟踪

[复制链接]
发表于 2012-2-11 19:43:02 | 显示全部楼层 |阅读模式
链码在图像提取的后期即模式识别是一个很重要的特征,比如进行数字识别或者文字识别都会用到链码的特征,而链码的提取则可以借助于边界跟踪算法获取边界序列,注意是边界序列而不是边界,边界很容易获取,但是要想把边界的点按照一定的顺序输出则要费些功夫。下面采用边界跟踪算法获取边界,并存储在堆栈中,(这里的堆栈实际是C++容器类,是虚拟堆栈)。


利用点的八邻域信息,选择下一个点作为边界点,这个算法需要选择一个开始点,可以选择图像上是目标点,在最上,最左的点。然后查看它的八邻域的点,从右下方45°的位置开始寻找,如果是目标点,将沿顺时针90°作为下一次寻找的方向,如果不是,则逆时针45°继续寻找,一旦找到重复上面的过程。


具体的步骤在算法中有讲解。

/************************************************************************//* 查找物体的边界,输出已排序的边界序列 适应于单一区域        *//************************************************************************///若能够输出边界点的序列则是比较有用的
  1. #include<cv.h>
  2. #include <highgui.h>
  3. #include <iostream>
  4. #include <stack>
  5. using namespace std;
  6. int main(){
  7.         IplImage * image,*image2;
  8.         image = cvLoadImage("E:\\image\\mapleleaf.tif",0);
  9.         cvNamedWindow("image",1);
  10.         cvShowImage("image",image);
  11.         image2 = cvCreateImage(cvSize(image->width, image->height),image->depth,1);
  12.         cvZero(image2);//image2 赋值为0
  13.         //寻找区域的左上角点
  14.         CvPoint startPoint = cvPoint(0,0);
  15.         bool bFindStartpoint = false;
  16.         int i ,j;
  17.         unsigned char * ptr,*dst;
  18.         stack<int> board;//奇数位存储x坐标,偶数位存储y坐标
  19.         //当前扫描点
  20.         CvPoint currentPoint = cvPoint(0,0);
  21.         //邻域的8个点的方向
  22.         int directions[8][2] = {{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1}};
  23.         int beginDirection = 0;
  24.         bool bFindBoardpoint = false;//寻找到邻域的边界点的判定
  25.         for (i = 0 ; i< image->height && bFindStartpoint == false; i++)
  26.         {
  27.                 for (j = 0 ; j< image->width && bFindStartpoint == false; j++)
  28.                 {
  29.                         ptr = (unsigned char *)(image->imageData + i*image->widthStep + j);
  30.                         if (*ptr == 255)
  31.                         {
  32.                                 startPoint.x = j;
  33.                                 startPoint.y = i;
  34.                                 bFindStartpoint = true;
  35.                                 //cout<<"x:  " << j <<"y :  " <<i <<endl;  
  36.                         }
  37.                 }
  38.         }
  39.         //进行边界跟踪 每次搜索8个方向的点 找到了即停止
  40.         currentPoint = startPoint;
  41.     bFindStartpoint = false;
  42.         beginDirection = 0;
  43.         board.push(startPoint.x);
  44.         board.push(startPoint.y);
  45.         while (!bFindStartpoint)
  46.         {
  47.                 bFindBoardpoint = false;
  48.                 //在8个方向寻找符合条件的边界点
  49.                 while (!bFindBoardpoint)
  50.                 {   
  51.                         //进行出界判定  不对啊 这张图不可能出界啊
  52.                         ptr = (unsigned char *)(image->imageData + (currentPoint.y + directions[beginDirection][1])* image->widthStep + currentPoint.x + directions[beginDirection][0]);
  53.                         if (*ptr == 255)
  54.                         {
  55.                                 bFindBoardpoint = true;
  56.                                 currentPoint.x +=  directions[beginDirection][0];
  57.                                 currentPoint.y  += directions[beginDirection][1];
  58.                                 /************************************************************************/
  59.                                 /*  此处添加序列存储的代码                    */
  60.                                 /************************************************************************/
  61.                                 //一、将边界存储到图片中
  62.                                 dst  = (unsigned char *)image2->imageData + currentPoint.y * image2->widthStep + currentPoint.x;
  63.                                 *dst = 255;
  64.                                 //二、将边界点的序列存储到一个堆栈中
  65.                                 board.push(currentPoint.x);
  66.                                 board.push(currentPoint.y);
  67.                                 if (currentPoint.x == startPoint.x  && currentPoint.y == startPoint.y )
  68.                                 {
  69.                                         bFindStartpoint = true;
  70.                                 }
  71.                                 //改变下次首先开始扫描的方向
  72.                                 beginDirection -= 2;
  73.                                 if (beginDirection < 0)
  74.                                 {
  75.                                         beginDirection += 8;
  76.                                 }
  77.                                
  78.                                
  79.                                
  80.                         }
  81.                         else
  82.                         {
  83.                                 beginDirection ++;
  84.                                 beginDirection = beginDirection%8;
  85.                         }
  86.                 }
  87.                 //cout<<"currentPoint    "<<currentPoint.x <<"     "<< currentPoint.y<<endl;
  88.         }
  89.         cvNamedWindow("image2",1);
  90.         cvShowImage("image2",image2);
  91.        
  92.         //显示堆栈中的数据 顺时针存储,逆时针显示
  93.         //注意:显示时候堆栈中已经没有数据了
  94. /*        int x,y;
  95.         while(!board.empty())
  96.         {
  97.                 y = board.top();
  98.                 board.pop();
  99.                 x = board.top();
  100.                 board.pop();
  101.                 cout<<"x   "<<x<<"    y    "<<y<<endl;
  102.         }
  103. */
  104.         cvWaitKey(0);
  105.         return 0;
  106. }
复制代码



/************************************************************************//* 轮廓跟踪算法获取物体的轮廓序列 生成边界链码   *//************************************************************************/#include<cv.h>
  1. #include <highgui.h>
  2. #include <iostream>
  3. #include <stack>
  4. using namespace std;
  5. int main(){
  6.         IplImage * image,*image2,*image3;
  7.         image = cvLoadImage("E:\\image\\bottle2.tif",0);
  8.         cvNamedWindow("image",1);
  9.         cvShowImage("image",image);
  10.         image2 = cvCreateImage(cvSize(image->width, image->height),image->depth,1);
  11.         image3 = cvCreateImage(cvSize(image->width, image->height),image->depth,1);
  12.         cvZero(image2);//image2 赋值为0
  13.         cvZero(image3);
  14.         //寻找区域的左上角点
  15.         CvPoint startPoint = cvPoint(0,0);
  16.         bool bFindStartpoint = false;
  17.         int i ,j;
  18.         unsigned char * ptr,*dst;
  19.         stack<int> board;//奇数位存储x坐标,偶数位存储y坐标
  20.         //当前扫描点
  21.         CvPoint currentPoint = cvPoint(0,0);
  22.         //邻域的8个点的方向
  23.         int directions[8][2] = {{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1}};
  24.         int beginDirection = 0;
  25.         bool bFindBoardpoint = false;//寻找到邻域的边界点的判定
  26.         for (i = 0 ; i< image->height && bFindStartpoint == false; i++)
  27.         {
  28.                 for (j = 0 ; j< image->width && bFindStartpoint == false; j++)
  29.                 {
  30.                         ptr = (unsigned char *)(image->imageData + i*image->widthStep + j);
  31.                         if (*ptr == 255)
  32.                         {
  33.                                 startPoint.x = j;
  34.                                 startPoint.y = i;
  35.                                 bFindStartpoint = true;
  36.                                 //cout<<"x:  " << j <<"y :  " <<i <<endl;  
  37.                         }
  38.                 }
  39.         }
  40.         //进行边界跟踪 每次搜索8个方向的点 找到了即停止
  41.         currentPoint = startPoint;
  42.     bFindStartpoint = false;
  43.         beginDirection = 0;
  44.         board.push(startPoint.x);
  45.         board.push(startPoint.y);
  46.         while (!bFindStartpoint)
  47.         {
  48.                 bFindBoardpoint = false;
  49.                 //在8个方向寻找符合条件的边界点
  50.                 while (!bFindBoardpoint)
  51.                 {   
  52.                         //进行出界判定  不对啊 这张图不可能出界啊
  53.                         ptr = (unsigned char *)(image->imageData + (currentPoint.y + directions[beginDirection][1])* image->widthStep + currentPoint.x + directions[beginDirection][0]);
  54.                         if (*ptr == 255)
  55.                         {
  56.                                 bFindBoardpoint = true;
  57.                                 currentPoint.x +=  directions[beginDirection][0];
  58.                                 currentPoint.y  += directions[beginDirection][1];
  59.                                 /************************************************************************/
  60.                                 /*  此处添加序列存储的代码                    */
  61.                                 /************************************************************************/
  62.                                 //一、将边界存储到图片中
  63.                                 dst  = (unsigned char *)image2->imageData + currentPoint.y * image2->widthStep + currentPoint.x;
  64.                                 *dst = 255;
  65.                                 //二、将边界点的序列存储到一个堆栈中
  66.                                 board.push(currentPoint.x);
  67.                                 board.push(currentPoint.y);
  68.                                 if (currentPoint.x == startPoint.x  && currentPoint.y == startPoint.y )
  69.                                 {
  70.                                         bFindStartpoint = true;
  71.                                 }
  72.                                 //改变下次首先开始扫描的方向
  73.                                 beginDirection -= 2;
  74.                                 if (beginDirection < 0)
  75.                                 {
  76.                                         beginDirection += 8;
  77.                                 }
  78.                                
  79.                                
  80.                                
  81.                         }
  82.                         else
  83.                         {
  84.                                 beginDirection ++;
  85.                                 beginDirection = beginDirection%8;
  86.                         }
  87.                 }
  88.                 //cout<<"currentPoint    "<<currentPoint.x <<"     "<< currentPoint.y<<endl;
  89.         }
  90.         cvNamedWindow("image2",1);
  91.         cvShowImage("image2",image2);
  92.        
  93.         //显示堆栈中的数据 顺时针存储,逆时针显示
  94.         //注意:显示时候堆栈中已经没有数据了
  95. /*        int x,y;
  96.         while(!board.empty())
  97.         {
  98.                 y = board.top();
  99.                 board.pop();
  100.                 x = board.top();
  101.                 board.pop();
  102.                 cout<<"x   "<<x<<"    y    "<<y<<endl;
  103.         }
  104. */
  105.         //Board中存储着边界的序列 转化为8邻域链码,每隔10个点取样 显示
  106.         int lianmaLength = (board.size()+5)/10;
  107.     int* lianma = new int[lianmaLength];
  108.         for (i = 0 ; i< lianmaLength  && !board.empty();i += 2)
  109.         {
  110.                 lianma[i+1] = board.top();
  111.                 board.pop();
  112.                 lianma[i] = board.top();
  113.                 board.pop();
  114.                 for (j = 0; j< 18 && !board.empty();j++)
  115.                 {
  116.                         board.pop();
  117.                 }
  118.         }
  119.         //将数据在image3中显示
  120.         int t;
  121.         for ( t = 0; t < lianmaLength;t += 2)
  122.         {
  123.                  i = lianma[t+1];
  124.                  j = lianma[t];
  125.                  ptr = (unsigned char *)image3->imageData + i*image->widthStep + j;
  126.                  *ptr = 255;
  127.                
  128.         }
  129.     cvNamedWindow("image3",1);
  130.         cvSaveImage("E:\\image\\bottle2lianma.bmp",image3);
  131.         cvShowImage("image3",image3);
  132.         cvWaitKey(0);
  133.         return 0;
  134. }
复制代码




作者:renshengrumenglibing 发表于2012-2-11 15:58:54 原文链接

您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

Archiver|手机版|小黑屋|ACE Developer ( 京ICP备06055248号 )

GMT+8, 2024-5-6 00:32 , Processed in 0.018535 second(s), 6 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表