赞
踩
传统的目标检测方法是指基于手工设计的特征提取器和机器学习算法,这些方法使用人工定义的特征,如Haar特征、HOG特征等,结合分类器(如支持向量机、AdaBoost等)来检测和分类目标。
Haar特征是一种基于像素的特征描述符,最初由Viola和Jones在2001年提出,用于人脸检测。这种特征能够有效地描述图像中的局部区域,因此也可以用于检测其他类型的目标。Haar特征通常用于基于级联的目标检测方法,例如Viola-Jones目标检测器。这种方法通过使用AdaBoost算法选择和组合具有最佳分类性能的Haar特征,构建一个级联分类器,用于检测目标对象。
Haar特征的优点如下所示。
然而,Haar特征也存在一些局限性,具体说明如下所示。
因此,虽然Haar特征在一些场景下仍然被使用,但是在许多情况下,基于深度学习的目标检测方法如Faster R-CNN、YOLO和SSD等已经取得了更好的性能。
例如下面是一个使用Python和OpenCV库实现目标检测的例子,该例子使用Haar级联分类器来检测人脸。
实例2-1:用Haar级联分类器来检测人脸(源码路径:codes\2\Haar\)
实例文件face.py的具体实现代码如下所示。
- import cv2
-
- # 加载Haar级联分类器
- face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
-
- # 加载图像
- image = cv2.imread('111.jpg')
-
- # 将图像转换为灰度图像
- gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
-
- # 使用Haar级联分类器进行人脸检测
- faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30))
-
- # 在检测到的人脸周围绘制矩形框
- for (x, y, w, h) in faces:
- cv2.rectangle(image, (x, y), (x+w, y+h), (255, 0, 0), 2)
-
- # 显示结果图像
- cv2.imshow('Detected Faces', image)
- cv2.waitKey(0)
- cv2.destroyAllWindows()
在这个例子中,首先加载了Haar级联分类器,然后加载了要进行目标检测的图像。接着,将图像转换为灰度图像,因为Haar级联分类器需要输入灰度图像。然后,我们使用detectMultiScale函数来检测图像中的人脸,该函数返回检测到的人脸的边界框。最后,我们在检测到的人脸周围绘制了矩形框,并显示了结果图像,如图2-1所示。
图2-1 检测结果
目标检测是一个监督学习问题,可以使用各种机器学习技术来解决。传统的机器学习方法包括使用特征提取和分类器来检测目标,而深度学习方法则通过端到端的训练来学习特征表示和目标检测。在传统机器学习方法中,可以使用各种特征提取方法,例如Haar特征、HOG(方向梯度直方图)特征等,并结合分类器如支持向量机(SVM)、随机森林、决策树等来进行目标检测。这些方法通常需要手工设计特征和选择合适的分类器,对于复杂的目标和场景可能需要大量的特征工程。
为了提高开发效率,可以使用dlib提供的机器学习工具训练自己的模型,提高目标检测效率。请看下面的实例文件train_shape_predictor.py,功能是训练一个基于小数据集的人脸标记模型,然后对其进行评估。本实例使用了dlib论文是中的算法《One Millisecond Face Alignment with an Ensemble of Regression Trees,Vahid Kazemi和Josephine Sullivan,CVPR 2014》。如果要在某些图像上可视化训练模型的输出,则可以运行实例文件train_shape_predictor.py,并将文件predictor.dat作为输入模型。大家需要注意的是,此类模型虽然经常用于人脸标记领域,但是却非常通用,也可以用于各种形状的预测任务。但是在本实例,我们仅使用一个简单的面部标记任务应用来演示训练自己的模型的知识。实例文件train_shape_predictor.py的具体实现流程如下所示。
实例2-2:训练一个目标检测模型并评估(源码路径:codes\2\train_shape_predictor.py)
(1)在本实例中将基于“examples/faces”目录中的small faces数据集训练一个人脸检测器,需要提供此“faces”文件夹的路径作为命令行参数,以便让程序知道它在哪里。
- if len(sys.argv) != 2:
- print(
- "Give the path to the examples/faces directory as the argument to this "
- "program. For example, if you are in the python_examples folder then "
- "execute this program by running:\n"
- " ./train_shape_predictor.py ../examples/faces")
- exit()
- faces_folder = sys.argv[1]
-
- options = dlib.shape_predictor_training_options()
(2)现在开始训练模型,在本算法中可以设置多个参数,在shape_predictor_trainer的文档中说明了这些参数的含义,在Kazemi的论文中也详细解释了各个参数。在本实例中,只是设置了其中的三个参数的值,没有使用这三个参数的默认值。这样设置的原因是,本实例用到的只是一个非常小的数据集。其中将采样参数设置为较高的值(300),可以有效地提高训练集的大小。
- options.oversampling_amount = 300
- #增加正则化(使nu变小)和使用深度更小的树来降低模型的容量。
- options.nu = 0.05
- options.tree_depth = 2
- options.be_verbose = True
(3)使用函数dlib.train_shape_predictor()做实际训练工作,将最终的预测器数据保存到文件predictor.dat中。输入的是一个XML文件,在其中列出了训练数据集中的图像,也包含了面部各个成员的位置。
- training_xml_path = os.path.join(faces_folder, "training_with_face_landmarks.xml")
- dlib.train_shape_predictor(training_xml_path, "predictor.dat", options)
(4)现在已经有了一个数据模型,接下来就可以测试这个模型。函数test_shape_predictor()用于测量shape_predictor输出的人脸标记与根据真值数据应该位于的位置之间的平均距离。
- print("\n训练精度: {}".format(
- dlib.test_shape_predictor(training_xml_path, "predictor.dat")))
(5)在真正的测试工作中,看看它在没有经过训练的数据上做得有多好。因为我们在一个非常小的数据集上进行训练,所以精确度不是很高,但是效果还是很满意的。此外,如果在一个大的人脸标记数据集上训练它,可以获得最好的结果,正如Kazemi的论文所示。
- testing_xml_path = os.path.join(faces_folder, "testing_with_face_landmarks.xml")
- print("测试精度 {}".format(
- dlib.test_shape_predictor(testing_xml_path, "predictor.dat")))
(6)接下来像在普通应用程序中一样使用预测数据predictor.dat,首先从磁盘中加载预测数据文件predictor.dat,然后还需要加载一个人脸检测器来提供人脸位置的初始估计值。
- predictor = dlib.shape_predictor("predictor.dat")
- detector = dlib.get_frontal_face_detector()
(7)接下来对“faces”文件夹中的图像运行detector和shape_predictor并显示结果。
- print("显示faces文件夹中图像的检测和预测...")
- win = dlib.image_window()
- for f in glob.glob(os.path.join(faces_folder, "*.jpg")):
- print("正在处理文件: {}".format(f))
- img = dlib.load_rgb_image(f)
-
- win.clear_overlay()
- win.set_image(img)
(8)让探测器找到每个面部的边界框,其中第二个参数1表示应该将图像向上采样1次,这样可以让我们能够发现更多的面孔。
- dets = detector(img, 1)
- print("检测到的面数: {}".format(len(dets)))
- for k, d in enumerate(dets):
- print("检测 {}: Left: {} Top: {} Right: {} Bottom: {}".format(
- k, d.left(), d.top(), d.right(), d.bottom()))
- #在方框d中获取面部的landmarks/parts
- shape = predictor(img, d)
- print("Part 0: {}, Part 1: {} ...".format(shape.part(0),
- shape.part(1)))
- #在屏幕中绘制出面部标志。
- win.add_overlay(shape)
-
- win.add_overlay(dets)
- dlib.hit_enter_to_continue()
输入下面的命令运行本实例,运行后会创建自制的数据集文件predictor.dat,并检测“examples/faces”目录中各个图片的人脸,如图2-11所示。每当按下回车键,可以逐一检测“examples/faces”目录中的图片。
python train_shape_predictor.py faces
图2-11 执行效果
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。