opencv 29.Haar特征

博客主要介绍了基于Haar特征的Adaboost人脸检测级联分类。阐述了Haar特征是分类器输入,通过将矩形放于人脸或非人脸区域计算特征值来区分两者。为加快像素和计算引入积分图,还给出几种不常规区域积分图计算及haar特征计算公式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一般用法为:
基于Haar特征Adaboost人脸检测级联分类,称haar分类器。

目前只介绍下Haar特征和积分图,其他的还未深入。

1.Haar特征

  什么是特征,特征就是分类器的输入。

  把它放在以下的情景中来描写叙述,如果在人脸检測时我们须要有这么一个子窗体在待检測的图片窗体中不断的移位滑动,子窗体每到一个位置,就会计算出该区域的特征,然后用我们训练好的级联分类器对该特征进行筛选,一旦该特征通过了全部强分类器的筛选。则判定该区域为人脸。

  那么这个特征怎样表示呢?好了。这就是大牛们干的好事了。后人称这他们搞出来的这些东西叫Haar-Like特征。

基础的haar特征例如以下:
在这里插入图片描述
改进的Haar特征:
在这里插入图片描述
这些所谓的特征不就是一堆堆带条纹的矩形么,究竟是干什么用的?将上面的随意一个矩形放到人脸区域上,然后。将白色区域的像素和减去黑色区域的像素和。得到的值我们暂且称之为人脸特征值。假设你把这个矩形放到一个非人脸区域。那么计算出的特征值应该和人脸特征值是不一样的,并且越不一样越好,所以这些方块的目的就是把人脸特征量化,以区分人脸和非人脸。

由于要计算像素和,为了加快计算便引入了积分图的方式。

2.积分图

积分图的具体意思在SIFT和SURF里讲过了,下面说下几种不常规的区域积分图计算

在这里插入图片描述
对于a、c图所看到的的haar特征。计算公式例如以下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
当中,SAT即为积分图中的值,RecSum即为(x,y)处的长宽为(w,h)的区域的和。

有了RecSum后,就能够计算haar特征了。

相似的,b,d图所看到的的haar特征计算公式例如以下:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

参考博客:
http://www.cnblogs.com/bhlsheji/p/4726376.html
https://blog.youkuaiyun.com/xizero00/article/details/46929261
https://blog.youkuaiyun.com/zachary_co/article/details/78811605

