上一节中我介绍了如何使用Opencv自带的opencv_traincascade.exe来做训练,接下来介绍如何使用训练生成的cascade.xml模型文件来检测车脸。

首先需要说明的是我这里的训练数据是卡口数据是在监控下面的照片,主要为了截取卡口摄像头拍摄下的照片的车脸部分,如下图是待检测图像:

这里主要基于了opencv中自带的检测函数,可以对目标物检测有一个较好的认识,读者可以用cmake生成Opencv的源码工程来细看具体实现细节(Cmake真是个神器)。这里用到了timer头文件,可以计算平均的检测时间。

一下是主要的代码部分,程序可以输出定位出来的坐标到txt文件中,同时也可以通过开关用imshow显示具体的截取效果。

给出工程链接github工程链接此处有链接!!

我的车是数据大部分都是如下,是卡口监控的拍摄图片

截出的车脸示意图,也可以用绿线在原图上标出,代码中已经将ROI部分截出,以下是代码部分。

// facedetection.cpp : 定义控制台应用程序的入口点。
#include<opencv/cv.h>
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/opencv.hpp>
#include <opencv2/opencv.hpp>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <assert.h>
#include <math.h>
#include <float.h>
#include <limits.h>
#include <time.h>
#include <ctype.h>
#include<vector>
#include<fstream>
#include<sstream>
#include<iostream>
#include "timer.h" using namespace std;
using namespace cv;
vector<string> testSamples;
cv::CascadeClassifier cascade;
const int detectSizeX = 320;//用来标明是将图缩放到在320*240
const int detectSizeY = 240;
const int detectRecXStart = 80;//检测窗口的起始大小
const int detectRecYStart = 80;
const int detectRecYEnd = 220;//检测窗口的终止大小
//const int detectRecYEnd = 220; //***************************************************************
// 名称: find_overlap
// 功能: 计算矩形框的overlap
// 权限: public
// 返回值: float
// 参数: Rect x
// 参数: Rect y
//***************************************************************
float find_overlap(Rect x,Rect y)//判断框出图像的重叠面积
{
float endx=max(x.x+x.width,y.x+y.width);
float startx=min(x.x,y.x);
float endy=max(x.y+x.height,y.y+y.height);
float starty=min(x.y,y.y);
float w=x.width+y.width-(endx-startx);
float h=x.height+y.height-(endy-starty);
if (w<=0||h<=0)
return 0;
else
{
float area=w*h;
return area/(x.width*x.height);
}
} //***************************************************************
// 名称: readFileList
// 功能: 待检测的图像列表
// 权限: public
// 返回值: void
// 参数: string testImgFile txt文件包含待检测图像
// 参数: string basePath 基地址,用来连接到txt中的相对位置构成绝对地址
//***************************************************************
//void readFileList(string testImgFile = "D:\\DataSet\\CarFaceTestDataSet\\CarFace_ImageList.txt", string basePath="")
void readFileList(string testImgFile, string basePath)
{
string buffer;
std::ifstream fIn(testImgFile.c_str());
while (fIn)
{
if (getline(fIn,buffer))
{
testSamples.push_back(basePath + buffer);
}
}
cout<<"Load FileList Successfully"<<endl;
} //***************************************************************
// 名称: loadCascadeModel
// 功能: 载入cascade模型文件
// 权限: public
// 返回值: void
// 参数: string xmlPath
//***************************************************************
void loadCascadeModel(string xmlPath)
{
cascade.load(xmlPath.c_str());
if (!cascade.empty())
{
cout<<"Load Cascade Model Successfully"<<endl;
}
} void detecctObject(string savePath)
{ TM_STATE timer;//用来计算检测的时间
TM_COUNTER start, end;
double duration, max_duration, total_duration, average_duration;
max_duration = total_duration = 0.;
ofstream fout; fout.open(savePath + "\\cascade_detect_result.txt");//存储框出图像的坐标文件名 int num=0; for (int i = 0; i < testSamples.size(); i++)
{
start_timer (&timer, &start);//启动计时器 IplImage * img = cvLoadImage(testSamples[i].c_str());
vector<cv::Rect> detectedRect;//存储检测到的图像
IplImage * copyImg = cvCreateImage(cvSize(detectSizeX,detectSizeY), 8, 3);//图像缩放到detectSizeX*detectSizeY,自己设置合适的数值,不能再原始图上检测,太慢,还会引入误差
cvResize(img, copyImg,1 );
IplImage * grayImage = cvCreateImage(cvGetSize(copyImg), 8, 1); cvCvtColor(copyImg, grayImage, CV_BGR2GRAY);//转换到灰度图检测 detectedRect.clear();
cascade.detectMultiScale(grayImage, detectedRect, 1.1, 3, CV_HAAR_SCALE_IMAGE | CV_HAAR_DO_CANNY_PRUNING, cvSize(detectRecXStart, detectRecXStart), cvSize(detectRecYEnd, detectRecYEnd));//检测函数 fout<<testSamples[i].c_str()<<" "<<detectedRect.size()<<" ";
cout<<testSamples[i].c_str()<<" "<<detectedRect.size()<<" ";
for (vector<cv::Rect>::iterator k= detectedRect.begin(); k != detectedRect.end(); k++)
{
Rect r = *k;
vector<cv::Rect>::iterator j= detectedRect.begin();
for (j= detectedRect.begin(); j != detectedRect.end(); j++)
{
if ( k != j && (r & *j) == r)//用来消除嵌套的,一个矩形在另一个矩形框中的情况
break;
if(find_overlap(*k, *j)>0.6 && k->height*k->width < j->height*j->width)//用来消除检测中两个宽重叠超过0.6的框,一般视为误检测
break;
}
if(j ==detectedRect.end())
{
//此处将框出的图像放大了0.03倍 使用画矩阵函数可以看到
//cvRectangle(img, cvPoint(k->x*img->width/detectSizeX-k->width*img->width/detectSizeX*0.03, k->y*img->width/detectSizeX-k->width*img->width/detectSizeX*0.03), cvPoint(k->x*img->width/detectSizeX + k->width*img->width/detectSizeX + k->width*img->width/detectSizeX*0.03, k->y*img->width/detectSizeX + k->height*img->width/detectSizeX +k->width*img->width/detectSizeX*0.03),Scalar(0, 255, 0));
//cvRectangle(img, cvPoint(k->x*img->width/detectSizeX, k->y*img->width/detectSizeX), cvPoint(k->x*img->width/detectSizeX + k->width*img->width/detectSizeX, k->y*img->width/detectSizeX + k->height*img->width/detectSizeX),Scalar(0, 255, 0)); fout << k->x*img->width/detectSizeX-k->width*img->width/detectSizeX*0.03 << " "<<k->y*img->height/detectSizeY-k->width*img->width/detectSizeX*0.03<<" "<<k->width*img->width/detectSizeX + k->width*img->width/detectSizeX*0.06<<" "<<k->height*img->height/detectSizeY + k->width*img->width/detectSizeX*0.06<<" ";
cout << k->x*img->width/detectSizeX-k->width*img->width/detectSizeX*0.03 << " "<<k->y*img->height/detectSizeY-k->width*img->width/detectSizeX*0.03<<" "<<k->width*img->width/detectSizeX + k->width*img->width/detectSizeX*0.06<<" "<<k->height*img->height/detectSizeY + k->width*img->width/detectSizeX*0.06<<" "; //用来截取车脸设定ROI
cvSetImageROI(img, cvRect(k->x*img->width/detectSizeX - k->width*img->width/detectSizeX*0.03,k->y*img->height/detectSizeY - k->width*img->width/detectSizeX*0.03,k->width*img->width/detectSizeX+ k->width*img->width/detectSizeX*0.06,k->width*img->width/detectSizeX+ k->width*img->width/detectSizeX*0.06));
//cvSetImageROI(img, cvRect(k->x*img->width/detectSizeX,k->y*img->height/detectSizeY,k->width*img->width/detectSizeX,k->width*img->width/detectSizeX));
string filePartName=testSamples[i].substr(testSamples[i].find_first_of("/\\") + 1 ,testSamples[i].find(".jpg") -testSamples[i].find_last_of("/\\") - 1); std::stringstream ss;
string numstr;
ss<<num;
ss>>numstr;
num++;
string name=savePath+filePartName+"_"+numstr+".jpg";//存储图像命名
cout<<name<<endl;
cvSaveImage(name.c_str(),img);
}
} fout <<endl;
cout<<endl;
stop_timer (&end);
duration = elapsed_time (&timer, &start, &end); if (duration > max_duration)
max_duration = duration; total_duration += duration;
cout<<"duration"<<duration<<" max_duration"<<max_duration<<" total_duration"<<total_duration<<endl;
////显示窗口
cvNamedWindow("output");
cvShowImage("output",copyImg);
cvShowImage("output",img);
waitKey(0); cvReleaseImage(&img);
cvReleaseImage(&grayImage);
cvReleaseImage(&copyImg);
}
fout.close();
}
void main ()
{
string testImgFile = "D:\\DataSet\\CarFaceTestDataSet\\CarFace_ImageList.txt";
string basePath="";
string xmlPath = "D:\\WorkSpace\\VS_Projects\\facedetection\\cascade.xml";
string savePath = "D:\\DataSet\\CarFaceTestDataSet\\result";
readFileList(testImgFile,basePath);
loadCascadeModel(xmlPath);
detecctObject(savePath); }

