.NET中的快速对象检测

633 篇文章 16 订阅
564 篇文章 57 订阅

目录

介绍

背景

Haar-like特征

级联和阶段

积分图像

方差归一化

扫描过程

嵌套矩形的平均值

使用库

参数

一个例子


介绍

Viola-Jones目标检测算法最流行和最快的实现无疑是OpenCV的实现。但是OpenCV要求包装类可用于.NET语言,并且.NETBitmap对象必须在与OpenCV一起使用之前转换为IplImage格式。另一方面,使用OpenCV的程序依赖于所有OpenCV库及其包装器。使用OpenCV的功能时,这些都不是问题。但是如果我们只需要检测位图上的对象,那么让我们的程序依赖于所有OpenCV库和包装器是不值得的......

我编写了一个库(HaarCascadeClassifier.dll ),它可以在.NET中进行对象检测,而无需任何其他库要求。它是一个开源项目,包含Viola-Jones对象检测算法的实现。该库使用OpenCVXML文件)生成的haar级联来检测特定对象,例如人脸。

它可用于对象检测目的或仅用于了解算法以及参数如何影响结果或速度。

背景

其实我的目的是分享HaarCascadeClassifier.dll及其用法。所以我会尝试总结一下算法。

Viola and Jones的算法不直接使用像素来检测物体。它使用称为“haar-like features”的矩形特征。这些特征可以用234个矩形来表示。

Haar-like特征

haar-like特征的值被计算为覆盖该特征的矩形下像素的平均值与黑色矩形下的像素平均值之间的差。每个矩形用5个值表示;xywidth,heightweightxy是矩形将放置在搜索窗口上的坐标。Widthheight是矩形的大小。Weight乘以矩形内所有像素的总和。(因此,我们可以说黑色矩形的权重值为负。)

级联和阶段

级联的弱分类器用于确定图像上的子窗口是否包含搜索到的对象。级联的结构可以通过编程方式表示如下:

' Feature rectangle
Public Structure FeatureRect
   Public Rectangle As Rectangle
   Public Weight As Single
End Structure

' Binary tree nodes
Public Structure Node
   ' Feature rectangles
   Public FeatureRects As List(Of FeatureRect)
   
   ' Threshold for determining what to select (left value/right value) or where to go on
   ' binary tree (left or right)
   Public Threshold As Single
   
   ' Left value
   Public LeftVal As Single

   ' Right value
   Public RightVal As Single
   
   ' Does this node have a left node? (Checking a boolean takes less time then to control
   ' if left node is null or not.)              
   Public HasLNode As Boolean
   
   ' Left node. If the current node doesn't have a left node, this will be null.
   Public LeftNode As Integer
   
   ' Does this node have a right node?
   Public HasRNode As Boolean
   
   ' Right node. If the current node doesn't have a right node, this will be null.
   Public RightNode As Integer
End Structure

' Will be used as a binary tree
Public Structure Tree
   Public Nodes As List(Of Node)
End Structure

' Stages
Public Structure Stage
   ' Trees in the stage.
   Public Trees As List(Of Tree)
   
   ' Threshold of the stage.
   Public Threshold As Single
End Structure

' Stages of the cascade
Public Stages As List(Of Stage)

将特征应用于子图像,直到子图像被其中一个拒绝或全部传递。

节点的值计算为节点内所有特征的总和,用于确定下一个节点或将添加到阶段值的值。如果当前节点是叶子(表示它没有节点)并且计算的节点值小于阈值,则将左值(否则右值)添加到阶段值(RightValLeftVal)。如果当前节点不是叶子,则在下一个节点上进行特征(如果特征值小于阈值LeftNode,否则为RightNode),根据当前节点的值选择的必须应用于相同的子图像。在对当前阶段的每棵树完成后,将计算的阶段值与阶段阈值进行比较。如果小于,则表示子图像不包含搜索到的对象,直接将其消除而不应用剩余阶段。

积分图像

积分图像是一种加速算法的方法。一个位置的积分图像是该位置上方和左侧所有像素的总和。(CalculateCumSums32bpp()CalculateCumSums24bpp()CalculateCumSums8bpp())。它用于非常快速地计算矩形内的像素总和。

例如,阴影矩形下的像素总和可以计算为IntegralImage(D) - IntegralImage(B) - IntegralImage(C) + IntegralImage(A)

