train_cascade 源码阅读之Haar特征

2024-01-12 12:08

本文主要是介绍train_cascade 源码阅读之Haar特征,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

下面片段是生成用于在积分图中的矩形块的坐标,Feature类中存的是在积分图矩阵中的初始偏移量,矩形的左上角坐标和宽高,以及是否旋转。不同类型的Haar特征已经在代码中体现的很明确了,故不赘述。
[cpp]  view plain copy
在CODE上查看代码片 派生到我的代码片
  1. <span style="font-size:14px;">void CvHaarEvaluator::generateFeatures()  
  2. {  
  3.     int mode = ((const CvHaarFeatureParams*)((CvFeatureParams*)featureParams))->mode;  
  4.     int offset = winSize.width + 1;  
  5.     forint x = 0; x < winSize.width; x++ )  
  6.     {  
  7.         forint y = 0; y < winSize.height; y++ )  
  8.         {  
  9.             forint dx = 1; dx <= winSize.width; dx++ )  
  10.             {  
  11.                 forint dy = 1; dy <= winSize.height; dy++ )  
  12.                 {  
  13.                     // haar_x2  
  14.                     if ( (x+dx*2 <= winSize.width) && (y+dy <= winSize.height) )  
  15.                     {  
  16.                         features.push_back( Feature( offset, false,  
  17.                             x,    y, dx*2, dy, -1,  
  18.                             x+dx, y, dx  , dy, +2 ) );  
  19.                     }  
  20.                     // haar_y2  
  21.                     if ( (x+dx <= winSize.width) && (y+dy*2 <= winSize.height) )  
  22.                     {  
  23.                         features.push_back( Feature( offset, false,  
  24.                             x,    y, dx, dy*2, -1,  
  25.                             x, y+dy, dx, dy,   +2 ) );  
  26.                     }  
  27.                     // haar_x3  
  28.                     if ( (x+dx*3 <= winSize.width) && (y+dy <= winSize.height) )  
  29.                     {  
  30.                         features.push_back( Feature( offset, false,  
  31.                             x,    y, dx*3, dy, -1,  
  32.                             x+dx, y, dx  , dy, +3 ) );  
  33.                     }  
  34.                     // haar_y3  
  35.                     if ( (x+dx <= winSize.width) && (y+dy*3 <= winSize.height) )  
  36.                     {  
  37.                         features.push_back( Feature( offset, false,  
  38.                             x, y,    dx, dy*3, -1,  
  39.                             x, y+dy, dx, dy,   +3 ) );  
  40.                     }  
  41.                     if( mode != CvHaarFeatureParams::BASIC )  
  42.                     {  
  43.                         // haar_x4  
  44.                         if ( (x+dx*4 <= winSize.width) && (y+dy <= winSize.height) )  
  45.                         {  
  46.                             features.push_back( Feature( offset, false,  
  47.                                 x,    y, dx*4, dy, -1,  
  48.                                 x+dx, y, dx*2, dy, +2 ) );  
  49.                         }  
  50.                         // haar_y4  
  51.                         if ( (x+dx <= winSize.width ) && (y+dy*4 <= winSize.height) )  
  52.                         {  
  53.                             features.push_back( Feature( offset, false,  
  54.                                 x, y,    dx, dy*4, -1,  
  55.                                 x, y+dy, dx, dy*2, +2 ) );  
  56.                         }  
  57.                     }  
  58.                     // x2_y2  
  59.                     if ( (x+dx*2 <= winSize.width) && (y+dy*2 <= winSize.height) )  
  60.                     {  
  61.                         features.push_back( Feature( offset, false,  
  62.                             x,    y,    dx*2, dy*2, -1,  
  63.                             x,    y,    dx,   dy,   +2,  
  64.                             x+dx, y+dy, dx,   dy,   +2 ) );  
  65.                     }  
  66.                     if (mode != CvHaarFeatureParams::BASIC)  
  67.                     {  
  68.                         if ( (x+dx*3 <= winSize.width) && (y+dy*3 <= winSize.height) )  
  69.                         {  
  70.                             features.push_back( Feature( offset, false,  
  71.                                 x   , y   , dx*3, dy*3, -1,  
  72.                                 x+dx, y+dy, dx  , dy  , +9) );  
  73.                         }  
  74.                     }  
  75.                     if (mode == CvHaarFeatureParams::ALL)  
  76.                     {  
  77.                         // tilted haar_x2  
  78.                         if ( (x+2*dx <= winSize.width) && (y+2*dx+dy <= winSize.height) && (x-dy>= 0) )  
  79.                         {  
  80.                             features.push_back( Feature( offset, true,  
  81.                                 x, y, dx*2, dy, -1,  
  82.                                 x, y, dx,   dy, +2 ) );  
  83.                         }  
  84.                         // tilted haar_y2  
  85.                         if ( (x+dx <= winSize.width) && (y+dx+2*dy <= winSize.height) && (x-2*dy>= 0) )  
  86.                         {  
  87.                             features.push_back( Feature( offset, true,  
  88.                                 x, y, dx, 2*dy, -1,  
  89.                                 x, y, dx, dy,   +2 ) );  
  90.                         }  
  91.                         // tilted haar_x3  
  92.                         if ( (x+3*dx <= winSize.width) && (y+3*dx+dy <= winSize.height) && (x-dy>= 0) )  
  93.                         {  
  94.                             features.push_back( Feature( offset, true,  
  95.                                 x,    y,    dx*3, dy, -1,  
  96.                                 x+dx, y+dx, dx,   dy, +3 ) );  
  97.                         }  
  98.                         // tilted haar_y3  
  99.                         if ( (x+dx <= winSize.width) && (y+dx+3*dy <= winSize.height) && (x-3*dy>= 0) )  
  100.                         {  
  101.                             features.push_back( Feature( offset, true,  
  102.                                 x,    y,    dx, 3*dy, -1,  
  103.                                 x-dy, y+dy, dx, dy,   +3 ) );  
  104.                         }  
  105.                         // tilted haar_x4  
  106.                         if ( (x+4*dx <= winSize.width) && (y+4*dx+dy <= winSize.height) && (x-dy>= 0) )  
  107.                         {  
  108.                             features.push_back( Feature( offset, true,  
  109.                                 x,    y,    dx*4, dy, -1,  
  110.                                 x+dx, y+dx, dx*2, dy, +2 ) );  
  111.                         }  
  112.                         // tilted haar_y4  
  113.                         if ( (x+dx <= winSize.width) && (y+dx+4*dy <= winSize.height) && (x-4*dy>= 0) )  
  114.                         {  
  115.                             features.push_back( Feature( offset, true,  
  116.                                 x,    y,    dx, 4*dy, -1,  
  117.                                 x-dy, y+dy, dx, 2*dy, +2 ) );  
  118.                         }  
  119.                     }  
  120.                 }  
  121.             }  
  122.         }  
  123.     }  
  124.     numFeatures = (int)features.size();  
  125. }</span>  
接着,在 CvHaarEvaluator::Feature构造函数中,对刚刚求得的坐标做了偏移量上的转换。
[cpp]  view plain copy
在CODE上查看代码片 派生到我的代码片
  1. <span style="font-size:14px;">CvHaarEvaluator::Feature::Feature( int offset, bool _tilted,  
  2.                                           int x0, int y0, int w0, int h0, float wt0,  
  3.                                           int x1, int y1, int w1, int h1, float wt1,  
  4.                                           int x2, int y2, int w2, int h2, float wt2 )  
  5. {  
  6.     tilted = _tilted;  
  7.   
  8.     rect[0].r.x = x0;  
  9.     rect[0].r.y = y0;  
  10.     rect[0].r.width  = w0;  
  11.     rect[0].r.height = h0;  
  12.     rect[0].weight   = wt0;  
  13.   
  14.     rect[1].r.x = x1;  
  15.     rect[1].r.y = y1;  
  16.     rect[1].r.width  = w1;  
  17.     rect[1].r.height = h1;  
  18.     rect[1].weight   = wt1;  
  19.   
  20.     rect[2].r.x = x2;  
  21.     rect[2].r.y = y2;  
  22.     rect[2].r.width  = w2;  
  23.     rect[2].r.height = h2;  
  24.     rect[2].weight   = wt2;  
  25.   
  26.     if( !tilted )  
  27.     {  
  28.         forint j = 0; j < CV_HAAR_FEATURE_MAX; j++ )  
  29.         {  
  30.             if( rect[j].weight == 0.0F )  
  31.                 break;  
  32.             CV_SUM_OFFSETS( fastRect[j].p0, fastRect[j].p1,   
  33.                             fastRect[j].p2, fastRect[j].p3, rect[j].r, offset )  
  34.         }  
  35.     }  
  36.     else  
  37.     {  
  38.         forint j = 0; j < CV_HAAR_FEATURE_MAX; j++ )  
  39.         {  
  40.             if( rect[j].weight == 0.0F )  
  41.                 break;  
  42.             CV_TILTED_OFFSETS( fastRect[j].p0, fastRect[j].p1,   
  43.                                fastRect[j].p2, fastRect[j].p3, rect[j].r, offset )  
  44.         }  
  45.     }  
  46. }  
  47. </span>  
CV_SUM_OFFSET和CV_TILTED_OFFSET是计算偏移量的宏,它们将左上角点和宽高转换成在单行sum或者tilted矩阵中的位置。sum矩阵的求法和LBP中是一样的,也是利用了OpenCV自带的cv::integral函数,而斜45度的矩阵也没有用到旋转图像之类的操作,而是…嗯,还是integral函数,自带重载功能,实现了45度倾斜操作。
[cpp]  view plain copy
在CODE上查看代码片 派生到我的代码片
  1. <span style="font-size:14px;">void CvHaarEvaluator::setImage(const Mat& img, uchar clsLabel, int idx)  
  2. {  
  3.     CV_DbgAssert( !sum.empty() && !tilted.empty() && !normfactor.empty() );  
  4.     CvFeatureEvaluator::setImage( img, clsLabel, idx);  
  5.     Mat innSum(winSize.height + 1, winSize.width + 1, sum.type(), sum.ptr<int>((int)idx));  
  6.     Mat innTilted(winSize.height + 1, winSize.width + 1, tilted.type(), tilted.ptr<int>((int)idx));  
  7.     Mat innSqSum;  
  8.     integral(img, innSum, innSqSum, innTilted);  
  9.     normfactor.ptr<float>(0)[idx] = calcNormFactor( innSum, innSqSum );  
  10. }</span>  
归一化因子计算如下:
[cpp]  view plain copy
在CODE上查看代码片 派生到我的代码片
  1. <span style="font-size:14px;">float calcNormFactor( const Mat& sum, const Mat& sqSum )  
  2. {  
  3.     CV_DbgAssert( sum.cols > 3 && sqSum.rows > 3 );  
  4.     Rect normrect( 1, 1, sum.cols - 3, sum.rows - 3 );  
  5.     size_t p0, p1, p2, p3;  
  6.     CV_SUM_OFFSETS( p0, p1, p2, p3, normrect, sum.step1() )  
  7.     double area = normrect.width * normrect.height;  
  8.     const int *sp = (const int*)sum.data;  
  9.     int valSum = sp[p0] - sp[p1] - sp[p2] + sp[p3];  
  10.     const double *sqp = (const double *)sqSum.data;  
  11.     double valSqSum = sqp[p0] - sqp[p1] - sqp[p2] + sqp[p3];  
  12.     return (float) sqrt( (double) (area * valSqSum - (double)valSum * valSum) );  
  13. }</span>  

SqSum是平方积分图。
最后,不同小块乘上权重系数,作为Haar特征值。
[cpp]  view plain copy
在CODE上查看代码片 派生到我的代码片
  1. <span style="font-size:14px;">inline float CvHaarEvaluator::Feature::calc(  
  2.         const cv::Mat &_sum,  
  3.         const cv::Mat &_tilted,  
  4.         size_t y) const  
  5. {  
  6.     const int* img = tilted ?  
  7.                 _tilted.ptr<int>((int)y) : _sum.ptr<int>((int)y);  
  8.     float ret = rect[0].weight * (  
  9.                 img[fastRect[0].p0]  
  10.             - img[fastRect[0].p1]  
  11.             - img[fastRect[0].p2]  
  12.             + img[fastRect[0].p3] ) +  
  13.             rect[1].weight * (  
  14.                 img[fastRect[1].p0]  
  15.             - img[fastRect[1].p1]  
  16.             - img[fastRect[1].p2]  
  17.             + img[fastRect[1].p3] );  
  18.     if( rect[2].weight != 0.0f )  
  19.         ret += rect[2].weight * (  
  20.                     img[fastRect[2].p0]  
  21.                 - img[fastRect[2].p1]  
  22.                 - img[fastRect[2].p2]  
  23.                 + img[fastRect[2].p3] );  
  24.     return ret;  
  25. }</span>  

