您的位置:首页 > 其它

图像中连通域分析算法处理

2008-10-20 11:17 429 查看

1. 算法目的:

连通域分析算法的目的就是对二值图像进行分析,计算出在每帧图象上目标(这里是人)的位置。这里主要扩充了游程码的思想,将相互毗邻的值为“1”的像素点归结到同一个连通域中,不相互毗邻的点归结到不同的连通域中,并用矩形盒把所有的连通域包围起来,最后得出包围盒得左上、右下顶点坐标,连通域的面积、质心等特征值。

l 难点:

① 如何在求连通域过程中同时确定连通域的质心;

② 系统固有噪声,以及人所携带得小目标干扰可能会导致误识别,产生误差。这一点可以通过给连通域的面积设定阀值的方法在一定范围内校正。

l 缺点:

无法解决多个人粘连到一起的情况,这时,多个粘连的人会被划分到同一个连通域中,引起记数误差。该算法无法正确处理这种情况,初步准备在该算法之后用其他算法解决。

2.算法描述:

l 算法接口

① 输入:int data(int width,int height);

② 输出:struct boxlist* arealist

l 数据结构

① 连通域链表arealist*

用来存储连通域分析处理好的,最终结果中的连通域包围盒。

struct box* arealist

② 当前扫描段链表boxlist*

用来存储正在处理的包围盒。

struct box{

int boxX1, boxY1 ; /*包围盒左上顶点的坐标*/

int boxX2,boxY2 ; /*包围盒右下顶点的坐标*/

int area ; /*该连通域的面积,即点数*/

float centerX,centerY ; /*质心的坐标*/

struct box* next ; /*指向链表的下一个节点*/

int flag ; /*处理标志*/

}boxlist* ;

③正在处理的行的扫描段链表seglist*

用来存储上一行、当前行的扫描段。

struct box{

int x, y ; /*包围盒左上顶点的坐标*/

struct box* box ; /*该段所属的box*/

}seglist*;

l 处理过程

① 从运动提取模块(唐华松负责)接收一幅数据帧data(int width,int height);

② 从第一行开始自左向右逐位扫描该数据帧,直到找到包含有扫描段(连续为“1“的段)的行,用链表seglist*保存各扫描段seg*,并用链表boxlist*保存各扫描段的包围盒box*,设置各坐标,并记算连通域面积,令各seg->box=box; box->flag=0;如果找不到包含扫描段的行,则转至①;

③ 扫描下一行,将各扫描段装入seglist1*;

④ 对seglist1*中的每一个扫描段seg1*,判断它与seglist*中各扫描段的邻接情况:

⑴如果该扫描段seg1*与seglist*中的所有扫描段都没有邻接的关系,则将该扫描段的包围盒box1*插入到boxlist*中,并令seg1->box=box1,box1->flag=1;

⑵如果该扫描段seg1*与seglist*中的一个或多个扫描段有邻接关系,则先合并seglist*中这些有邻接关系的扫描段的包围盒,box->x1=min(有邻接的box->x1),box->y1=min(有邻接的box->y1),box->x2=max(有邻接的box->x2), box->y2=max(有邻接的box->y2);

然后,令seg1*->box=box,box->flag=1, box->x1=min(seg1->x1, box->x1),box->x2=max(seg1->x2, box->x2),box->y2= y;

⑶重复⑴、⑵的处理直到完成seglist1*的所有扫描段。

⑤ 释放seglist*各节点,然后,令seglist=seglist1;

⑥ 扫描boxlist*链表,对每一个节点box*,如果box->flag=0,则将该节点从boxlist*中移去,并插入到链表arealist*中(这里需要进一步考虑噪声滤波,初步考虑根据连通域的点数滤掉除人以外的其他干扰物体),为已经处理好的连通域;如果box->flag=1,则令box->flog=0。

⑦ 重复步骤③至⑥直到处理完当前帧的所有行。

⑧ 重复步骤①至⑦,处理下一帧图象。

l 算法实现

算法的实现过程见下图。






各函数功能及输入输出

1.Area.c文件

该文件是主要处理程序,处理对连通域的扫描合并,其主要函数如下:

(1) struct seg *getCurSegList(int data[height][width],int row)

功能:扫描一行象素点,找到象素点为1的点,并根据是否连续分成不同的SegList,然后用指针连接起来。

输入:将每帧图象的象素点值(0,1)用二维数组data存放,作为该函数的输入,并且将处理的当前行值row输入。

输出:返回指针,该指针是第row行的扫描得到的SegList链表表头。

(2) struct box *getArea(int data[height][width])

功能:针对每一行调用getCurSegList函数,得到每行连通的象素段SegList,然后针对

每个SegList判断它的前后左右是否有相联结的SegList,如果有则合并,然后

加入到一个boxlist的链表中,并对boxlist链表中的元素判断,如果没有相连

接段的则加入到arealist中。

输入:二维数组data(存放每帧象素点值)。

输出:返回指针,该指针是经处理得到的连通域的链表表头areaList。

2.GetAreaList.c文件:

该文件包括一个函数getAreaList,所示如下:

struct box *getAreaList(int data[height][width],int fno)

功能:对处理得到的连通域(数据类型为box)的某些参数赋值,比如帧号,标记位flag,

计算连通区域的质心位置(横坐标和纵坐标),并滤掉一些噪声干扰(如果连通区

域的面积小于AREAmin,则忽略掉)。

输入:二维数组data(存放每帧象素点值),当前帧的帧号fno.

输出:处理完全的连通域链表表头areaList.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: