分享

局部二值模式(LBP)中间过程的可视化

 昵称15226177 2014-10-15

      局部二值模式(Local Binary Pattern - LBP)是广泛用于图像分类的一种图像特征,它的特点是,在图像发生光照变化时,提取的特征仍然能够不发生大的改变。提取LBP的过程首先是将原始图像转换为LBP图,然后统计LBP图的LBP直方图,并以这个向量形式的直方图来表示原始的图像。由于目前不少开源的LBP实现代码没有给出中间过程的可视化步骤,这里给出了由原始图转换为LBP图的C++代码。


      转换LBP图的代码



  1. #include <iostream>  
  2.   
  3. #include <opencv2/core/core.hpp>  
  4. #include <opencv2/imgproc/imgproc.hpp>  
  5. #include <opencv2/highgui/highgui.hpp>  
  6.   
  7. #ifdef _DEBUG  
  8. #pragma comment( lib, "opencv_core245d.lib" )  
  9. #pragma comment( lib, "opencv_imgproc245d.lib" )  
  10. #pragma comment( lib, "opencv_highgui245d.lib" )  
  11. #else  
  12. #pragma comment( lib, "opencv_core245.lib" )  
  13. #pragma comment( lib, "opencv_imgproc245.lib" )  
  14. #pragma comment( lib, "opencv_highgui245.lib" )  
  15. #endif  
  16.   
  17. int main( int argc, char * argv[] )  
  18. {  
  19.     if ( argc != 4 )  
  20.     {  
  21.         std::cerr << "Arguments not valid." << std::endl;  
  22.         return 1;  
  23.     }  
  24.   
  25.     //////////////////////////////////////////////////////////////////////////  
  26.   
  27.     cv::Mat image = cv::imread( argv[1], 0 );  
  28.     bool bRotation = true;  
  29.     bool bMapping = atoi( argv[3] );  
  30.   
  31.     if ( image.empty() )  
  32.     {  
  33.         std::cerr << "Input image name not valid." << std::endl;  
  34.         return 2;  
  35.     }  
  36.   
  37.     //////////////////////////////////////////////////////////////////////////  
  38.   
  39.     unsigned int valMap[256];  
  40.   
  41.     if ( bMapping )  
  42.     {  
  43.         for ( int i = 0; i < 256; i++ )  
  44.         {  
  45.             valMap[i] = 57;  
  46.         }  
  47.   
  48.         valMap[0x00] = 56;  
  49.         valMap[0xff] = 56;  
  50.   
  51.         for ( int i = 0 ; i < 8 ; ++i )   
  52.         {   
  53.             for ( int j = 1 ; j <= 7 ; ++j )   
  54.             {  
  55.   
  56.                 unsigned int nByte = (1 << j) - 1 ;  
  57.   
  58.                 /* put i zeroes in front */  
  59.                 nByte <<= i ;  
  60.   
  61.                 /* wrap around 8 bit boundaries */  
  62.                 nByte = (nByte | (nByte >> 8)) & 0xff ;  
  63.   
  64.                 /* optionally transpose the pattern */  
  65.                 if ( bRotation )   
  66.                 {  
  67.                     unsigned int original = nByte;  
  68.   
  69.                     /* flip the string left-right */  
  70.                     nByte = 0;  
  71.   
  72.                     for ( int k = 0 ; k < 8 ; ++k)  
  73.                     {  
  74.                         nByte <<= 1 ;  
  75.                         nByte |= original & 0x1  ;  
  76.                         original >>= 1 ;  
  77.                     }  
  78.   
  79.                     /* rotate 90 degrees */  
  80.                     nByte <<= 3 ;  
  81.                     nByte = ( nByte | ( nByte >> 8 ) ) & 0xff ;  
  82.                 }  
  83.   
  84.                 valMap[nByte] = i * 7 + ( j - 1 ) ;  
  85.             }  
  86.         }  
  87.     }  
  88.   
  89.     //////////////////////////////////////////////////////////////////////////  
  90.   
  91.     cv::Mat imageLBP = cv::Mat::zeros( image.size(), image.type() );  
  92.   
  93.     for ( int y = 1; y < image.rows - 1; y++ )  
  94.     {     
  95.         for ( int x = 1; x < image.cols - 1; x++ )  
  96.         {  
  97.             unsigned int bitString = 0 ;  
  98.             unsigned char center = image.at<unsigned char>( cv::Point( x, y ) );  
  99.             if(image.at<unsigned char>( cv::Point(x+1,y+0) ) > center ) bitString |= 0x1 << 0; /*  E */  
  100.             if(image.at<unsigned char>( cv::Point(x+1,y+1) ) > center ) bitString |= 0x1 << 1; /* SE */  
  101.             if(image.at<unsigned char>( cv::Point(x+0,y+1) ) > center ) bitString |= 0x1 << 2; /* S  */  
  102.             if(image.at<unsigned char>( cv::Point(x-1,y+1) ) > center ) bitString |= 0x1 << 3; /* SW */  
  103.             if(image.at<unsigned char>( cv::Point(x-1,y+0) ) > center ) bitString |= 0x1 << 4; /*  W */  
  104.             if(image.at<unsigned char>( cv::Point(x-1,y-1) ) > center ) bitString |= 0x1 << 5; /* NW */  
  105.             if(image.at<unsigned char>( cv::Point(x+0,y-1) ) > center ) bitString |= 0x1 << 6; /* N  */  
  106.             if(image.at<unsigned char>( cv::Point(x+1,y-1) ) > center ) bitString |= 0x1 << 7; /* NE */  
  107.             if(bMapping) bitString = valMap[bitString];  
  108.             imageLBP.at<unsigned char>( cv::Point(x, y) ) = bitString;  
  109.         }  
  110.     }  
  111.   
  112.     if ( !cv::imwrite( argv[2], imageLBP ) )  
  113.     {  
  114.         std::cerr << "Output mage name not valid." << std::endl;  
  115.         return 3;  
  116.     }  
  117.   
  118.     return 0;  
  119. }  
      使用方法



  1. /** Convert to 256 Code LBP Image */  
  2. /** 转换为 256 Code LBP图 */  
  3. // Program.exe [原始图像路径] [输出图像路径] 0  
  4.   
  5. /** Convert to 56 Code LBP Image */  
  6. /** 转换为 56 Code LBP图 */  
  7. // Program.exe [原始图像路径] [输出图像路径] 1  

      实验结果





