一种基于特征矩阵的图像连通域快速算法

本文描述了一种可以应用在大分辨率图像上的连通域标记方法,该方法可以极大的简化图像标记的计算量,且对于标记的准确率和标记速度都是可控的。
1.整体思路
在任何一副图像中寻找连通域都是对不同区域的有效像素进行统计和关系判定,大多数连通域算法都需要做到整张图片的遍历和计算,有的需要多次遍历整张图片才能计算出准确的连通区域;
本文的思想是,一张图中并不是每个像素都需要计算的,使用一些具有代表性的像素判断某一区域的有效性其实也可准确表达区域信息;
基于上述想法,本文采用的方法是:
第一步,先将图像划分为多个区域,每个区域采用固定的长宽大小,使整张图片划分成若干个窗格,比如使用4x4的矩阵窗口,对于一张640x480的图像进行划分,可得到160x120个矩阵窗口,我们需要计算的连通区域就是由这些划分好的窗格组成;
第二步,划分好矩阵窗口后,进行每个窗口对角线上的像素值遍历(为了方便计算,使用两条中心线也可达到同样的效果),如果该窗口特征线上的有效像素值满足要求,则将该窗口计为1,反之则记为0,那么整个160x120的矩阵窗口被标记为了1和0;此时已经生成了代表整图特征的矩阵;
第三步,对特征矩阵进行连通域计算,首先计算每行的连续区域,并打上标记,每行中的连续区域全部被标记好,保存下来行信息,列信息,和有效数目;然后遍历标记好的数组,计算每行的有效区域的领域是否也为有效区域(此时8邻域的计算,变成了2领域,上下两行),如果是有效的,则将其标记为同一区域,遍历完成后可得到所有有效区域的标记;最后将标记写入原矩阵对应的坐标位置,得到标记好的特征矩阵;
第四步,对标记好的特征矩阵进行提取,从标号1开始为第一个连通区域,通过一次遍历可得到所有连通域的坐标信息,最后经过坐标转换,将特征矩阵中的坐标,转换到原图像中的坐标得到最终的连通域信息。
2.特点分析
上述方法,有三个设计点:
(1)窗口化,将整个图像分成若干窗口,并通过计算特征线上的有效值,使计算流程极大简化且计算量呈几何下降,按4x4的窗口,原本需要计算16个像素,实际只计算了8个像素,第一次遍历整图,速度提升2倍;原图缩小16倍,则第二次遍历计算每行连通区域,速度提升16倍;如果采用8x8或者更大的窗口,速度还可提升;
(2)按行分块进行连通域求取,先把每行的连通域计算出来,然后按照分块的方法,把每个单独连通域的块进行二次计算,极大的简化了计算过程,速度再次提升;
(3)最后,提取连通域坐标时,只需要提取特征矩阵中的坐标,就可映射到原图中,不受原图类型的影响,对于RGB,灰度图,二值化图皆可适用,其次,该算法很大程度上减少了内存消耗,除了原始图像,需要额外分配的内存只有原图像的部分大小,甚至根据窗口设置可达到非常小的内存消耗。
关键代码1.区域划分和有效值计算

在这里插入代码片
//整图计算有效区域,划分成若个窗格进行搜索,生成特征矩阵,支持ROI区域计算
static int SearchCentre(unsigned char *pimage,int width,int w_stride,int h_stride,const COLOR_LAB_THRESHOLEDS *color_thread,SEARCH_AREA *Area,unsigned char *pResult)
{
   
    
    
 unsigned int i,j,k;
 int FailCount=0;
 COLOR_LAB LAB;
 uint16_t *row_ptr=NULL;
 
 for(i=Area->X_Start;i<Area->X_End;i+=h_stride) //行
 {
   
    
     
  
  for(j=Area->Y_Start*2;j<Area->Y_End*2;j+=w_stride*2) //列
  {
   
    
    
   FailCount=0;  //每个区域内不符合阈值的累计 
   k=0;
   for(k=0;k<w_stride*2;k+=2)
   {
   
    
    
    row_ptr=(uint16_t*)(pimage+(i+h_stride/2)*width*2+j+k); //取16位   行不变
    if(!ColorMatchLAB(*row_ptr,color_thread))
    {
   
    
    
     FailCount++;
    }
    if(FailCount>((w_stride+h_stride)>>2))
    {
   
    
       
     break;
    }
   }
   
   if(k==w_stride*2)
   {
   
    
    
    k=0;
    for(k=0;k<h_stride;k++)
    {
   
    
    
     row_ptr=(uint16_t *)(pimage+(i+k)*width*2+j+w_stride); //取16位   列不变    
     if(!ColorMatchLAB(*row_ptr,color_thread))
     {
   
    
    
      FailCount++

猜你喜欢

转载自blog.csdn.net/weixin_40672861/article/details/123261312