这篇关于train_cascade 源码阅读之Haar特征的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/597813

相关文章

java 恺撒加密/解密实现原理(附带源码)

《java恺撒加密/解密实现原理(附带源码)》本文介绍Java实现恺撒加密与解密,通过固定位移量对字母进行循环替换,保留大小写及非字母字符,由于其实现简单、易于理解,恺撒加密常被用作学习加密算法的入... 目录Java 恺撒加密/解密实现1. 项目背景与介绍2. 相关知识2.1 恺撒加密算法原理2.2 Ja

Nginx屏蔽服务器名称与版本信息方式(源码级修改)

《Nginx屏蔽服务器名称与版本信息方式(源码级修改)》本文详解如何通过源码修改Nginx1.25.4,移除Server响应头中的服务类型和版本信息,以增强安全性,需重新配置、编译、安装,升级时需重复... 目录一、背景与目的二、适用版本三、操作步骤修改源码文件四、后续操作提示五、注意事项六、总结一、背景与

Android实现图片浏览功能的示例详解(附带源码)

《Android实现图片浏览功能的示例详解(附带源码)》在许多应用中,都需要展示图片并支持用户进行浏览,本文主要为大家介绍了如何通过Android实现图片浏览功能,感兴趣的小伙伴可以跟随小编一起学习一... 目录一、项目背景详细介绍二、项目需求详细介绍三、相关技术详细介绍四、实现思路详细介绍五、完整实现代码

HTML5 中的<button>标签用法和特征

《HTML5中的<button>标签用法和特征》在HTML5中,button标签用于定义一个可点击的按钮,它是创建交互式网页的重要元素之一,本文将深入解析HTML5中的button标签,详细介绍其属... 目录引言<button> 标签的基本用法<button> 标签的属性typevaluedisabled

8种快速易用的Python Matplotlib数据可视化方法汇总(附源码)

《8种快速易用的PythonMatplotlib数据可视化方法汇总(附源码)》你是否曾经面对一堆复杂的数据,却不知道如何让它们变得直观易懂?别慌,Python的Matplotlib库是你数据可视化的... 目录引言1. 折线图(Line Plot)——趋势分析2. 柱状图(Bar Chart)——对比分析3

Android实现一键录屏功能(附源码)

《Android实现一键录屏功能(附源码)》在Android5.0及以上版本,系统提供了MediaProjectionAPI,允许应用在用户授权下录制屏幕内容并输出到视频文件,所以本文将基于此实现一个... 目录一、项目介绍二、相关技术与原理三、系统权限与用户授权四、项目架构与流程五、环境配置与依赖六、完整

Android实现定时任务的几种方式汇总(附源码)

《Android实现定时任务的几种方式汇总(附源码)》在Android应用中,定时任务(ScheduledTask)的需求几乎无处不在:从定时刷新数据、定时备份、定时推送通知,到夜间静默下载、循环执行... 目录一、项目介绍1. 背景与意义二、相关基础知识与系统约束三、方案一:Handler.postDel

Java 正则表达式URL 匹配与源码全解析

《Java正则表达式URL匹配与源码全解析》在Web应用开发中,我们经常需要对URL进行格式验证,今天我们结合Java的Pattern和Matcher类,深入理解正则表达式在实际应用中... 目录1.正则表达式分解:2. 添加域名匹配 (2)3. 添加路径和查询参数匹配 (3) 4. 最终优化版本5.设计思

Java调用C++动态库超详细步骤讲解(附源码)

《Java调用C++动态库超详细步骤讲解(附源码)》C语言因其高效和接近硬件的特性,时常会被用在性能要求较高或者需要直接操作硬件的场合,:本文主要介绍Java调用C++动态库的相关资料,文中通过代... 目录一、直接调用C++库第一步:动态库生成(vs2017+qt5.12.10)第二步:Java调用C++

Python实现无痛修改第三方库源码的方法详解

《Python实现无痛修改第三方库源码的方法详解》很多时候,我们下载的第三方库是不会有需求不满足的情况,但也有极少的情况,第三方库没有兼顾到需求,本文将介绍几个修改源码的操作,大家可以根据需求进行选择... 目录需求不符合模拟示例 1. 修改源文件2. 继承修改3. 猴子补丁4. 追踪局部变量需求不符合很