<think>我们被要求使用OpenCV在Android应用中加载一个存储在raw资源目录下的Haar级联分类器文件(haarcascade_frontalface_default.xml)。 步骤: 1. 将XML文件放在res/raw目录下(如果没有raw目录,则创建它)。 2. 在代码中,我们需要获取这个资源的输入流,然后使用OpenCV的CascadeClassifier加载它。 但是注意:OpenCV的CascadeClassifier通常需要文件路径。然而,当我们把文件放在raw目录中时,我们无法直接获取文件路径(因为资源是压缩的)。因此,我们需要先将文件复制到应用的内部存储或外部存储,然后从那里加载。 具体步骤: a) 将XML文件从res/raw复制到内部存储的某个目录(例如files目录)。 b) 使用复制后的文件路径来初始化CascadeClassifier。 注意:为了避免每次启动应用都复制,我们可以检查文件是否已经存在。 另外,我们也可以将文件放在assets目录下,然后以类似的方式处理。 但是,根据引用[1]中的描述,他们是将xml文件拷贝到raw目录中。所以我们这里按照raw目录来处理。 实现代码示例: 1. 在res目录下创建raw目录,并将haarcascade_frontalface_default.xml文件放入其中。 2. 在代码中: 首先,我们需要一个方法将raw资源复制到内部存储: ```java private void copyRawResourceToFile(int resourceId, String outputFileName) { InputStream inputStream = getResources().openRawResource(resourceId); OutputStream outputStream = null; try { outputStream = new FileOutputStream(outputFileName); byte[] buffer = new byte[1024]; int length; while ((length = inputStream.read(buffer)) > 0) { outputStream.write(buffer, 0, length); } outputStream.flush(); } catch (IOException e) { e.printStackTrace(); } finally { try { if (outputStream != null) outputStream.close(); if (inputStream != null) inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } ``` 然后,在初始化OpenCV后,我们进行复制和加载: ```java // 假设我们的资源文件名为:haarcascade_frontalface_default.xml,在raw目录下,资源ID为R.raw.haarcascade_frontalface_default String cascadeDir = getDir("cascade", Context.MODE_PRIVATE).getAbsolutePath(); String cascadeFilePath = cascadeDir + "/haarcascade_frontalface_default.xml"; // 如果文件不存在,则复制 File cascadeFile = new File(cascadeFilePath); if (!cascadeFile.exists()) { copyRawResourceToFile(R.raw.haarcascade_frontalface_default, cascadeFilePath); } // 加载级联分类器 CascadeClassifier faceDetector = new CascadeClassifier(); if (faceDetector.load(cascadeFilePath)) { // 加载成功 } else { // 加载失败 Log.e(TAG, "Failed to load cascade classifier"); faceDetector = null; } ``` 注意:getDir("cascade", Context.MODE_PRIVATE)会在应用的内部存储中创建一个名为"cascade"的目录(如果不存在),并返回该目录的绝对路径。 3. 使用faceDetector进行人脸检测。 另外,我们也可以将文件放在assets目录下,然后使用AssetManager来复制。但这里用户要求使用R.raw,所以我们使用raw目录。 重要:在复制完成后,我们可以使用这个cascadeFilePath来初始化CascadeClassifier。 但是,请注意,每次应用更新时,如果资源文件有变化,我们可能需要重新复制。或者我们可以检查文件的版本等。不过通常我们只需要在第一次运行或者文件不存在时复制。 另外,由于内部存储空间是应用私有的,所以不用担心文件被其他应用修改。 以上就是在Android中使用OpenCV加载raw资源目录下的级联分类器的方法。 相关问题: 1. 如何提高OpenCV在Android上的人脸检测速度? 2. 除了Haar级联分类器,OpenCV还支持哪些人脸检测方法? 3. 在Android上使用OpenCV进行人脸检测时,如何处理相机的实时视频流?</think>### Android OpenCV 加载 R.raw.haarcascade_frontalface_default 方法 在 Android 中使用 OpenCV 加载 `R.raw.haarcascade_frontalface_default` 资源进行人脸检测,需按以下步骤操作: #### 1. **准备资源文件** - 将 `haarcascade_frontalface_default.xml` 放入 `res/raw/` 目录(若目录不存在需手动创建) - 确保资源 ID 正确:`R.raw.haarcascade_frontalface_default` #### 2. **关键代码实现** ```java import org.opencv.android.Utils; import org.opencv.core.Mat; import org.opencv.core.MatOfRect; import org.opencv.core.Rect; import org.opencv.core.Scalar; import org.opencv.imgproc.Imgproc; import org.opencv.objdetect.CascadeClassifier; // 步骤1:将资源文件复制到应用内部存储 private CascadeClassifier initFaceDetector(Context context) { try { // 创建内部存储路径 File cascadeDir = context.getDir("cascade", Context.MODE_PRIVATE); File cascadeFile = new File(cascadeDir, "haarcascade_frontalface_default.xml"); // 复制资源文件(首次运行或更新时) if (!cascadeFile.exists() || isResourceUpdated(context)) { InputStream is = context.getResources().openRawResource(R.raw.haarcascade_frontalface_default); FileOutputStream os = new FileOutputStream(cascadeFile); byte[] buffer = new byte[4096]; int bytesRead; while ((bytesRead = is.read(buffer)) != -1) { os.write(buffer, 0, bytesRead); } is.close(); os.close(); } // 步骤2:加载级联分类器 CascadeClassifier faceDetector = new CascadeClassifier(); if (faceDetector.load(cascadeFile.getAbsolutePath())) { return faceDetector; } } catch (IOException e) { Log.e("OpenCV", "Error loading cascade: " + e.getMessage()); } return null; } // 步骤3:执行人脸检测 private void detectFaces(Mat rgbaMat, CascadeClassifier faceDetector) { Mat grayMat = new Mat(); Imgproc.cvtColor(rgbaMat, grayMat, Imgproc.COLOR_RGBA2GRAY); // 转为灰度图 MatOfRect faceDetections = new MatOfRect(); faceDetector.detectMultiScale( grayMat, // 输入图像 faceDetections, // 检测结果 1.1, // 缩放因子 3, // 最小邻居数 0, // 标志(保留默认) new Size(30, 30), // 最小人脸尺寸 new Size() // 最大人脸尺寸(空表示无限制) ); // 绘制检测框 for (Rect rect : faceDetections.toArray()) { Imgproc.rectangle(rgbaMat, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y + rect.height), new Scalar(0, 255, 0), // 绿色框 2 ); } grayMat.release(); } ``` #### 3. **使用示例** ```java // 在CameraView的回调中调用 @Override public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) { Mat rgba = inputFrame.rgba(); if (faceDetector != null) { detectFaces(rgba, faceDetector); } return rgba; } ``` #### 4. **注意事项** 1. **文件复制必要性** OpenCV 的 `CascadeClassifier.load()` 需要文件系统路径,无法直接加载 `raw` 资源流,因此需先复制到内部存储[^1]。 2. **性能优化建议** - 灰度转换:检测前先转为单通道灰度图提升速度 - 尺寸限制:通过 `Size()` 参数限制最小/最大检测人脸尺寸 - 异步处理:在非UI线程执行检测避免卡顿 3. **资源更新处理** 实现 `isResourceUpdated()` 方法,通过版本号或MD5校验确保资源更新后重新复制。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值