OpenCV的Filter2D代码解析

Filter是一个非常耗时的操作,不过Opencv的Filter写法比较特别

这里把原理解析一下,就可以编写自己的filter代码了


1. 首先把边界预先处理,然后再处理非边界部分(防止溢出)

2. 每行处理dst图像,而src的指针加1,这里为什么是src++呢?实际上这里src保留的是源数据的每行首地址

3. 对于5*5的核来说,k_ptr实际上保留了与src有关的25个指针地址,分别对应kernel里面的每一项。这25个指针地址,也只是src的每行的首地址。

所以后面使用的时候,sptr = (*kp++) + i;其中kp就是这个首地址,偏置为i。k_ptr里面的每个值都是一个源图的图像数据地址。

也就是说,OpenCV在计算每个核的时候,首先把与dst每个像素对应的那个源数据区域所用的像素点地址计算出来了,这对于Sparse的核来说非常重要。另外,当核很大时,这样事先计算出地址的方法也能提高cache的概率。

4. 在while循环里面实现这个线性核的所有计算,比如,5*5的核,25个乘法和25个加法。kc表示核系数的首地址。


	for( ; count > 0; count--, dst += dst_step, src++ )      // 处理dst的每一行,每行之后,把src的指针+1,
    {                                                       
        for( k = 0; k < k_count; k++ )                      
            k_ptr[k] = src[k_sparse[k].y] + k_sparse[k].x;  
                                                            
        for( i = 0; i <= width - 4; i += 4 )                
        {                                                   
            const arrtype** kp = k_ptr;                     
            const float* kc = k_coeffs;                     
            double s0 = 0, s1 = 0, s2 = 0, s3 = 0;          
            worktype t0, t1;                                
                                                            
            while( kp != k_end )                            
            {                                               
                const arrtype* sptr = (*kp++) + i;          
                float f = *kc++;                            
                s0 += f*load_macro(sptr[0]);                
                s1 += f*load_macro(sptr[1]);                
                s2 += f*load_macro(sptr[2]);                
                s3 += f*load_macro(sptr[3]);                
            }                                               
                                                            
            t0 = cast_macro1(s0); t1 = cast_macro1(s1);     
            dst[i] = cast_macro2(t0);                       
            dst[i+1] = cast_macro2(t1);                     
            t0 = cast_macro1(s2); t1 = cast_macro1(s3);     
            dst[i+2] = cast_macro2(t0);                     
            dst[i+3] = cast_macro2(t1);                     
        }                                                   
                                                            
        for( ; i < width; i++ )                             
        {                                                   
            const arrtype** kp = k_ptr;                     
            const float* kc = k_coeffs;                     
            double s0 = 0;                                  
            worktype t0;                                    
                                                            
            while( kp != k_end )                            
            {                                               
                const arrtype* sptr = *kp++;                
                float f = *kc++;                            
                s0 += f*load_macro(sptr[i]);                
            }                                               
                                                            
            t0 = cast_macro1(s0);                           
            dst[i] = cast_macro2(t0);                       
        }                                                   
    }                                                       


你可能感兴趣的:(OpenCV的Filter2D代码解析)