方差归一化

在训练过程中,对每张图像的方差进行归一化处理,以减少不同光照条件的影响。因此,在检测期间必须对所有子窗口进行归一化。也可以对阈值进行归一化,而不是对图像方差进行归一化(这样更快)。阈值乘以当前子窗口中像素的标准偏差以进行标准化。

扫描过程

扫描过程是算法的重要组成部分。几乎所有Detect()库函数所需的参数都用于优化此过程。

在扫描过程中,使用缩放的搜索窗口将分类器应用于所有子图像。(特征也被缩放。)

While Scaler < MaxScale
   .... 
   Scaler = Scaler * ScaleMult
End While 

搜索窗口的步长通过SlidingRatio乘以当前搜索窗口宽度来计算。这意味着搜索窗口的每一步都等于StepSize像素。

For i = 0 To ImageWidth - SearchingWinWidth - 1 Step StepSize
   For j = 0 To ImageWidth - SearchingWinHeight - 1 Step StepSize
      ...
   Next
Next

嵌套矩形的平均值

可以不止一次地在不同的尺度上检测到对象。这会导致表示对象位置的矩形被嵌套。

必须计算这些矩形的平均值,并且必须从返回的结果中消除所有嵌套的矩形。

如果矩形边缘之间的距离足够短,则认为它们是嵌套的。目标阈值是通过将sizeMultForNesRectCon乘以其中一个矩形的大小(AreTheyNested())来获得的。

使用库

该库易于在所有.NET语言中使用。下面在C#中给出了一个示例。更多示例可以从此处下载已编译的可执行文件。

参数

范围

描述

MaxDetCount

当检测到的物体数量达到此值时,探测器停止搜索。

MinNRectCount

必须从检测器通过以验证搜索对象是否存在的最小相邻区域。

FirstScale

搜索窗口的第一个缩放器。

MaxScale

搜索窗口的最大缩放器。

ScaleMult

ScaleMult(Scale Multiplier)和当前缩放器相乘以在当前缩放器上进行增量。

SizeMultForNesRectCon

SizeMultForNesRectCon(嵌套对象控件的大小乘数)和每个矩形的大小分别相乘以获得当前矩形与其他矩形之间可接受的最大水平和垂直距离。最大距离用于检查矩形是否嵌套。

SlidingRatio

步长与缩放搜索窗口宽度的比率。CurrentStepSize = ScaledWindowWidth * SlidingRatio)

Pen

在给定位图上绘制矩形的Pen对象。如果给定为null,则不会绘制任何内容。

一个例子

准备所需参数:

int maxDetCount = Int32.MaxValue;
int minNRectCount = 0;
float firstScale = detector.Size2Scale(100);
float maxScale = detector.Size2Scale(400);
float scaleMult = 1.1f;
float sizeMultForNesRectCon = 0.3f;
float slidingRatio = 0.2f;
Pen pen = new Pen(Brushes.Red, 4);
HaarCascadeClassifer.HaarDetector.DetectionParams detectorParameters;
detectorParameters = 
    new HaarCascadeClassifer.HaarDetector.DetectionParams(maxDetCount, minNRectCount, 
    firstScale, maxScale, scaleMult, sizeMultForNesRectCon, slidingRatio, pen);

加载嵌入式XML haar级联:

XmlDocument xmlDoc=new XmlDocument();
xmlDoc.LoadXml(HaarCascadeClassifer.My.Resources.Resources.haarcascade_frontalface_alt);
HaarDetector detector = new HaarDetector(xmlDoc);

从外部XML文件加载haar级联:

XmlDocument xmlDoc=new XmlDocument();
xmlDoc.Load("haarcascade_frontalface_alt.xml");
HaarDetector detector = new HaarDetector(xmlDoc);

检测:

Bitmap bmp = new Bitmap("C:\bitmap.bmp");
HaarCascadeClassifer.HaarDetector.DResults results = 
                     detector.Detect(ref bmp, detectorParameters);

results包含以下内容:

results.NOfObjects               // Number of detected objects
results.DetectedOLocs            // Locations of detected objects (Rectangles)
results.SearchedSubRegionCount   // Number of searched subregions

      https://www.codeproject.com/Articles/436521/Rapid-Object-Detection-in-NET

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值