1. 程式人生 > >影像之結構化特徵 廣度優先搜尋模板題

影像之結構化特徵 廣度優先搜尋模板題

影像之結構化特徵

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 ;
}