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智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

Java ArrayList扩容机制 (源码解读)

结论:初始长度为10,若所需长度小于1.5倍原长度,则按照1.5倍扩容。若不够用则按照所需长度扩容。 一. 明确类内部重要变量含义         1:数组默认长度         2:这是一个共享的空数组实例,用于明确创建长度为0时的ArrayList ,比如通过 new ArrayList<>(0),ArrayList 内部的数组 elementData 会指向这个 EMPTY_EL

如何在Visual Studio中调试.NET源码

今天偶然在看别人代码时,发现在他的代码里使用了Any判断List<T>是否为空。 我一般的做法是先判断是否为null,再判断Count。 看了一下Count的源码如下: 1 [__DynamicallyInvokable]2 public int Count3 {4 [__DynamicallyInvokable]5 get

工厂ERP管理系统实现源码(JAVA)

工厂进销存管理系统是一个集采购管理、仓库管理、生产管理和销售管理于一体的综合解决方案。该系统旨在帮助企业优化流程、提高效率、降低成本,并实时掌握各环节的运营状况。 在采购管理方面,系统能够处理采购订单、供应商管理和采购入库等流程,确保采购过程的透明和高效。仓库管理方面,实现库存的精准管理,包括入库、出库、盘点等操作,确保库存数据的准确性和实时性。 生产管理模块则涵盖了生产计划制定、物料需求计划、

论文阅读笔记: Segment Anything

文章目录 Segment Anything摘要引言任务模型数据引擎数据集负责任的人工智能 Segment Anything Model图像编码器提示编码器mask解码器解决歧义损失和训练 Segment Anything 论文地址: https://arxiv.org/abs/2304.02643 代码地址:https://github.com/facebookresear

Spring 源码解读:自定义实现Bean定义的注册与解析

引言 在Spring框架中,Bean的注册与解析是整个依赖注入流程的核心步骤。通过Bean定义,Spring容器知道如何创建、配置和管理每个Bean实例。本篇文章将通过实现一个简化版的Bean定义注册与解析机制,帮助你理解Spring框架背后的设计逻辑。我们还将对比Spring中的BeanDefinition和BeanDefinitionRegistry,以全面掌握Bean注册和解析的核心原理。

音视频入门基础:WAV专题(10)——FFmpeg源码中计算WAV音频文件每个packet的pts、dts的实现

一、引言 从文章《音视频入门基础:WAV专题(6)——通过FFprobe显示WAV音频文件每个数据包的信息》中我们可以知道,通过FFprobe命令可以打印WAV音频文件每个packet(也称为数据包或多媒体包)的信息,这些信息包含该packet的pts、dts: 打印出来的“pts”实际是AVPacket结构体中的成员变量pts,是以AVStream->time_base为单位的显

kubelet组件的启动流程源码分析

概述 摘要: 本文将总结kubelet的作用以及原理,在有一定基础认识的前提下,通过阅读kubelet源码,对kubelet组件的启动流程进行分析。 正文 kubelet的作用 这里对kubelet的作用做一个简单总结。 节点管理 节点的注册 节点状态更新 容器管理(pod生命周期管理) 监听apiserver的容器事件 容器的创建、删除(CRI) 容器的网络的创建与删除

OmniGlue论文详解(特征匹配)

OmniGlue论文详解(特征匹配) 摘要1. 引言2. 相关工作2.1. 广义局部特征匹配2.2. 稀疏可学习匹配2.3. 半稠密可学习匹配2.4. 与其他图像表示匹配 3. OmniGlue3.1. 模型概述3.2. OmniGlue 细节3.2.1. 特征提取3.2.2. 利用DINOv2构建图形。3.2.3. 信息传播与新的指导3.2.4. 匹配层和损失函数3.2.5. 与Super

软件架构模式:5 分钟阅读

原文: https://orkhanscience.medium.com/software-architecture-patterns-5-mins-read-e9e3c8eb47d2 软件架构模式:5 分钟阅读 当有人潜入软件工程世界时,有一天他需要学习软件架构模式的基础知识。当我刚接触编码时,我不知道从哪里获得简要介绍现有架构模式的资源,这样它就不会太详细和混乱,而是非常抽象和易