【数字图像处理】顶帽变换和底帽变换

文章链接:http://blog.csdn.net/kk55guang2/article/details/78490069

顶帽变换和底帽变换

灰度级图像 f 的顶帽变换(top-hat transformation)定义为f减去其开操作:
That(f)=f−(f∘b)

类似地,f 的底帽变换(bottom-hat transformation)定义为f的闭操作减去f:
Bhat(f)=(f∙b)−f

  这两个变换的主要应用之一是,用一个结构元通过开操作或闭操作从一副图像中删除物体,而不是拟合被删除的物体。然后,差操作得到一副仅保留已删除分量的图像。顶帽变换用于暗背景上的亮物体,而底帽变换则用于相反的情况。由于这一原因,当谈到这两个变换时,常常分别称为白顶帽变换和黑底帽变换。它们一个重要用途是校正不均匀光照的影响。[1]
实例
  下面,我们通过一个实例来说明此方法,对于图1(a),可以看到光照明显不均匀,左边光照更强,直接进行otsu法全局阈值得到图1(b),可以看到左边的硬币分割出错。
  由于原图是背景亮,前景暗,对原图进行底帽变换以解决光照不均匀的问题,这里先给出处理结果,如图1(c)和(d),可以看到底帽变换后的图像删除了大部分非均匀背景,最后阈值处理后,左边的硬币被分割出来,有少量残缺,但是影响不大,后续可以通过形态学的其他处理将残缺补齐。

                图1 处理图像
  那么为什么底帽变换或顶帽变换可以达到上述效果呢,下面以底帽变换为例,通过图像的灰度三维图来进行解释。
  底帽变换为f的闭操作减去f,闭运算可以几何意义是让球体紧贴在曲面的上表面滚动,此时球体任何部分所能达到的最低点即构成了闭运算f∙bf∙b的曲面。[2]
  图2为原图灰度三维图,上方弯曲的走势显示了图像各部分光照不均匀造成的背景灰度不均现象,其中凹陷对应图像中灰度值比较小的区域,也就是图像中的硬币。

  通过选取大于硬币大小的合适结构元,可以看成一个球体在灰度曲面上滚动,球体下表面的轨迹构成闭运算的曲面,如图3所示,原图中的凹陷都被填上,可以近似代表不均匀的背景。闭运算完之后再减去原图像即可得到背景近似均匀的图像,如图4所示,对应的灰度图可以看图1(c),可以看到不均匀的背景被大致去除,这将十分有助于后面的阈值分割。

参考程序:

//Image_Use为原图像,Image为处理图像副本
                      for (int i = 0; i < Use_ROWS; i++)
                            {
                                for (int j = 0; j < Use_Line; j++)
                                {
                                  Image[i][j] = Image_Use[i][j];
                                }
                            }
                    //二值化  
                    int i,j;
                    int Threshold;
                    Threshold = GetOSTU(Image);
                    for(i = 0; i < Use_ROWS; i++)   
                    {
                        for(j =0; j < Use_Line; j++)
                        {
                          
                          if(Image[i][j] >= Threshold)
                                Image[i][j]=255;
                          else
                                Image[i][j]=0;
                               
                        }
                    }
                    
                    //去噪:不处理四边
                    int bai;
                    for(i = 1; i < Use_ROWS-1; i++)   
                    {
                        for( j=1; j < Use_Line-1; j++)
                        { 
                          if(Image[i][j] == 255) continue;     
                          bai = Image[i-1][j] + Image[i-1][j-1] + Image[i-1][j+1] +Image[i][j+1] +Image[i][j-1] +Image[i+1][j] +Image[i+1][j-1] +Image[i+1][j+1] ;
                          if(bai == 2040)
                          Image[i][j] = 255;
                          
                        }
                    }
                    
                   
                    
                    //开操作
                     for (int i = 1; i < Use_ROWS-1; i++)
                            {
                                for (int j = 1; j < Use_Line - 1; j++)
                                {
                                    if (Image[i][j] == 255 &&
                                        Image[i][j + 1] == 255 &&
                                        Image[i][j - 1] == 255)
                                    {
                                        Image[i][j] = 255;
                                    }

                                }
                            }
                    for (int i = 1; i < Use_ROWS-1; i++)
                            {
                                for (int j = 1; j < Use_Line - 1; j++)
                                {
                                    if (Image[i][j] == 255 ||
                                        Image[i][j + 1] == 255 ||
                                        Image[i][j - 1] == 255)
                                    {
                                        Image[i][j] = 255;
                                    }
                                }
                            }
                  //原图像-开操作  
                  for (int i = 0; i < Use_ROWS; i++)
                            {
                                for (int j = 0; j < Use_Line; j++)
                                {
                                  Image_Use[i][j] = Image_Use[i][j] - Image[i][j];
                                }
                            }  
                    
                  //再进行顶帽变换的图像进行二值化  
                 Threshold = GetOSTU(Image_Use);
                  for(i = 0; i < Use_ROWS; i++)   
                    {
                        for(j =0; j < Use_Line; j++)
                        {
                          
                          if(Image_Use[i][j] >= Threshold)
                                Image_Use[i][j]=255;
                          else
                                Image_Use[i][j]=0;
                               
                        }
                    }
                    //去噪:不处理四边
                    for(i = 1; i < Use_ROWS-1; i++)   
                    {
                        for( j=1; j < Use_Line-1; j++)
                        { 
                          if(Image_Use[i][j] == 255) continue;     
                          bai = Image_Use[i-1][j] + Image_Use[i-1][j-1] + Image_Use[i-1][j+1] +Image_Use[i][j+1] +Image_Use[i][j-1] +Image_Use[i+1][j] +Image_Use[i+1][j-1] +Image_Use[i+1][j+1] ;
                          if(bai == 2040)
                          Image_Use[i][j] = 255;
                        }
                    }

参考文献
[1]《数字图像处理》(第3版),冈萨雷斯著,阮秋琦译,电子工业出版社,2013年;
[2]《数字图像处理与机器视觉——Visual C++与Matlab实现》,张铮,王艳平,薛桂香等编著,人民邮电出版社,2014年

猜你喜欢

转载自www.cnblogs.com/-wenli/p/11980413.html