opencv CascadeClassifier
demo: http://download.csdn.net/detail/keen_zuxwang/9848478
OpenCV中CascadeClassifier类实现多尺度检测源码解析
http://blog.csdn.net/xidianzhimeng/article/details/41851569
它使用Adaboost的方法+LBP、HOG、HAAR进行目标检测
opencv CvHaarClassifierCascade() (针对具体的HAAR特征的级联分类器)
//Objdetect.hpp
typedef struct CvHaarClassifierCascade
{
int flags;
int count;
CvSize orig_window_size;
CvSize real_window_size;
double scale;
CvHaarStageClassifier* stage_classifier;
CvHidHaarClassifierCascade* hid_cascade;
} CvHaarClassifierCascade;
#define CV_HAAR_DO_CANNY_PRUNING 1
#define CV_HAAR_SCALE_IMAGE 2
#define CV_HAAR_FIND_BIGGEST_OBJECT 4
#define CV_HAAR_DO_ROUGH_SEARCH 8
/* sets images for haar classifier cascade */
CVAPI(void) cvSetImagesForHaarClassifierCascade( CvHaarClassifierCascade* cascade,
const CvArr* sum, const CvArr* sqsum,
const CvArr* tilted_sum, double scale );
/* runs the cascade on the specified window */
CVAPI(int) cvRunHaarClassifierCascade( const CvHaarClassifierCascade* cascade,
CvPoint pt, int start_stage CV_DEFAULT(0));
CVAPI(CvSeq*) cvHaarDetectObjects( const CvArr* image,
CvHaarClassifierCascade* cascade, CvMemStorage* storage,
double scale_factor CV_DEFAULT(1.1),
int min_neighbors CV_DEFAULT(3), int flags CV_DEFAULT(0),
CvSize min_size CV_DEFAULT(cvSize(0,0)), CvSize max_size CV_DEFAULT(cvSize(0,0)));
image
输入图像
cascade
harr 分类器对象
storage
存储检测到的一序列候选目标矩形框的内存区域。
scale_factor
在前后两次相继的扫描中,搜索窗口的比例系数。如1.1指将搜索窗口依次扩大10%。
min_neighbors
构成检测目标的相邻矩形的最小个数(缺省-1)。如组成检测目标的小矩形的个数和小于min_neighbors-1 都会被排除。如min_neighbors为0,则函数不做任何操作就返回所有的被检候选矩形框
flags
操作方式,如flags设为CV_HAAR_DO_CANNY_PRUNING, 则函数利用Canny边缘检测器来排除一些边缘很少或者很多的图像区域,可提高了检测速度。
min_size
检测窗口的最小尺寸。默认设为分类器训练时采用的样本尺寸(人脸检测中缺省大小是~20×20)
max_size
检测窗口的最大尺寸。默认设为分类器训练时采用的样本尺寸
cvHaarDetectObjects
使用针对某目标物体训练的级联分类器在图像中找到包含目标物体的矩形区域,并且将这些区域作为一序列的矩形框返回。函数以不同比例大小的扫描窗口对图像进行几次搜索(调用cvSetImagesForHaarClassifierCascade函数),并每次都要对图像中的这些重叠区域利用cvRunHaarClassifierCascade进行检测
opencv CascadeClassifier级联分类器(针对具体的LBP + HAAR特征的级联分类器)
//级联分类器构造函数,filename XML分类器文件路径
CV_WRAP CascadeClassifier( const string& filename );
CV_WRAP bool load( const string& filename ); // 功能同上门带参的构造函数相同,加载XML分类器文件
// 多尺度检测函数
CV_WRAP virtual void detectMultiScale( const Mat& image,
CV_OUT vector<Rect>& objects,
double scaleFactor=1.1,
int minNeighbors=3, int flags=0,
Size minSize=Size(),
Size maxSize=Size() );
image
输入图像,须为8位灰度图像
objects
输出矩形,注意vector不是线程安全的
scaleFactor
缩放比例,必须大于1
minNeighbors
合并窗口时最小neighbor,每个候选矩阵至少包含的附近元素个数
flags
检测标记,只对旧格式的分类器有效,与cvHaarDetectObjects的参数flags相同,默认为0,可能的取值为
CV_HAAR_DO_CANNY_PRUNING(CANNY边缘检测)、
CV_HAAR_SCALE_IMAGE(缩放图像)、
CV_HAAR_FIND_BIGGEST_OBJECT(寻找最大的目标)、
CV_HAAR_DO_ROUGH_SEARCH(做粗略搜索);
如果寻找最大的目标就不能缩放图像,也不能CANNY边缘检测
minSize
最小检测目标
maxSize
最大检测目标
//最好不要在这里设置最大最小,可能会影响合并的效果,因此可以在检测完毕后自行判断结果是否满足要求
CV_WRAP virtual void detectMultiScale( const Mat& image,
CV_OUT vector<Rect>& objects,
vector<int>& rejectLevels,
vector<double>& levelWeights,
double scaleFactor=1.1,
int minNeighbors=3, int flags=0,
Size minSize=Size(),
Size maxSize=Size(),
bool outputRejectLevels=false );
// 上述参数多了rejectLevels和levelWeights以及outputRejectLevels参数,只有在outputRejectLevels为true的时候才可能输出前两个参数,还有就是在使用旧分类器的时候必须设置flags为CV_HAAR_SCALE_IMAGE,可以通过haarcascade_frontalface_alt.xml检测人脸尝试
java端实现,低层调用的是CascadeClassifier()类实现
FdActivity2.java:
public class FdActivity2 extends Activity implements CvCameraViewListener2 {
...
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
@Override
public void onManagerConnected(int status) {
switch (status) {
case LoaderCallbackInterface.SUCCESS:
{
Log.i(TAG, "OpenCV loaded successfully");
// load cascade file from application resources
/*
InputStream is = getResources().openRawResource(R.raw.lbpcascade_frontalface);
File cascadeDir = getDir("cascade", Context.MODE_PRIVATE);
mCascadeFile = new File(cascadeDir, "lbpcascade_frontalface.xml");
FileOutputStream os = new FileOutputStream(mCascadeFile);
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = is.read(buffer)) != -1) {
os.write(buffer, 0, bytesRead);
}
is.close();
os.close();
*/
//lbpcascade_frontalface.xml
//lbpcascade_profileface.xml
//haarcascade_fullbody.xml
//haarcascade_mcs_nose.xml
final String xmlPath = Environment.getExternalStorageDirectory() + "/haarcascade_mcs_nose.xml"; //XML分离器文件
Log.i(TAG, "xmlPath " + xmlPath);
//1\ 带参创建级联分类器
mJavaDetector = new CascadeClassifier(xmlPath);//mCascadeFile.getAbsolutePath()
if (mJavaDetector.empty()) {
Log.e(TAG, "Failed to load cascade classifier");
mJavaDetector = null;
} else
Log.i(TAG, "Loaded cascade classifier from " + xmlPath);//mCascadeFile.getAbsolutePath());
mOpenCvCameraView.enableView();
} break;
default:
{
super.onManagerConnected(status);
} break;
}
}
};
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
mRgba = inputFrame.rgba();
mGray = inputFrame.gray();
if (mAbsoluteFaceSize == 0) {
int height = mGray.rows();
if (Math.round(height * mRelativeFaceSize) > 0) {
mAbsoluteFaceSize = Math.round(height * mRelativeFaceSize);
}
}
MatOfRect faces = new MatOfRect();
if (mDetectorType == JAVA_DETECTOR) {
if (mJavaDetector != null)
//2\ 多尺度检测函数检测符合XML分类器检测特征的
mJavaDetector.detectMultiScale(mGray, //待检测灰度图像
faces,
//被检测物体的矩形框向量
1.1,
//前后两次相继扫描中搜索窗口的比例系数,默认为1.1 即每次搜索窗口扩大10%
2,
//构成检测目标的相邻矩形的最小个数 如果组成检测目标的小矩形的个数和小于minneighbors - 1 都会被排除
//如果minneighbors为0 则函数不做任何操作就返回所有被检候选矩形框
2,
// TODO: objdetect.CV_HAAR_SCALE_IMAGE
//(haar分类器是旧版的,CV_HAAR_DO_CANNY_PRUNING利用Canny边缘检测器来排除一些边缘很少或者很多的图像区域,
//CV_HAAR_SCALE_IMAGE就是按比例正常检测,CV_HAAR_FIND_BIGGEST_OBJECT只检测最大的物体,
//CV_HAAR_DO_ROUGH_SEARCH只做初略检测)
new Size(mAbsoluteFaceSize, mAbsoluteFaceSize),
//限制得到的目标区域的最小范围
new Size()
//限制得到的目标区域的最大范围
);
}
else {
Log.e(TAG, "Detection method is not selected!");
}
Rect[] facesArray = faces.toArray();
for (int i = 0; i < facesArray.length; i++)
Core.rectangle(mRgba, facesArray[i].tl(), facesArray[i].br(), FACE_RECT_COLOR, 3);
return mRgba;
}
...
}
lbpcascade_frontalface.xml
haarcascade_fullbody.xml