分类器: 判别某个事物是否属于某种分类的器件,两种结果:是、否
级联分类器: 可以理解为将N个单类的分类器串联起来。如果一个事物能属于这一系列串联起来的的所有分类器,则最终结果就是 是,若有一项不符,则判定为否
比如人脸,它有很多属性,我们将每个属性做一成个分类器,如果一个模型符合了我们定义的人脸的所有属性,则我们人为这个模型就是一个人脸。那么这些属性是指什么呢? 比如人脸需要有两条眉毛,两只眼睛,一个鼻子,一张嘴,一个大概U形状的下巴或者是轮廓等等
class CV_EXPORTS_W CascadeClassifier
{
public:
CV_WRAP CascadeClassifier();
//从文件中加载级联分类器
CV_WRAP CascadeClassifier(const String& filename);
~CascadeClassifier();
//检测级联分类器是否被加载
CV_WRAP bool empty() const;
//从文件中加载级联分类器
CV_WRAP bool load( const String& filename );
//从FileStorage节点读取分类器
CV_WRAP bool read( const FileNode& node );
/** 检测输入图像中不同大小的对象。检测到的对象以矩形列表的形式返回。
参数:
image: 包含检测对象的图像的CV_8U类型矩阵
objects: 矩形的向量,其中每个矩形包含被检测的对象,矩形可以部分位于原始图像之外
scaleFactor: 指定在每个图像缩放时的缩放比例
minNeighbors:指定每个候选矩形需要保留多少个相邻矩形
flags:含义与函数cvHaarDetectObjects中的旧级联相同。它不用于新的级联
minSize:对象最小大小,小于该值的对象被忽略。
maxSize:最大可能的对象大小,大于这个值的对象被忽略
该函数与TBB库并行
*/
CV_WRAP void detectMultiScale( InputArray image,
CV_OUT std::vector& objects,
double scaleFactor = 1.1,
int minNeighbors = 3, int flags = 0,
Size minSize = Size(),
Size maxSize = Size() );
/**
detectMultiScale重载函数
参数:
image:包含检测对象的图像的CV_8U类型矩阵
objects: 矩形的向量,其中每个矩形包含被检测的对象,矩形可以部分位于原始图像之外
numDetections: 对应对象的检测编号向量。一个物体被探测到的次数是相邻的被积极分类的矩形的数量,这些矩形被连接在一起形成物体
scaleFactor: 指定在每个图像缩放时的缩放比例
minNeighbors:指定每个候选矩形需要保留多少个相邻矩形
flags:含义与函数cvHaarDetectObjects中的旧级联相同。它不用于新的级联
minSize:对象最小大小,小于该值的对象被忽略。
maxSize:最大可能的对象大小,大于这个值的对象被忽略
*/
CV_WRAP_AS(detectMultiScale2) void detectMultiScale( InputArray image,
CV_OUT std::vector& objects,
CV_OUT std::vector& numDetections,
double scaleFactor=1.1,
int minNeighbors=3, int flags=0,
Size minSize=Size(),
Size maxSize=Size() );
/**
detectMultiScale重载函数,此函数允许您检索分类的最终阶段决策确定性
为此,需要将' outputRejectLevels '设置为true,并提供' rejectLevels '和' levelWeights '参数。
对于每一个结果检测,‘levelWeights’将在最后阶段包含分类的确定性。
这个值可以用来区分强分类和弱分类。
具体使用示例代码
Mat img;
vector weights;
vector levels;
vector detections;
CascadeClassifier model("/path/to/your/model.xml");
model.detectMultiScale(img, detections, levels, weights, 1.1, 3, 0, Size(), Size(), true);
cerr << "Detection " << detections[0] << " with weight " << weights[0] << endl;
*/
CV_WRAP_AS(detectMultiScale3) void detectMultiScale( InputArray image,
CV_OUT std::vector& objects,
CV_OUT std::vector& rejectLevels,
CV_OUT std::vector& levelWeights,
double scaleFactor = 1.1,
int minNeighbors = 3, int flags = 0,
Size minSize = Size(),
Size maxSize = Size(),
bool outputRejectLevels = false );
CV_WRAP bool isOldFormatCascade() const;
CV_WRAP Size getOriginalWindowSize() const;
CV_WRAP int getFeatureType() const;
void* getOldCascade();
CV_WRAP static bool convert(const String& oldcascade, const String& newcascade);
void setMaskGenerator(const Ptr& maskGenerator);
Ptr getMaskGenerator();
Ptr cc;
};
#include
#include
#include
#include
#include
int main()
{
//1.加载分类器
CascadeClassifier cascade;
//如果要识别人体的其它部位,只需将上面的haarcascade_frontalface_alt2.xml分类器替换即可。
cascade.load("E:\\Windowstest\\OPENCV\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_alt.xml");
Mat srcImg, dstImg, grayImg;
//定义7种颜色,用于标记人脸
Scalar colors[] =
{
// 红橙黄绿青蓝紫
CV_RGB(255,0,0),
CV_RGB(255, 97, 0),
CV_RGB(255, 255, 0),
CV_RGB(0, 255, 0),
CV_RGB(255, 97, 0),
CV_RGB(0, 0, 255),
CV_RGB(160, 32, 240),
};
//打开摄像头
cv::VideoCapture cap(0);
if (!cap.isOpened())
{
printf("open video failed!\n");
return 1;
}
int frameNum = 1000;
cv::namedWindow("识别结果", CV_WINDOW_NORMAL);
while (frameNum > 0) {
if (cv::waitKey(100) == 'q')break;
//将视频图片传给Mat
cap >> srcImg;
//尺寸调整
int scale = 1.0;
resize(srcImg, srcImg, Size(srcImg.cols / scale, srcImg.rows / scale), 0, 0, INTER_LINEAR); //用线性插值
dstImg = srcImg.clone();
grayImg.create(srcImg.size(), srcImg.type());
cvtColor(srcImg, grayImg, CV_BGR2GRAY);//生成灰度图,提高检测效率
// 3.检测
vector rect;
cascade.detectMultiScale(grayImg, rect, 1.1, 3, 0);//分类器对象调用
printf("检测到人脸个数:%d\n", rect.size());
//标记--脸部画矩形
for (int i = 0; i < rect.size(); i++) {
rectangle(dstImg, Point(rect[i].x, rect[i].y), Point(rect[i].x + rect[i].width, rect[i].y + rect[i].height), colors[i % 7], 2, 8, 0);
}
//5.显示
imshow("识别结果", dstImg);
frameNum--;
}
waitKey(0);
}
参考地址