影像之结构化特征 广度优先搜索模板题

影像之结构化特征

Problem Description
在影像比对中,有一种方法是利用影像中的边缘(edge)资讯,计算每个边缘资讯中具有代表性的结构化特征,以作为比对两张影像是否相似的判断标准。Water-filling方法是从每个边缘图的一个端点开始,绕着相连的边缘点走并依序编号。若走到某一步时,遇到一个以上不同的连接点,则分成不同路径同时继续走,直到没有任何连接点为止。如果一个点和另一个点为上下左右相邻,就称为连接。
例如,在图的影像中包含三个边缘图,每个边缘图由一些互相连接的边缘点构成。图中以黑色的方块代表边缘点,白色的方块代表背景。在Water-filling方法中,首先,从第一列(row)开始,由上至下,由左至右,先找到第一个黑点并编号为1。接着,找1的下一个尚未编号的连接点并编号为2。依此方法继续往下一个点前进依次编号。在编号6的点之后有两个尚未编号的连接点,此时,则分为两条路线,并同时编号为7继续往下走。当走到没有任何的相连点时,则结束现有边缘图的编号,并继续对影像中的其它边缘图编号。走完图1所有边缘图后所得到的编号如图2所示。所以,走完这三个边缘图所需要的步数分别为12、7及3;所以,12、7及3可以作为代表此张影像的结构化特征。请注意:位于斜对角上的两点不能算做连接,如:这是不相邻的情况
题目数据题目数据的答案
请写一个程序计算每个影像中,以Water-filling方法走完其中所有的边缘图后,将每个边缘图需走的步数依走访的顺序列出。
Input
输入文件包含一个正方形的影像。每组影像以图的宽度n开头(l≤n≤1000)。接下来的n行代表影像的内容:0表示背景的白点,1表示黑色的边缘点。
Output
对每一个输入的影像,以Water-filling方法走完所有的边缘图后,先印出此张影像中共有几个边缘图。接着,将每个边缘图需走的步数按升序列出。
Sample
10
0000000000
0011110000
0000010000
0011111000
0010110100
0010010110
0011110010
0100010010
0100000110
0100000000
样例输出
3
3
7
12

观察本题,我们很容易知道,本题要求我们对于一个图,其大小为n*n,从上到下,从左到右,进行搜索。对于搜索到其值为1的点,我们需要从这个点开始进行广搜,搜索完与其相连成一块的所有点,并且每次搜索完与其相连的点后,记录下其距离开始搜索点最远的点的搜索距离。最后,对于所有这样的值进行排序并且顺序输出。
很显然,我们只需要按题目所说,搜索完所有点,并且保证每个联通的点集仅搜索一遍且搜索初始点是其中最左、最上的点。
所以,得到如下代码:

#include <cstdio>
 
using namespace std;
 
int n,head=1,tail,num,t,maxn;
struct node{
    int x,y;
}q[1020010];
int ber[1020010];
node move[5]={0,0,1,0,0,1,-1,0,0,-1};
bool bo[1010][1010];
int ans[500010];
 
inline void read()
{
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)
        {
            char c=getchar();
            while ((c!='0')&&(c!='1'))
                c=getchar();
            if (c=='1')
                bo[i][j]=true;
        }
    return ;
}
 
void sort(int ,int );
 
int main()
{
    scanf("%d",&n);
    read();
    for (int j=1;j<=n;j++)
        for (int i=1;i<=n;i++)
        {
            if (bo[i][j])
            {
                maxn=1;
                q[++tail].x=i;
                q[tail].y=j;
                ber[tail]=1;
                bo[i][j]=false;
                while (head<=tail)
                {
                    node now;
                    t=head;
                    if (ber[t]>maxn)
                        maxn=ber[t];
                    now=q[head++];
                    for (int k=1;k<=4;k++)
                        if (bo[now.x+move[k].x][now.y+move[k].y])
                        {
                            bo[now.x+move[k].x][now.y+move[k].y]=false;
                            q[++tail].x=now.x+move[k].x;
                            q[tail].y=now.y+move[k].y;
                            ber[tail]=ber[t]+1;
                        }
                }
                ans[++num]=maxn;
            }
        }
    sort(1,num);
    printf("%d\n",num);
    for (int i=1;i<=num;i++)
        printf("%d\n",ans[i]);
    return 0;
}
 
void sort(int l,int r)
{
    int a=l,b=r;
    int mid=ans[(a+b)>>1];
    while (a<=b)
    {
        while (ans[a]<mid)
            a++;
        while (ans[b]>mid)
            b--;
        if (a<=b)
        {
            int f=ans[a];
            ans[a]=ans[b];
            ans[b]=f;
            a++;b--;
        }
    }
    if (l<b)
        sort(l,b);
    if (a<r)
        sort(a,r);
    return ;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值