圖形圖像處理-之-一個複雜度爲常數的快速局部自適應算法 下篇

         圖形圖像處理-之-一個複雜度爲常數的快速局部自適應算法 下篇
                      
[email protected]    2008.04.12

 

(2009.03.10  可以到這裏下載完整的可以編譯的項目源代碼: http://cid-10fa89dec380323f.skydrive.live.com/browse.aspx/.Public?uc=4

 

tag: 圖像二值化,局部自適應,二維模板
  
摘要: 圖像處理中,某些算法在對一個像素的處理都需要根據周圍很多像素的綜合信息
來做處理,這類算法一般叫做局部自適應算法;用以得到更好的處理效果,但很多時候
這都可能成爲一個性能瓶頸,因爲對一個像素點都需要做大量的處理;本文將提供我使
用的一個複雜度爲常數的快速局部自適應算法。
(當然,某些二維模板不一定能夠拆解成常數算法,但很多還是可以拆解成線性算法的)
       
正文:
  代碼使用C++,編譯器:VC2005
  測試平臺:(CPU:AMD64x2 4200+(2.37G); 內存:DDR2 677(雙通道); 編譯器:VC2005)
 
(請先參看文章的上篇)


E:我們來優化它,得到一個線性複雜度的算法
  考慮一下,一行上相鄰的兩個像素,如果知道了上一個像素周圍的亮度和,那麼模板
移動一個像素後的亮度和也能很容易根據上一個亮度和得到;所以有了新的實現:

     // 返回圖像src中座標爲(x,y0)的縱軸上距離localHalfWidth內的所有像素的亮度和
     long  getLocalLight_linearV( const  TPicRegion &  src, long  x, long  y0, long  localHalfWidth)
    {
        
long  sumYLight = 0 ;
        
for  ( long  y = y0 - localHalfWidth;y <= y0 + localHalfWidth; ++ y)
        {
            
const  TARGB32 &  mapBorderColor = getMapBorderColor(src,x,y);
            sumYLight
+= getGrayInt(mapBorderColor);
        }
        
return  sumYLight;
    }
    
// 返回圖像src中座標爲(x0,y)的橫軸上距離localHalfWidth內的所有像素的亮度和
     long  getLocalLight_linearH( const  TPicRegion &  src, long  x0, long  y, long  localHalfWidth)
    {
        
long  sumXLight = 0 ;
        
for  ( long  x = x0 - localHalfWidth;x <= x0 + localHalfWidth; ++ x)
        {
            
const  TARGB32 &  mapBorderColor = getMapBorderColor(src,x,y);
            sumXLight
+= getGrayInt(mapBorderColor);
        }
        
return  sumXLight;
    }
void  localAdaptiveThreshold_linear( const  TPicRegion &  dst, const  TPicRegion &  src, long  localWidth)
{
    
long  width = dst.width;
    
if  (src.width < width) width = src.width;
    
long  height = dst.height;
    
if  (src.height < height) height = src.height;
    TARGB32
*  srcLine = src.pdata;
    TARGB32
*  dstLine = dst.pdata;
    
long  localHalfWidth = localWidth / 2 ;
    
long  tLocalWidth = localHalfWidth * 2 + 1 ;
    
long  tLocalWidthSqr = tLocalWidth * tLocalWidth;
    
long  sumLight0 = getLocalLight_quadratic(src, - 1 , - 1 ,localHalfWidth);
    
for  ( long  y = 0 ;y < height; ++ y)
    {
        sumLight0
= sumLight0 
                
+ getLocalLight_linearH(src, - 1 ,y + localHalfWidth,localHalfWidth)
                
- getLocalLight_linearH(src, - 1 ,y - localHalfWidth - 1 ,localHalfWidth);
        
long  sumLight = sumLight0;
        
for  ( long  x = 0 ;x < width; ++ x)
        {
            sumLight
= sumLight
                    
+ getLocalLight_linearV(src,x + localHalfWidth,y,localHalfWidth)
                    
- getLocalLight_linearV(src,x - localHalfWidth - 1 ,y,localHalfWidth);
            
long  light = getGrayInt(srcLine[x]);
            TUInt32 color
= ((sumLight - light * tLocalWidthSqr) >> 31 );
            ((TUInt32
* )dstLine)[x] = color; 
        }
        (TUInt8
*& )srcLine += src.byte_width;
        (TUInt8
*& )dstLine += dst.byte_width;
    }
}

 

localAdaptiveThreshold_linear函數的功能和localAdaptiveThreshold_quadratic的完全一樣;
速度測試:

//////////////////////////////////////////////////////////////
//                      localWidth=   5 |  17 |  51 | 151 
//------------------------------------------------------------
//localAdaptiveThreshold_linear    21.25  7.20  2.33  0.72 FPS
//////////////////////////////////////////////////////////////

恩,隨着localWidth的增大,函數速度成線性降低

F:繼續優化,得到一個常數複雜度的算法
  我們考慮了水平方向的計算優化,再來看看垂直方向上的計算節約,保留上一行的所有亮度和,
爲下一行的計算服務;算法實現如下:

    inline  long  getLocalLight_constant( const  TPicRegion &  src, long  x, long  y)
    {
        
return  getGrayInt(getMapBorderColor(src,x,y));
    }
void  localAdaptiveThreshold_constant( const  TPicRegion &  dst, const  TPicRegion &  src, long  localWidth)
{
    
long  width = dst.width;
    
if  (src.width < width) width = src.width;
    
if  (width <= 0 return ;
    
long  height = dst.height;
    
if  (src.height < height) height = src.height;
    TARGB32
*  srcLine = src.pdata;
    TARGB32
*  dstLine = dst.pdata;
    
long  localHalfWidth = localWidth / 2 ;
    
long  tLocalWidth = localHalfWidth * 2 + 1 ;
    
long  tLocalWidthSqr = tLocalWidth * tLocalWidth;

    
long *  _sumLightArray = new   long [width + 1 ];
    
long *  sumLightArray =& _sumLightArray[ 1 ];
    sumLightArray[
- 1 ] = getLocalLight_quadratic(src, - 1 , - 1 ,localHalfWidth);
    
for  ( long  x = 0 ;x < width; ++ x)
    {
        sumLightArray[x] 
=  sumLightArray[x - 1 ]
                
+ getLocalLight_linearV(src,x + localHalfWidth, - 1 ,localHalfWidth)
                
- getLocalLight_linearV(src,x - localHalfWidth - 1 , - 1 ,localHalfWidth);
    }

    
for  ( long  y = 0 ;y < height; ++ y)
    {
        
long  sumLight0 = sumLightArray[ - 1 ]
                
+ getLocalLight_linearH(src, - 1 ,y + localHalfWidth,localHalfWidth)
                
- getLocalLight_linearH(src, - 1 ,y - localHalfWidth - 1 ,localHalfWidth);
        
for  ( long  x = 0 ;x < width; ++ x)
        {
            
long  sumLight = sumLight0 + sumLightArray[x] - sumLightArray[x - 1 ]
                     
+ getLocalLight_constant(src,x - localHalfWidth - 1 ,y - localHalfWidth - 1 )
                     
+ getLocalLight_constant(src,x + localHalfWidth,y + localHalfWidth)
                     
- getLocalLight_constant(src,x + localHalfWidth,y - localHalfWidth - 1 )
                     
- getLocalLight_constant(src,x - localHalfWidth - 1 ,y + localHalfWidth);

            sumLightArray[x
- 1 ] = sumLight0;
            sumLight0
= sumLight;

            
long  light = getGrayInt(srcLine[x]);
            TUInt32 color
= ((sumLight - light * tLocalWidthSqr) >> 31 );
            ((TUInt32
* )dstLine)[x] = color; 
        }
        sumLightArray[width
- 1 ] = sumLight0;
        (TUInt8
*& )srcLine += src.byte_width;
        (TUInt8
*& )dstLine += dst.byte_width;
    }

    delete []_sumLightArray;
}

 

localAdaptiveThreshold_constant函數的功能和localAdaptiveThreshold_quadratic的完全一樣;
速度測試:
//////////////////////////////////////////////////////////////
//                      localWidth=   5 |  17 |  51 | 151 
//------------------------------------------------------------
//localAdaptiveThreshold_constant  57.30 56.00 51.89 43.00 FPS
//////////////////////////////////////////////////////////////

:D 隨着localWidth的增大,速度變化不大!

  當然,該函數還可以繼續優化的,比如將邊界和內部區域分開處理;
比如使用MMX、SSE等的指令,等等;
   該常數複雜度算法的實現也可以用兩次模板運算來實現的,申請一個和源圖片一樣大的臨時緩
衝區,先計算緩衝區的每個點(x,y)在源圖片(x,y)點垂直M範圍內的亮度和(可以做到常數複雜度),
那麼計算源圖片(x,y)點周圍的亮度和就可以通過計算緩衝區(x,y)點水平M範圍內的亮度和(也可
以做到常數複雜度)來獲得;


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章