【图像处理】二值图像连通区域标记中等价对的合并

近来,在进行数字图像处理练习过程中,遇到连通区域标记的问题,网上有很多相关算法的讲解,我参考的是这篇文章,根据作者的讲解,可以很轻易地实现连通域的标记。

本人在进行基于行程的标记处理中第三步——”等价对的合并”时编写简单程序实现。希望能对诸君有所参考。

其中equivalences存放所有等价对,overlap存放所有合并后的结果。

void MergeRuns(vector<pair<int,int>>equivalences,  vector<vector<int>>&overlap)
{
    for(int i=0; i<equivalences.size();i++)
    {
        vector<int>cur;     //存放当前正在合并的团

        //初始化当前合并的团(即把第一个未合并的等价对放入其中)
        int first = equivalences[i].first;
        int second = equivalences[i].second;    
        cur.push_back(first);
        cur.push_back(second);

        //从第一个未合并的等价对之后开始对比判断
        for(int j=i+1;j<equivalences.size();j++)
        {
            int pre_size = cur.size();  //当前合并团在该次合并前的大小
            for(int k=0;k<cur.size();k++)
            {
                //判断当前合并团是否与当前等价对有重叠,
                //如果重叠,则将另一团标号放入当前合并团,并跳出循环
                if(cur[k] == equivalences[j].first)
                {
                    cur.push_back(equivalences[j].second);
                    vector<pair<int,int>>::iterator iter = equivalences.begin()+j;
                    equivalences.erase(iter);
                    iter = equivalences.begin();
                    break;
                }
                else if(cur[k]==equivalences[j].second)
                {
                    cur.push_back(equivalences[j].first);
                    vector<pair<int,int>>::iterator iter = equivalences.begin()+j;
                    equivalences.erase(iter);
                    iter = equivalences.begin();
                    break;
                }
            }

            //判断此次合并是否有新团标号加入,
            //如果是,则需从第一个未合并的等价对之后开始对比判断
            if(pre_size!=cur.size())
            {
                j=i;
            }
        }
        overlap.push_back(cur);     //将当前合并完成的团放入结果vector中
    }

}

结果如图1所示;


图1 合并结果

然而,这段程序有些许不足之处:
1. 产生的结果没有进行排序(想来不会影响最终标记,便未加优化)
2. 再者,在进行合并时未加入单独团标号,即不存在等价对的团标号,比如本例中的4号。


2017-8-29修改
修改代码,完善不足2,以完成合并单独团标号

//添加参数int label_num,表示团标号最大值
void MergeRuns(vector<pair<int,int>>equivalences,  vector<vector<int>>&overlap, int label_num)
{
    ...
    //以上为之前代码,未做修改
    //下面为添加无等价对的团标号代码
    //处理方式其实很无脑,就是对所有团标号进行查找,
    //找到不在合并后的团中的就将其放入结果vector中
    for(int i = 0;i<=label_num;i++)
    {
        for(int j=0;j<overlap.size();j++)
        {
            int k=0;
            for(;k<overlap[j].size();k++)
                if(overlap[j][k]==i)
                    break;
            if(k<overlap[j].size())
                break;
            else if(j==overlap.size()-1)
            {
                vector<int>cur;
                cur.push_back(i);
                overlap.push_back(cur);
            }
        }
    }
}

处理方式其实很无脑,就是对所有团标号进行查找,找到不在合并后的团中的就将其放入结果vector中。

结果如图2所示;


图2 修改后的合并结果

这里我的团标号是从0开始计的,因此结果中包含0,是单独团标号。如果从1开始,则将代码中循环起始处修改为1。

抛砖之言,望指教!

参考文章:
http://www.cnblogs.com/ronny/p/img_aly_01.html

猜你喜欢

转载自blog.csdn.net/qq_26035563/article/details/77574940