目录
一、CascadeClassifier应用简介
1.1 objdetect模块
1.2 CascadeClassifier类
1.3 detectMultiScale函数详解
二、CascadeClassifier应用示例
2.1 模型及图片下载准备
2.2 程序代码
2.3 程序编译及运行
一、CascadeClassifier应用简介
1.1 objdetect模块
在OpenCV中,objdetect
模块提供了对象检测的功能,特别是基于预训练分类器的对象检测,如人脸检测、人体检测或其他特定目标的检测。
以下是objdetect
模块中常用的一些类和函数:
-
CascadeClassifier:
CascadeClassifier
类用于加载预训练的分类器,如Haar特征或LBP特征的级联分类器,通常用于人脸检测。加载分类器后,可以使用detectMultiScale
函数在图像中检测对象。 -
HOGDescriptor:
HOGDescriptor
类用于计算图像的Histogram of Oriented Gradients(HOG)描述符,通常与SVM分类器结合使用,进行行人检测等任务。 -
DNN(深度神经网络):
虽然DNN不是objdetect
模块的直接部分,但OpenCV提供了dnn
模块,该模块可以用于加载和运行深度学习模型进行对象检测。例如,你可以使用YOLO、SSD或Faster R-CNN等模型进行对象检测。 -
其他检测器:
除了上述的Haar和HOG检测器外,objdetect
模块还包含其他类型的对象检测器,如基于LSD(Line Segment Detector)的线检测器和基于轮廓的方法。但是,这些功能可能不像Haar和HOG那样直接在该模块中提供,而是需要一些额外的处理和编程。
1.2 CascadeClassifier类
CascadeClassifier
类用于对象检测,特别是基于Haar或LBP特征的级联分类器的对象检测,这种检测方法通常用于人脸检测,但也可以用于其他目标,如眼睛、鼻子等。
以下是使用 CascadeClassifier
类进行人脸检测的基本步骤:
- 加载级联分类器:首先,你需要加载一个预训练的级联分类器文件(通常是一个
.xml
文件)。这个文件包含了用于对象检测的级联函数和特征。对于人脸检测,OpenCV提供了一些预训练的模型,如haarcascade_frontalface_default.xml
。 - 读取图像:使用
imread
函数读取要检测的图像。 - 预处理图像(可选):对于某些级联分类器,将图像转换为灰度可能是必要的,因为级联分类器通常是在灰度图像上训练的。使用
cvtColor
函数进行转换。 - 检测对象:使用
CascadeClassifier
类的detectMultiScale
函数在图像中检测对象。这个函数会返回一组矩形区域,表示检测到的对象的位置和大小。 - 绘制检测结果:使用
rectangle
函数在原始图像上绘制检测到的对象的边界框。 - 显示或保存结果:使用
imshow
函数显示结果图像,或使用imwrite
函数将结果保存到文件。
1.3 detectMultiScale函数详解
CascadeClassifier
类的 detectMultiScale
函数是用于在图像中检测多个对象(如人脸)的。这个函数基于Haar或LBP特征的级联分类器来工作,并返回一系列矩形(cv::Rect
),这些矩形表示在图像中检测到的对象的位置。
void CascadeClassifier::detectMultiScale( InputArray image, std::vector<Rect>& objects, double scaleFactor = 1.1, int minNeighbors = 3, int flags = 0, Size minSize = Size(), Size maxSize = Size()
);
参数说明:
- image:待检测的输入图像。它应该是灰度图像(
CV_8UC1
),除非你已经对彩色图像训练了特定的分类器。 - objects:一个向量,用于存储检测到的对象的矩形边界框。每个矩形由其左上角坐标
(x, y)
和宽高(width, height)
定义。 - scaleFactor:比例因子,用于表示在每次图像缩放时的大小变化率。较小的值会产生更精确的结果,但也会增加计算时间。默认为1.1。
- minNeighbors:构成检测到的对象的相邻矩形的最小数量。如果数量太少,可能会丢弃该检测。这个参数可以减少误检(假阳性)。默认为3。
- flags:修改检测方式的标志。它可以是以下值的组合:
CASCADE_SCALE_IMAGE
:在检测过程中按比例缩放图像。如果未设置此标志,则会按比例缩放分类器检测窗口。默认为设置此标志。CASCADE_FIND_BIGGEST_OBJECT
:只返回最大的对象检测。CASCADE_DO_ROUGH_SEARCH
:做初步检测,接受被其他级联拒绝的候选对象。这可能会增加误检,但可能会找到一些遗漏的对象。
- minSize:检测窗口的最小可能大小。小于此尺寸的窗口将被忽略。默认为空,表示没有限制。
- maxSize:检测窗口的最大可能大小。大于此尺寸的窗口将被忽略。默认为空,表示没有限制。
返回值
此函数没有返回值。检测到的对象边界框存储在传入的 objects
向量中。
二、CascadeClassifier应用示例
2.1 模型及图片下载准备
需要用到预先训练好的模型“haarcascade_frontalface_default.xml”,前往gitee网站下载haarcascade_frontalface_default.xml · Miwat/face_recognition_LBPH - Gitee.com
前往网上,下载人物图片用于人脸识别验证。
2.2 程序代码
main.cpp实现
#include <opencv2/opencv.hpp>
#include <opencv2/objdetect/objdetect.hpp> int main(int argc, char** argv)
{ // 加载预训练的人脸分类器 cv::CascadeClassifier face_cascade; if (!face_cascade.load("haarcascade_frontalface_default.xml")) { std::cerr << "--(!)Error loading face cascade\n"; return -1; } // 读取图像 cv::Mat image = cv::imread(argv[1], cv::IMREAD_COLOR); if (image.empty()) { std::cerr << "--(!)Error loading image\n"; return -1; } // 转换为灰度图像(大多数级联分类器在灰度图像上工作得更好) cv::Mat gray; cv::cvtColor(image, gray, cv::COLOR_BGR2GRAY); //获取训练集的原始尺寸,作为分类器的最小尺寸,这样能得到最佳的检测效果(不是必须的)// cv::Size original_size = face_cascade.getOriginalWindowSize();// std::cerr << "original_size = " << original_size << "\n";// 检测人脸 std::vector<cv::Rect> faces; face_cascade.detectMultiScale(gray, faces, 1.1, 2, 0 | cv::CASCADE_SCALE_IMAGE, cv::Size(24, 16)/*original_size*//*cv::Size(30, 30)*/); std::cerr << "faces.size() = " << faces.size() << "\n";// 在图像上绘制检测到的人脸 for (size_t i = 0; i < faces.size(); i++) { cv::rectangle(image, faces[i], cv::Scalar(255, 0, 0), 2); } // 显示结果 cv::imshow("Faces", image); cv::waitKey(0); return 0;
}
2.3 程序编译及运行
本文是采用win系统下,opencv采用MinGW编译的静态库(C/C++开发,win下OpenCV+MinGW编译环境搭建_opencv mingw-CSDN博客),建立makefile:
#/bin/sh
#win32
CX= g++ -DWIN32
#linux
#CX= g++ -Dlinux BIN := ./
TARGET := opencv_objdetect01.exe
FLAGS := -std=c++11 -static
SRCDIR := ./
#INCLUDES
INCLUDEDIR := -I"../../opencv_MinGW/include" -I"./"
#-I"$(SRCDIR)"
staticDir := ../../opencv_MinGW/x64/mingw/staticlib/
#LIBDIR := $(staticDir)/libopencv_world460.a\
# $(staticDir)/libade.a \
# $(staticDir)/libIlmImf.a \
# $(staticDir)/libquirc.a \
# $(staticDir)/libzlib.a \
# $(wildcard $(staticDir)/liblib*.a) \
# -lgdi32 -lComDlg32 -lOleAut32 -lOle32 -luuid
#opencv_world放弃前,然后是opencv依赖的第三方库,后面的库是MinGW编译工具的库LIBDIR := -L $(staticDir) -lopencv_world460 -lade -lIlmImf -lquirc -lzlib \-llibjpeg-turbo -llibopenjp2 -llibpng -llibprotobuf -llibtiff -llibwebp \-lgdi32 -lComDlg32 -lOleAut32 -lOle32 -luuid
source := $(wildcard $(SRCDIR)/*.cpp) $(TARGET) :$(CX) $(FLAGS) $(INCLUDEDIR) $(source) -o $(BIN)/$(TARGET) $(LIBDIR)clean:rm $(BIN)/$(TARGET)
编译如下:
程序运行输出如下:
大家可以调节各个参数来观察其效果。