车脸检测 Adaboost 检测过程的更多相关文章

  1. 【图像处理】Haar Adaboost 检测自定义目标(视频车辆检测算法代码)

    阅读须知 本博客涉及到的资源: 正样本:http://download.csdn.net/detail/zhuangxiaobin/7326197 负样本:http://download.csdn.n ...

  2. OpenCV:OpenCV目标检测Adaboost+haar源代码分析

    使用OpenCV作图像检测, Adaboost+haar决策过程,其中一部分源代码如下: 函数调用堆栈的底层为: 1.使用有序决策桩进行预测 template<class FEval> i ...

  3. (77)zabbix主动、被动检测的详细过程与区别

    zabbix agent检测分为主动(agent active)和被动(agent)两种形式,主动与被动的说法均是相对于agent来讨论的.简单说明一下主动与被动的区别如下: 主动:agent请求se ...

  4. [DeeplearningAI笔记]卷积神经网络3.1-3.5目标定位/特征点检测/目标检测/滑动窗口的卷积神经网络实现/YOLO算法

    4.3目标检测 觉得有用的话,欢迎一起讨论相互学习~Follow Me 3.1目标定位 对象定位localization和目标检测detection 判断图像中的对象是不是汽车--Image clas ...

  5. 【python+opencv】直线检测+圆检测

     Python+OpenCV图像处理—— 直线检测 直线检测理论知识: 1.霍夫变换(Hough Transform) 霍夫变换是图像处理中从图像中识别几何形状的基本方法之一,应用很广泛,也有很多改进 ...

  6. 人脸检测----Adaboost学习方法

    有了haar特征,有了提升性能的积分图,是不是已经可以很好的解决人脸检测问题了?答案是:no. 因为,计算每一个特征值的时候速度都大幅提升了,但是,一个小小的24*24是人脸图像根据不同的位置, 以及 ...

  7. Faster R-CNN:详解目标检测的实现过程

    本文详细解释了 Faster R-CNN 的网络架构和工作流,一步步带领读者理解目标检测的工作原理,作者本人也提供了 Luminoth 实现,供大家参考.   Luminoth 实现:https:// ...

  8. 【3D】PoseCNN姿态检测网络复现过程记录

    最近在研究室内6D姿态检测相关问题,计划在PoseCNN网络基础上进行改进实现.但是在第一步的复现过程中踩了无数的坑,最终成功运行了demo,但目前数据集train还是遇到了一些问题.有问题欢迎一起交 ...

  9. 学习OpenCV——行人检测&人脸检测(总算运行出来了)

    之前运行haar特征的adaboost算法人脸检测一直出错,加上今天的HOG&SVM行人检测程序,一直报错. 今天总算发现自己犯了多么白痴的错误——是因为外部依赖项lib文件没有添加完整,想一 ...

