dlib目标关键点检测器训练
2018年12月30日
在训练之前 我们需要目标检测器和已标注的数据集:
dlib下训练自己的物体检测器
开始训练:
把“D:\dlib-19.15\python_examples”目录下的“train_shape_predictor.py”复制命名为“train_shape_predictor_hand.py”
并修改代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
import os import sys import glob import dlib import cv2 ''' 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] ''' faces_folder = "../tools/imglab/build/Release" #“handpredictor.dat”为已训练好的,如果存在择不用再训练 if not os.path.exists("handpredictor.dat"): options = dlib.shape_predictor_training_options() #现在让对象负责训练模型。 #这个算法有很多参数,你可以搞砸。这个documentation for the shape_predictor_trainer的文档解释了所有这些。 #您还应该阅读Kazemi的论文,其中解释了所有参数非常详细。但是,这里我只设置其中的三个与默认值不同 #我这么做是因为我们有一个非常小的数据集。特别地,设置过采样 #到较高的数量(300)有效地提高了训练集的大小,所以 #这有助于这个示例。 #通过对训练样本进行随机变形扩大样本数目。比如你原来有N张训练图片,通过该参数的设置,训练样本数将变成N*_oversampling_amount张。 #所以通常该值越大越好,只是训练耗时也会越久 options.oversampling_amount = 300 #我还通过显式增加来减少模型的容量 #正则化(使nu更小)以及使用较小的深度。 #正则项,nu越大,表示对训练样本fit越好,当然也越有可能发生过拟合。_nu取值范围(0,1],默认取0.1。 options.nu = 0.05 #树深,则树的叶子节点个数为2(_tree_depth)个 options.tree_depth = 2 #cpu测试机器为num_threads(线程)核数 options.num_threads=4 options.be_verbose = True #dlib.train_shape_predictor() 执行实际的训练。输入是一个XML文件,它列出了训练数据集中的图像 #并且还包含人脸的位置部分零件。 training_xml_path = os.path.join(faces_folder, "handdataset.xml") #它将保存final predictor to handpredictor.dat. dlib.train_shape_predictor(training_xml_path, "handpredictor.dat", options) # 现在我们有了一个模型,可以测试它了 dlib.test_shape_predictor() # measures the average distance between a face landmark output by the # shape_predictor and where it should be according to the truth data. print("\nTraining accuracy: {}".format( dlib.test_shape_predictor(training_xml_path, "handpredictor.dat"))) # 真正的测试是看它在没有经过训练的数据上表现得有多好。 #我们在一个非常小的数据集上训练它,所以精度不是很高。 #但是它仍然做得很好. 此外,如果你在一个大型飞机上训练 # 面部标志数据集,您将获得最先进的结果, 如Kazemi论文所示. testing_xml_path = os.path.join(faces_folder, "handdataset.xml") print("Testing accuracy: {}".format( dlib.test_shape_predictor(testing_xml_path, "handpredictor.dat"))) # 现在让我们像在普通应用程序中一样使用它. 首先,我们将从磁盘加载它。 # 我们还需要加载一个面部检测器来提供初始值面部位置的估计。 predictor = dlib.shape_predictor("handpredictor.dat") #detector = dlib.get_frontal_face_detector() #加载之前训练好的目标检测器 detector = dlib.simple_object_detector("handdetector.svm") #现在让我们在面部的图像上运行检测器和shape_predictor文件夹并显示结果。 #print("Showing detections and predictions on the images in the faces folder...") win = dlib.image_window() for f in glob.glob(os.path.join(faces_folder, "testimages/*.jpg")): #print("Processing file: {}".format(f)) img = dlib.load_rgb_image(f) #img = dlib.load_rgb_image(os.path.join(faces_folder, "handimages/S1-P1-F-11-1.jpg")) # 让探测器找出每个人脸的边框。 The 1 in the # 第二个参数指示我们应该对图像进行1次上采样. #这将使所有东西变得更大,并允许我们检测更多的脸。 #dets = detector(img, 1) dets = detector(img) #d=dlib.rectangle(114, 140, 355, 388) #print("Left: {} Top: {} Right: {} Bottom: {}".format(d.left(), d.top(), d.right(), d.bottom())) # Get the landmarks/parts for the face in box d. for d in dets: shape = predictor(img, d) cv2.cvtColor(img, cv2.COLOR_RGB2BGR) #特征点总数 partss=len(shape.parts()) for i in range(partss): pa=shape.part(i) p = (pa.x,pa.y) #(shape.part(i).x, shape.part(i).y) cv2.circle(img,p,1,(0,255,0),2) #各参数依次是:照片/添加的文字/左上角坐标/字体/字体大小/颜色/字体粗细 cv2.putText(img,str(i),p,cv2.FONT_HERSHEY_COMPLEX,1,(0,0,255),1) # Draw the face landmarks on the screen. cv2.cvtColor(img, cv2.COLOR_BGR2RGB) win.clear_overlay() win.set_image(img) #win.add_overlay(shape) win.add_overlay(d) dlib.hit_enter_to_continue() |
关键点训练结果:
tree_depth=2,num_threads=8,CPU:70% 内存:20+GB 6+小时 sp.data=15.8MB
tree_depth=4,num_threads=8,CPU:70% 内存:20+GB 12+小时 sp.data=63.3MB
tree_depth=5,num_threads=8,CPU:70% 内存:20+GB 16+小时 sp.data=126MB
个人理解:
提高tree_depth可以增加检测器的精确度但同时增加生成模型的体积
num_threads为线程,根据自己的机器CPU核数调整
命令行输入:
1 |
python train_shape_predictor_hand.py |
每回车一次查看一张图片检测效果如下: