边界检测算法分析与实现

1、题目:一个数据矩阵,选定某个位置的数据元作为参考,寻找与该数据元值相同的连成一片的最大范围。如下二维数组中所示,选择arr[1][3]作为参考对象,从位置(1,3)开始寻找所有相连的值为‘1’的元素。结果很明显如下图1所示。

int arr[5][5]={
    1,0,1,0,0,
    0,1,1,1,0,
    0,1,0,1,1,
    0,1,0,0,1,
    0,1,1,1,1 };

图1:

2、深度遍历方法

  从(1,3)位置开始,按照“上、右、下、左”的顺序检查相邻位置的值是否与参考值相同,如果相同则被筛选到候选集中,并以该点为基点再出发扩展检查。

a.     (1,3)-->(2,3)-->(2,4)-->(3,4)-->(4,4)-->(4,3)-->(4,2)-->(4,1)-->(3,1)-->(2,1)-->(1,1)-->(1,2)-->{  (1,3)   ||  (0,2)  }

b.     (1,3)-->(1,2)-->...

     深度遍历可能从不同的路径到达相同的位置点,正如上面的(1,2)位置。为了避免形成回路,还得记住已识别点的位置。从分析来看,计算过程比较复杂,要记住所有点位置,也需要不少的内存空间;计算上,每识别一个新点,都要在已检测集合中进行匹配。

3、广度遍历方法

   从(1,3)位置开始,按照“上、右、下、左”的顺序检查相邻位置的值是否与参考值相同,如果相同则被筛选到候选集合中,并作为新的参考点。

   (1,3)-->(2,3)-->(1,2)

               |-->(2,4)   |-->(0,2)

              ...

    如此,从(1,3)位置相邻4个点筛选,命中的点追加的候选队列中。为了避免回路,把每个点4个相邻方向的检查状态记录下来,0表示未检测,1表示已检测为有相同值,2表示检测为无相同值(边界点)。这些信息在后续的检测中,避免重复循环。

#include <iostream>
#include <queue>
#include <vector>
using namespace std;

struct nposition
{
    int x, y;    //position in 2D array
    char statN, statE, statS, statW;    //north, east, south, west: 0-uncheck, 1-checked, 2-edge
};
#define MAX_LIMIT 5
int main()
{
    int arr[5][5]={
    1,0,1,0,0,
    0,1,1,1,0,
    0,1,0,1,1,
    0,1,0,0,1,
    0,1,1,1,1 };
    queue<nposition> active;    //待检测队列
    vector<nposition> checked;    //已检测的点
    nposition seed={0};
    int val=1;
    
    seed.x = 1;
    seed.y = 3;
    active.push( seed );
    while( !active.empty() )
    {
        nposition p=active.front();
        if( p.statN == 0 )
        {
            if( p.x > 0 && arr[p.x-1][p.y] == val )
            {
                nposition temp = {0};
                temp.x = p.x-1;
                temp.y = p.y;
                temp.statS = 1;
                active.push( temp );
                p.statN = 1;
            }
            else
                p.statN = 2;
        }
        if( p.statE == 0 )
        {
            if( p.y < MAX_LIMIT-1 && arr[p.x][p.y+1] == val )
            {
                nposition temp = {0};
                temp.x = p.x;
                temp.y = p.y+1;
                temp.statW = 1;
                active.push( temp );
                p.statE = 1;
            }
            else
                p.statE = 2;
        }
        if( p.statS == 0 )
        {
            if( p.x < MAX_LIMIT-1 && arr[p.x+1][p.y] == val )
            {
                nposition temp = {0};
                temp.x = p.x+1;
                temp.y = p.y;
                temp.statN = 1;
                active.push( temp );
                p.statS = 1;
            }
            else
                p.statS = 2;
        }
        if( p.statW == 0 )
        {
            if( p.y > 0 && arr[p.x][p.y-1] == val )
            {
                nposition temp = {0};
                temp.x = p.x;
                temp.y = p.y-1;
                temp.statE = 1;
                active.push( temp );
                p.statW = 1;
            }
            else
                p.statW = 2;
        }
        active.pop();
        checked.push_back( p );
    }//!while
    //
    int i=0;
    cout<<"linked positions:"<<endl;
    for( ; i<checked.size(); ++i )
    {
        cout<<"	("<<checked[i].x<<","<<checked[i].y<<")"<<endl;
    }
}
原文地址:https://www.cnblogs.com/feika/p/3574216.html