分水嶺分割算法源代碼(改進)

void  WaterThreshUpdate(const int **OriginalImage, char** SeedImage,
                                          int **LabelImage, int row, int col)
////////////////////////////////////////////////////////////////////////////////////////////
/////     功能    :    用標記-分水嶺算法對輸入圖像進行分割                          ///////////
/////    參數說明    :    OriginalImage --輸入圖像(灰度圖,0~255)                ///////////
/////                SeedImage     --標記圖像(二值圖,0-非標記,1-標記)         ///////////
/////               LabelImage    --輸出圖像(1-第一個分割區域,2-第二個分割區域,...) ////
/////                row           --圖像行數                                            ////
/////                col           --圖像列數                                            ////
////////////////////////////////////////////////////////////////////////////////////////////   
{
    using namespace std;

    //標記區域標識號,從1開始
    int Num=0;
    int i,j;

    //保存每個隊列種子個數的數組
    vector<int*> SeedCounts;
    //臨時種子隊列
    queue<POINT> que;
    //保存所有標記區域種子隊列的數組
    vector<queue<POINT>* > qu;
   
    int* array;
    queue<POINT> *uu;
    POINT temp;

    for(i=0;i<row;i++)
        for(j=0;j<col;j++)
            LabelImage[i][j]=0;
   

    int m,n,k=0;
    int up,down,right,left,upleft,upright,downleft,downright;

    //預處理,提取區分每個標記區域,並初始化每個標記的種子隊列
    //種子是指標記區域邊緣的點,他們可以在水位上升時向外淹沒(或者說生長)
    for(i=0;i<row;i++)
    {
        for(j=0;j<col;j++)
        {
            //如果找到一個標記區域
            if(SeedImage[i][j]==1)
            {
                //區域的標識號加一
                Num++;
                //分配數組並初始化爲零
                array=new int[256];
                ZeroMemory(array,256*sizeof(int));
                //
                SeedCounts.push_back(array);
                //分配本標記的優先隊列
                uu=new queue<POINT>[256];
                //加入到隊列數組中
                qu.push_back(uu);
                //當前點放入本標記區域的臨時種子隊列中
                temp.x=i;
                temp.y=j;
                que.push(temp);
                //當前點標記爲已處理
                LabelImage[i][j]=Num;
                SeedImage[i][j]=127;
               
                //讓種子隊列中的種子進行生長直到所有的種子都生長完畢
                while(!que.empty())
                {
                    up=down=right=left=0;
                    upleft=upright=downleft=downright=0;
                    //隊列中取出一個種子
                    temp=que.front();
                    m=temp.x;
                    n=temp.y;
                    que.pop();

                    if(m>0)
                    {
                        //上方若爲可生長點則加爲新種子
                        if(SeedImage[m-1][n]==1)
                        {
                            temp.x=m-1;
                            temp.y=n;
                            que.push(temp);
                            //新種子點標記爲已淹沒區域
                            LabelImage[m-1][n]=Num;
                            SeedImage[m-1][n]=127;
                        }else//否則上方爲不可生長
                        {
                            up=1;
                        }
                    }
                    if(m>0&&n>0)
                    {
                        if(SeedImage[m-1][n-1]==1)//左上方若爲可生長點則加爲新種子
                        {
                            temp.x=m-1;
                            temp.y=n-1;
                            que.push(temp);
                            //新種子點標記爲已淹沒區域
                            LabelImage[m-1][n-1]=Num;
                            SeedImage[m-1][n-1]=127;
                        }else//否則左上方爲不可生長
                        {
                            upleft=1;
                        }
                    }

                    if(m<row-1)
                    {
                        if(SeedImage[m+1][n]==1)//下方若爲可生長點則加爲新種子
                        {
                            temp.x=m+1;
                            temp.y=n;
                            que.push(temp);
                            //新種子點標記爲已淹沒區域
                            LabelImage[m+1][n]=Num;
                            SeedImage[m+1][n]=127;
                        }else//否則下方爲不可生長
                        {
                            down=1;
                        }
                    }
                    if(m<(row-1)&&n<(col-1))
                    {
                        if(SeedImage[m+1][n+1]==1)//下方若爲可生長點則加爲新種子
                        {
                            temp.x=m+1;
                            temp.y=n+1;
                            que.push(temp);
                            //新種子點標記爲已淹沒區域
                            LabelImage[m+1][n+1]=Num;
                            SeedImage[m+1][n+1]=127;
                        }else//否則下方爲不可生長
                        {
                            downright=1;
                        }
                    }
               
                    if(n<col-1)
                    {
                        if(SeedImage[m][n+1]==1)//右方若爲可生長點則加爲新種子
                        {
                            temp.x=m;
                            temp.y=n+1;
                            que.push(temp);
                            //新種子點標記爲已淹沒區域
                            LabelImage[m][n+1]=Num;
                            SeedImage[m][n+1]=127;
                        }else//否則右方爲不可生長
                        {
                            right=1;
                        }
                    }
                    if(m>0&&n<(col-1))
                    {
                        if(SeedImage[m-1][n+1]==1)//右上方若爲可生長點則加爲新種子
                        {
                            temp.x=m-1;
                            temp.y=n+1;
                            que.push(temp);
                            //新種子點標記爲已淹沒區域
                            LabelImage[m-1][n+1]=Num;
                            SeedImage[m-1][n+1]=127;
                        }else//否則右上方爲不可生長
                        {
                            upright=1;
                        }
                    }

                    if(n>0)
                    {
                        if(SeedImage[m][n-1]==1)//左方若爲可生長點則加爲新種子
                        {
                            temp.x=m;
                            temp.y=n-1;
                            que.push(temp);
                            //新種子點標記爲已淹沒區域
                            LabelImage[m][n-1]=Num;
                            SeedImage[m][n-1]=127;
                        }else//否則左方爲不可生長
                        {
                            left=1;
                        }
                    }
                    if(m<(row-1)&&n>0)
                    {
                        if(SeedImage[m+1][n-1]==1)//左下方若爲可生長點則加爲新種子
                        {
                            temp.x=m+1;
                            temp.y=n-1;
                            que.push(temp);
                            //新種子點標記爲已淹沒區域
                            LabelImage[m+1][n-1]=Num;
                            SeedImage[m+1][n-1]=127;
                        }else//否則左方爲不可生長
                        {
                            downleft=1;
                        }
                    }

                    //上下左右只要有一點不可生長,那麼本點爲初始種子隊列中的一個
                    if(up||down||right||left||
                        upleft||downleft||upright||downright)
                    {
                        temp.x=m;
                        temp.y=n;
                        qu[Num-1][OriginalImage[m][n]].push(temp);
                        SeedCounts[Num-1][OriginalImage[m][n]]++;
                    }

                }//while結束
            }
        }
    }

    bool actives;//在某一水位處,所有標記的種子生長完的標誌
    int WaterLevel;

    //淹沒過程開始,水位從零開始上升
    for(WaterLevel=0;WaterLevel<256;WaterLevel++)
    {
        actives=true;
        while(actives)
        {
            actives=false;
            //依次處理每個標記區域
            for(i=0;i<Num;i++)
            {
            if(!qu[i][WaterLevel].empty())
            {
                actives=true;
                while(SeedCounts[i][WaterLevel]>0)
                {
                    SeedCounts[i][WaterLevel]--;
                    temp=qu[i][WaterLevel].front();
                    qu[i][WaterLevel].pop();
                    m = temp.x;
                    n = temp.y;//當前種子的座標
                    if(m>0)
                    {
                        if(!LabelImage[m-1][n])//上方若未處理
                        {
                            temp.x=m-1;
                            temp.y=n;
                            LabelImage[m-1][n]=i+1;//上方點標記爲已淹沒區域

                            if(OriginalImage[m-1][n]<=WaterLevel)//上方若爲可生長點則加入當前隊列
                            {
                                qu[i][WaterLevel].push(temp);
                            }
                            else//否則加入OriginalImage[m-1][n]級隊列
                            {
                                qu[i][OriginalImage[m-1][n]].push(temp);
                                SeedCounts[i][OriginalImage[m-1][n]]++;
                            }
                        }
                    }

                    if(m<row-1)
                    {
                        if(!LabelImage[m+1][n])//下方若未處理
                        {
                            temp.x=m+1;
                            temp.y=n;
                            LabelImage[m+1][n]=i+1;//下方點標記爲已淹沒區域

                            if(OriginalImage[m+1][n]<=WaterLevel)//下方若爲可生長點則加入當前隊列
                            {
                                qu[i][WaterLevel].push(temp);
                            }
                            else//否則加入OriginalImage[m+1][n]級隊列
                            {
                                qu[i][OriginalImage[m+1][n]].push(temp);
                                SeedCounts[i][OriginalImage[m+1][n]]++;
                            }
                        }
                    }
           
                    if(n<col-1)
                    {
                        if(!LabelImage[m][n+1])//右邊若未處理
                        {
                            temp.x=m;
                            temp.y=n+1;
                            LabelImage[m][n+1]=i+1;//右邊點標記爲已淹沒區域

                            if(OriginalImage[m][n+1]<=WaterLevel)//右邊若爲可生長點則加入當前隊列
                            {
                                qu[i][WaterLevel].push(temp);
                            }
                            else//否則加入OriginalImage[m][n+1]級隊列
                            {
                                qu[i][OriginalImage[m][n+1]].push(temp);
                                SeedCounts[i][OriginalImage[m][n+1]]++;
                            }
                        }
                    }

                    if(n>0)
                    {
                        if(!LabelImage[m][n-1])//左邊若未處理
                        {
                            temp.x=m;
                            temp.y=n-1;
                            LabelImage[m][n-1]=i+1;//左邊點標記爲已淹沒區域

                            if(OriginalImage[m][n-1]<=WaterLevel)//左邊若爲可生長點則加入當前隊列
                            {
                                qu[i][WaterLevel].push(temp);
                            }
                            else//否則加入OriginalImage[m][n-1]級隊列
                            {
                                qu[i][OriginalImage[m][n-1]].push(temp);
                                SeedCounts[i][OriginalImage[m][n-1]]++;
                            }
                        }
                    }
                }//while循環結束
                SeedCounts[i][WaterLevel] = (int) qu[i][WaterLevel].size();
            }//if結束
            }//for循環結束
        }//while循環結束
    }//for循環結束
    while(!qu.empty())
    {
        uu=qu.back();
        delete[] uu;
        qu.pop_back();
    }
    while(!SeedCounts.empty())
    {
        array=SeedCounts.back();
        delete[] array;
        SeedCounts.pop_back();
    }
}

發佈了8 篇原創文章 · 獲贊 4 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章