原始图像及其对应的256 Code和56 Code LBP图





光照发生改变的图像及其对应的256 Code和56 Code LBP图


       由上图可以看出,当图像发生光照变化时,其提取的LBP图是基本上不变的;而56 Code LBP图相对于256Code LBP图变化会更小一些。




      局部二值模式(Local Binary Pattern - LBP)是广泛用于图像分类的一种图像特征,它的特点是,在图像发生光照变化时,提取的特征仍然能够不发生大的改变。提取LBP的过程首先是将原始图像转换为LBP图,然后统计LBP图的LBP直方图,并以这个向量形式的直方图来表示原始的图像。由于目前不少开源的LBP实现代码没有给出中间过程的可视化步骤,这里给出了由原始图转换为LBP图的C++代码。


      转换LBP图的代码



  1. #include <iostream>  
  2.   
  3. #include <opencv2/core/core.hpp>  
  4. #include <opencv2/imgproc/imgproc.hpp>  
  5. #include <opencv2/highgui/highgui.hpp>  
  6.   
  7. #ifdef _DEBUG  
  8. #pragma comment( lib, "opencv_core245d.lib" )  
  9. #pragma comment( lib, "opencv_imgproc245d.lib" )  
  10. #pragma comment( lib, "opencv_highgui245d.lib" )  
  11. #else  
  12. #pragma comment( lib, "opencv_core245.lib" )  
  13. #pragma comment( lib, "opencv_imgproc245.lib" )  
  14. #pragma comment( lib, "opencv_highgui245.lib" )  
  15. #endif  
  16.   
  17. int main( int argc, char * argv[] )  
  18. {  
  19.     if ( argc != 4 )  
  20.     {  
  21.         std::cerr << "Arguments not valid." << std::endl;  
  22.         return 1;  
  23.     }  
  24.   
  25.     //////////////////////////////////////////////////////////////////////////  
  26.   
  27.     cv::Mat image = cv::imread( argv[1], 0 );  
  28.     bool bRotation = true;  
  29.     bool bMapping = atoi( argv[3] );  
  30.   
  31.     if ( image.empty() )  
  32.     {  
  33.         std::cerr << "Input image name not valid." << std::endl;  
  34.         return 2;  
  35.     }  
  36.   
  37.     //////////////////////////////////////////////////////////////////////////  
  38.   
  39.     unsigned int valMap[256];  
  40.   
  41.     if ( bMapping )  
  42.     {  
  43.         for ( int i = 0; i < 256; i++ )  
  44.         {  
  45.             valMap[i] = 57;  
  46.         }  
  47.   
  48.         valMap[0x00] = 56;  
  49.         valMap[0xff] = 56;  
  50.   
  51.         for ( int i = 0 ; i < 8 ; ++i )   
  52.         {   
  53.             for ( int j = 1 ; j <= 7 ; ++j )   
  54.             {  
  55.   
  56.                 unsigned int nByte = (1 << j) - 1 ;  
  57.   
  58.                 /* put i zeroes in front */  
  59.                 nByte <<= i ;  
  60.   
  61.                 /* wrap around 8 bit boundaries */  
  62.                 nByte = (nByte | (nByte >> 8)) & 0xff ;  
  63.   
  64.                 /* optionally transpose the pattern */  
  65.                 if ( bRotation )   
  66.                 {  
  67.                     unsigned int original = nByte;  
  68.   
  69.                     /* flip the string left-right */  
  70.                     nByte = 0;  
  71.   
  72.                     for ( int k = 0 ; k < 8 ; ++k)  
  73.                     {  
  74.                         nByte <<= 1 ;  
  75.                         nByte |= original & 0x1  ;  
  76.                         original >>= 1 ;  
  77.                     }  
  78.   
  79.                     /* rotate 90 degrees */  
  80.                     nByte <<= 3 ;  
  81.                     nByte = ( nByte | ( nByte >> 8 ) ) & 0xff ;  
  82.                 }  
  83.   
  84.                 valMap[nByte] = i * 7 + ( j - 1 ) ;  
  85.             }  
  86.         }  
  87.     }  
  88.   
  89.     //////////////////////////////////////////////////////////////////////////  
  90.   
  91.     cv::Mat imageLBP = cv::Mat::zeros( image.size(), image.type() );  
  92.   
  93.     for ( int y = 1; y < image.rows - 1; y++ )  
  94.     {     
  95.         for ( int x = 1; x < image.cols - 1; x++ )  
  96.         {  
  97.             unsigned int bitString = 0 ;  
  98.             unsigned char center = image.at<unsigned char>( cv::Point( x, y ) );  
  99.             if(image.at<unsigned char>( cv::Point(x+1,y+0) ) > center ) bitString |= 0x1 << 0; /*  E */  
  100.             if(image.at<unsigned char>( cv::Point(x+1,y+1) ) > center ) bitString |= 0x1 << 1; /* SE */  
  101.             if(image.at<unsigned char>( cv::Point(x+0,y+1) ) > center ) bitString |= 0x1 << 2; /* S  */  
  102.             if(image.at<unsigned char>( cv::Point(x-1,y+1) ) > center ) bitString |= 0x1 << 3; /* SW */  
  103.             if(image.at<unsigned char>( cv::Point(x-1,y+0) ) > center ) bitString |= 0x1 << 4; /*  W */  
  104.             if(image.at<unsigned char>( cv::Point(x-1,y-1) ) > center ) bitString |= 0x1 << 5; /* NW */  
  105.             if(image.at<unsigned char>( cv::Point(x+0,y-1) ) > center ) bitString |= 0x1 << 6; /* N  */  
  106.             if(image.at<unsigned char>( cv::Point(x+1,y-1) ) > center ) bitString |= 0x1 << 7; /* NE */  
  107.             if(bMapping) bitString = valMap[bitString];  
  108.             imageLBP.at<unsigned char>( cv::Point(x, y) ) = bitString;  
  109.         }  
  110.     }  
  111.   
  112.     if ( !cv::imwrite( argv[2], imageLBP ) )  
  113.     {  
  114.         std::cerr << "Output mage name not valid." << std::endl;  
  115.         return 3;  
  116.     }  
  117.   
  118.     return 0;  
  119. }  
      使用方法



  1. /** Convert to 256 Code LBP Image */  
  2. /** 转换为 256 Code LBP图 */  
  3. // Program.exe [原始图像路径] [输出图像路径] 0  
  4.   
  5. /** Convert to 56 Code LBP Image */  
  6. /** 转换为 56 Code LBP图 */  
  7. // Program.exe [原始图像路径] [输出图像路径] 1  

      实验结果





原始图像及其对应的256 Code和56 Code LBP图





光照发生改变的图像及其对应的256 Code和56 Code LBP图


       由上图可以看出,当图像发生光照变化时,其提取的LBP图是基本上不变的;而56 Code LBP图相对于256Code LBP图变化会更小一些。




    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多