二值图像连通域标记算法与代码收藏.docx
《二值图像连通域标记算法与代码收藏.docx》由会员分享,可在线阅读,更多相关《二值图像连通域标记算法与代码收藏.docx(9页珍藏版)》请在冰豆网上搜索。
二值图像连通域标记算法与代码收藏
二值图像连通域标记算法与代码收藏
10:
19:
42二值图像连通域标记算法与代码
这里列举二值图像连通域标记算法包括直接扫描标记算法和二值图像连通域标记快速算法
一、直接扫描标记算法把连续区域作同一个标记,常见的四邻域标记算法和八邻域标记算法。
1、四邻域标记算法:
1)判断此点四邻域中的最左,最上有没有点,如果都没有点,则表示一个新的区域的开始。
2)如果此点四邻域中的最左有点,最上没有点,则标记此点为最左点的值;如果此点四邻域中的最左没有点,最上有点,则标记此点为最上点的值。
3)如果此点四邻域中的最左有点,最上都有点,则标记此点为这两个中的最小的标记点,并修改大标记为小标记。
2、八邻域标记算法:
1)判断此点八邻域中的最左,左上,最上,上右点的情况。
如果都没有点,则表示一个新的区域的开始。
2)如果此点八邻域中的最左有点,上右都有点,则标记此点为这两个中的最小的标记点,并修改大标记为小标记。
3)如果此点八邻域中的左上有点,上右都有点,则标记此点为这两个中的最小的标记点,并修改大标记为小标记。
4)否则按照最左,左上,最上,上右的顺序,标记此点为四个中的一个。
代码实现:
#include
#include
#include
像初步标记:
为每个像素赋予临时标记,并且将临时标记的等价关系记录在等价表中
2.整理等价表:
这一环节分为两个步骤:
(1)将具有等价关系的临时标记全部等价为其中的最小值;
(2)对连通区域以自然数顺序重新编号,得到临时标记与最终标记之间的等价关系。
3.图像代换:
对图像进行逐像素代换,将临时标记代换为最终标记.经过3个环节处理后,算法输出标记后的图像,图像中连通域按照由上到下,由左至右出现的顺序被标以连续的自然数。
代码实现:
#include
#include
#include
arkValue1);
pInnerListAdd->AddTail((void*)().MarkValue2);
((void*)pInnerListAdd);
();
/*定义pFindValue1和pFindValue2,存放在所有内层链表中找到特定值
的某个内层链表的头指针,也就是外层链表的某个元素值。
*/
CPtrList*pFindValue1=NULL;
CPtrList*pFindValue2=NULL;
arkValue1))
{
pFindValue1=pInnerList;
}
if(pInnerList->Find((void*)().MarkValue2))
{
pFindValue2=pInnerList;
}
(posExElem);
}
arkValue2);
}
elseif(pFindValue2)
{
pFindValue2->AddTail((void*)().MarkValue1);
}
/*等价对中两个值在整理过的等价关系中都
没有找到,则在exList中增加新元素。
*/
else
{
CPtrList*pInnerListAdd=newCPtrList;
pInnerListAdd->AddTail((void*)().MarkValue1);
pInnerListAdd->AddTail((void*)().MarkValue2);
((void*)pInnerListAdd);
}
=-1;
pRegionData[MarkNo].=-1;
pRegionData[MarkNo].=-1;
pRegionData[MarkNo].=-1;
pRegionData[MarkNo].();
}
for(j=0;j{
lpMarkMove=lpMark+j*nImageWidth;
for(i=0;i{
if(*lpMarkMove>0)
{
if(pRegionData[*lpMarkMove-1].==-1)
{
pRegionData[*lpMarkMove-1].=i;
pRegionData[*lpMarkMove-1].=i;
pRegionData[*lpMarkMove-1].=j;
pRegionData[*lpMarkMove-1].=j;
POINTptInsert;
=i;
=j;
pRegionData[*lpMarkMove-1].(ptInsert);
}
else
{
POINTptInsert;
=i;
=j;
pRegionData[*lpMarkMove-1].(ptInsert);
if(pRegionData[*lpMarkMove-1].>i)
{
pRegionData[*lpMarkMove-1].=i;
}
if(pRegionData[*lpMarkMove-1].
{
pRegionData[*lpMarkMove-1].=i;
}
if(pRegionData[*lpMarkMove-1].{
pRegionData[*lpMarkMove-1].=j;
}
if(pRegionData[*lpMarkMove-1].>j)
{
pRegionData[*lpMarkMove-1].=j;
}
}
}
lpMarkMove++;
}
}
for(i=0;i{
(pRegionData[i]);
}
if(pRegionData)
{
delete[]pRegionData;
pRegionData=NULL;
}
returnTRUE;
}
/*等价关系整理完成,下面建立第一次扫描的标记值和
第二次扫描的标记值之间的映射关系。
*/
intnTotalEqualNum=0;OriginalMark=i+1;
vMarkMap[i].nMappingMark=i+1;
}
POSITIONposInnerElem;MappingMark=nMin;
pInnerList->GetNext(posInnerElem);
}
(posExElem);
}
/*将映射向量nMappingMark中不重复的部分找出并对其进行排序。
使用find()和sort()这两种泛型算法,应该#include。
*/
std:
:
vectorvSortMark(nMarkRegion);MappingMark)
==())
{
vSortMark[nIndex++]=vMarkMap[i].nMappingMark;
}
}
sort((),());
/*根据排序后的标记在vSortMark向量中的位置,对映射向量做出重新调整。
*/
std:
:
vector:
:
iteratoritFind;
std:
:
vector:
:
iteratoritBegin;
itBegin=();
for(i=0;i{
itFind=find((),(),vMarkMap[i].nMappingMark);
vMarkMap[i].nMappingMark=(itFind-itBegin+1);
}
MappingMark;
}
lpMarkMove++;
}
}
=-1;
pRegionData[MarkNo].=-1;
pRegionData[MarkNo].=-1;
pRegionData[MarkNo].=-1;
pRegionData[MarkNo].();
}
==-1)
{
pRegionData[*lpMarkMove-1].=i;
pRegionData[*lpMarkMove-1].=i;
pRegionData[*lpMarkMove-1].=j;
pRegionData[*lpMarkMove-1].=j;
POINTptInsert;
=i;
=j;
pRegionData[*lpMarkMove-1].(ptInsert);
}
else
{
POINTptInsert;
=i;
=j;
pRegionData[*lpMarkMove-1].(ptInsert);
if(pRegionData[*lpMarkMove-1].>i)
{
pRegionData[*lpMarkMove-1].=i;
}
if(pRegionData[*lpMarkMove-1].
{
pRegionData[*lpMarkMove-1].=i;
}
if(pRegionData[*lpMarkMove-1].>j)
{
pRegionData[*lpMarkMove-1].=j;
}
if(pRegionData[*lpMarkMove-1].{
pRegionData[*lpMarkMove-1].=j;
}
}
}
lpMarkMove++;
}
}
for(i=0;i{
(pRegionData[i]);
}
if(pRegionData)
{
delete[]pRegionData;
pRegionData=NULL;
}
本文来自CSDN博客,转载请标明出处:
2009/08/07