随机推荐

  1. 股票价格涨跌预测—基于KNN分类器

    code{white-space: pre;} pre:not([class]) { background-color: white; }if (window.hljs && docu ...

  2. Android性能优化之一:ViewStub

    ViewStub是Android布局优化中一个很不错的标签/控件,直接继承自View.虽然Android开发人员基本上都听说过,但是真正用的可能不多. ViewStub可以理解成一个非常轻量级的Vie ...

  3. 欧拉计划之题目9:找出唯一的满足a + b + c = 1000的毕达哥拉斯三元组{a, b, c}

    本题来自:http://pe.spiritzhang.com/index.php/2011-05-11-09-44-54/10-9a--b--c--1000a-b-c #include <std ...

  4. 详解JavaScript函数模式

    JavaScript设计模式的作用是提高代码的重用性,可读性,使代码更容易的维护和扩展.在javascript中,函数是一类对象,这表示他可以作为参数传递给其他函数:此外,函数还可以提供作用域. 创建 ...

  5. ASP.NET MVC another entity of the same type already has the same primary key value

    ASP.NET MVC项目 Repository层中,Update.Delete总是失败 another entity of the same type already has the same pr ...

  6. 设置ArcGIS的外观改回到出厂

    在一般的软件中,都可以在工具-选项中打开相关设置将应用程序的外观改回到出厂.但ArcGIS好像没有,但查帮助文档原来是这样: 配置的更改保存在模板文档中(例如,ArcMap 将其更改保存在 Norma ...

  7. sharepoint 顺序工作流创建

    顺序工作流提供了一系列有组织的步骤,一般情况下,步骤是逐一执行的. 1.新建 > 项目,选择 SharePoint解决方案 > 空项目: 2.部署为场解决方案 3.添加 > 新项,选 ...

  8. 安卓开发_浅谈OptionsMenus(选项菜单)

    Android平台下所提供的菜单大体上可分为三类:选项菜单.上下文菜单和子菜单. 当Activity在前台运行时,如果用户按下手机上的Menu键,此时就会在屏幕低端弹出相应的选项菜单.但这个功能需要开 ...

  9. Fragments之间的交互(实现参数传递)

    Fragments之间的交互(实现参数传递) 日常开发中,通常Fragments之间可能需要交互,比如基于用户事件改变Fragment的内容.所有Fragment之间的交互需要通过他们关联的Activ ...

  10. 【原】训练自己的haar-like特征分类器并识别物体(3)

    在前两篇文章中,我介绍了<训练自己的haar-like特征分类器并识别物体>的前三个步骤: 1.准备训练样本图片,包括正例及反例样本 2.生成样本描述文件 3.训练样本 4.目标识别 == ...