人脸检测:MTCNN训练数据正负样本生成

本代码基于作者提供的python版本代码修改,参考:

https://github.com/DuinoDu/mtcnn/blob/master/demo.py  (作者提供)

https://github.com/dlunion/mtcnn/blob/master/train/gen_48net_data2.py


注解:Pnet和RNet之后的网络的Bbox的矩形框,关键点在框内的当成正样本来训练landmark;

1,生成positive,negative,part三种样本,用作者的net1->net2生成bbox, 根据预测的bbox和ground truth计算IOU:

positive: IOU >= 0.65;

negative: IOU < 0.3;

part: 0.4 <= IOU < 0.65

代码如下:

[python]  view plain  copy
  1. #!/usr/bin/env python  
  2. # -*- coding: utf-8 -*-  
  3. import _init_paths  
  4. import caffe  
  5. import cv2  
  6. import numpy as np  
  7. #from python_wrapper import *  
  8. import os  
  9.   
  10. def bbreg(boundingbox, reg):  
  11.     reg = reg.T   
  12.       
  13.     # calibrate bouding boxes  
  14.     if reg.shape[1] == 1:  
  15.         print "reshape of reg"  
  16.         pass # reshape of reg  
  17.     w = boundingbox[:,2] - boundingbox[:,0] + 1  
  18.     h = boundingbox[:,3] - boundingbox[:,1] + 1  
  19.   
  20.     bb0 = boundingbox[:,0] + reg[:,0]*w  
  21.     bb1 = boundingbox[:,1] + reg[:,1]*h  
  22.     bb2 = boundingbox[:,2] + reg[:,2]*w  
  23.     bb3 = boundingbox[:,3] + reg[:,3]*h  
  24.       
  25.     boundingbox[:,0:4] = np.array([bb0, bb1, bb2, bb3]).T  
  26.     #print "bb", boundingbox  
  27.     return boundingbox  
  28.   
  29. def pad(boxesA, w, h):  
  30.     boxes = boxesA.copy() # shit, value parameter!!!  
  31.   
  32.     tmph = boxes[:,3] - boxes[:,1] + 1  
  33.     tmpw = boxes[:,2] - boxes[:,0] + 1  
  34.     numbox = boxes.shape[0]  
  35.   
  36.     dx = np.ones(numbox)  
  37.     dy = np.ones(numbox)  
  38.     edx = tmpw   
  39.     edy = tmph  
  40.   
  41.     x = boxes[:,0:1][:,0]  
  42.     y = boxes[:,1:2][:,0]  
  43.     ex = boxes[:,2:3][:,0]  
  44.     ey = boxes[:,3:4][:,0]  
  45.     tmp = np.where(ex > w)[0]  
  46.     if tmp.shape[0] != 0:  
  47.         edx[tmp] = -ex[tmp] + w-1 + tmpw[tmp]  
  48.         ex[tmp] = w-1  
  49.   
  50.     tmp = np.where(ey > h)[0]  
  51.     if tmp.shape[0] != 0:  
  52.         edy[tmp] = -ey[tmp] + h-1 + tmph[tmp]  
  53.         ey[tmp] = h-1  
  54.   
  55.     tmp = np.where(x < 1)[0]  
  56.     if tmp.shape[0] != 0:  
  57.         dx[tmp] = 2 - x[tmp]  
  58.         x[tmp] = np.ones_like(x[tmp])  
  59.   
  60.     tmp = np.where(y < 1)[0]  
  61.     if tmp.shape[0] != 0:  
  62.         dy[tmp] = 2 - y[tmp]  
  63.         y[tmp] = np.ones_like(y[tmp])  
  64.       
  65.     # for python index from 0, while matlab from 1  
  66.     dy = np.maximum(0, dy-1)  
  67.     dx = np.maximum(0, dx-1)  
  68.     y = np.maximum(0, y-1)  
  69.     x = np.maximum(0, x-1)  
  70.     edy = np.maximum(0, edy-1)  
  71.     edx = np.maximum(0, edx-1)  
  72.     ey = np.maximum(0, ey-1)  
  73.     ex = np.maximum(0, ex-1)  
  74.   
  75.     return [dy, edy, dx, edx, y, ey, x, ex, tmpw, tmph]  
  76.   
  77. def IoU(box, boxes):  
  78.     """Compute IoU between detect box and gt boxes 
  79.  
  80.     Parameters: 
  81.     ---------- 
  82.     box: numpy array , shape (5, ): x1, y1, x2, y2, score 
  83.         input box 
  84.     boxes: numpy array, shape (n, 4): x1, y1, x2, y2 
  85.         input ground truth boxes 
  86.  
  87.     Returns: 
  88.     ------- 
  89.     ovr: numpy.array, shape (n, ) 
  90.         IoU 
  91.     """  
  92.     box_area = (box[2] - box[0] + 1) * (box[3] - box[1] + 1)  
  93.     area = (boxes[:, 2] - boxes[:, 0] + 1) * (boxes[:, 3] - boxes[:, 1] + 1)  
  94.     xx1 = np.maximum(box[0], boxes[:, 0])  
  95.     yy1 = np.maximum(box[1], boxes[:, 1])  
  96.     xx2 = np.minimum(box[2], boxes[:, 2])  
  97.     yy2 = np.minimum(box[3], boxes[:, 3])  
  98.   
  99.     # compute the width and height of the bounding box  
  100.     w = np.maximum(0, xx2 - xx1 + 1)  
  101.     h = np.maximum(0, yy2 - yy1 + 1)  
  102.   
  103.     inter = w * h  
  104.     ovr = inter / (box_area + area - inter)  
  105.     return ovr  
  106.   
  107.   
  108. def rerec(bboxA):  
  109.     # convert bboxA to square  
  110.     w = bboxA[:,2] - bboxA[:,0]  
  111.     h = bboxA[:,3] - bboxA[:,1]  
  112.     l = np.maximum(w,h).T  
  113.   
  114.     bboxA[:,0] = bboxA[:,0] + w*0.5 - l*0.5  
  115.     bboxA[:,1] = bboxA[:,1] + h*0.5 - l*0.5   
  116.     bboxA[:,2:4] = bboxA[:,0:2] + np.repeat([l], 2, axis = 0).T   
  117.     return bboxA  
  118.   
  119.   
  120. def nms(boxes, threshold, type):  
  121.     """nms 
  122.     :boxes: [:,0:5] 
  123.     :threshold: 0.5 like 
  124.     :type: 'Min' or others 
  125.     :returns: TODO 
  126.     """  
  127.     if boxes.shape[0] == 0:  
  128.         return np.array([])  
  129.     x1 = boxes[:,0]  
  130.     y1 = boxes[:,1]  
  131.     x2 = boxes[:,2]  
  132.     y2 = boxes[:,3]  
  133.     s = boxes[:,4]  
  134.     area = np.multiply(x2-x1+1, y2-y1+1)  
  135.     I = np.array(s.argsort()) # read s using I  
  136.       
  137.     pick = [];  
  138.     while len(I) > 0:  
  139.         xx1 = np.maximum(x1[I[-1]], x1[I[0:-1]])  
  140.         yy1 = np.maximum(y1[I[-1]], y1[I[0:-1]])  
  141.         xx2 = np.minimum(x2[I[-1]], x2[I[0:-1]])  
  142.         yy2 = np.minimum(y2[I[-1]], y2[I[0:-1]])  
  143.         w = np.maximum(0.0, xx2 - xx1 + 1)  
  144.         h = np.maximum(0.0, yy2 - yy1 + 1)  
  145.         inter = w * h  
  146.         if type == 'Min':  
  147.             o = inter / np.minimum(area[I[-1]], area[I[0:-1]])  
  148.         else:  
  149.             o = inter / (area[I[-1]] + area[I[0:-1]] - inter)  
  150.         pick.append(I[-1])  
  151.         I = I[np.where( o <= threshold)[0]]  
  152.     return pick  
  153.   
  154.   
  155. def generateBoundingBox(map, reg, scale, t):  
  156.     stride = 2  
  157.     cellsize = 12  
  158.     map = map.T  
  159.     dx1 = reg[0,:,:].T  
  160.     dy1 = reg[1,:,:].T  
  161.     dx2 = reg[2,:,:].T  
  162.     dy2 = reg[3,:,:].T  
  163.     (x, y) = np.where(map >= t)  
  164.   
  165.     yy = y  
  166.     xx = x  
  167.     score = map[x,y]  
  168.     reg = np.array([dx1[x,y], dy1[x,y], dx2[x,y], dy2[x,y]])  
  169.   
  170.     if reg.shape[0] == 0:  
  171.         pass  
  172.     boundingbox = np.array([yy, xx]).T  
  173.   
  174.     bb1 = np.fix((stride * (boundingbox) + 1) / scale).T # matlab index from 1, so with "boundingbox-1"  
  175.     bb2 = np.fix((stride * (boundingbox) + cellsize - 1 + 1) / scale).T # while python don't have to  
  176.     score = np.array([score])  
  177.   
  178.     boundingbox_out = np.concatenate((bb1, bb2, score, reg), axis=0)  
  179.   
  180.     return boundingbox_out.T 
  181.   
  182. def drawBoxes(im, boxes):  
  183.     x1 = boxes[:,0]  
  184.     y1 = boxes[:,1]  
  185.     x2 = boxes[:,2]  
  186.     y2 = boxes[:,3]  
  187.     for i in range(x1.shape[0]):  
  188.         cv2.rectangle(im, (int(x1[i]), int(y1[i])), (int(x2[i]), int(y2[i])), (0,255,0), 1)  
  189.     return im  
  190.   
  191. def drawlandmark(im, points):  
  192.     for i in range(points.shape[0]):  
  193.         for j in range(5):  
  194.             cv2.circle(im, (int(points[i][j]), int(points[i][j+5])), 2, (255,0,0))  
  195.     return im  
  196.   
  197.   
  198. from time import time  
  199. _tstart_stack = []  
  200. def tic():  
  201.     _tstart_stack.append(time())  
  202. def toc(fmt="Elapsed: %s s"):  
  203.     print fmt % (time()-_tstart_stack.pop())  
  204.   
  205.   
  206. def detect_face(img, minsize, PNet, RNet, threshold, fastresize, factor):  
  207.       
  208.     img2 = img.copy()  
  209.   
  210.     factor_count = 0  
  211.     total_boxes = np.zeros((0,9), np.float)  
  212.     points = []  
  213.     h = img.shape[0]  
  214.     w = img.shape[1]  
  215.     minl = min(h, w)  
  216.     img = img.astype(float)  
  217.     m = 12.0/minsize  
  218.     minl = minl*m  
  219.       
  220.   
  221.     # create scale pyramid  
  222.     scales = []  
  223.     while minl >= 12:  
  224.         scales.append(m * pow(factor, factor_count))  
  225.         minl *= factor  
  226.         factor_count += 1  
  227.       
  228.     # first stage  
  229.     for scale in scales:  
  230.         hs = int(np.ceil(h*scale))  
  231.         ws = int(np.ceil(w*scale))  
  232.   
  233.         if fastresize:  
  234.             im_data = (img-127.5)*0.0078125 # [0,255] -> [-1,1]  
  235.             im_data = cv2.resize(im_data, (ws,hs)) # default is bilinear  
  236.         else:   
  237.             im_data = cv2.resize(img, (ws,hs)) # default is bilinear  
  238.             im_data = (im_data-127.5)*0.0078125 # [0,255] -> [-1,1]  
  239.         #im_data = imResample(img, hs, ws); print "scale:", scale  
  240.   
  241.   
  242.         im_data = np.swapaxes(im_data, 02)  
  243.         im_data = np.array([im_data], dtype = np.float)  
  244.         PNet.blobs['data'].reshape(13, ws, hs)  
  245.         PNet.blobs['data'].data[...] = im_data  
  246.         out = PNet.forward()  
  247.       
  248.         boxes = generateBoundingBox(out['prob1'][0,1,:,:], out['conv4-2'][0], scale, threshold[0])  
  249.         if boxes.shape[0] != 0:  
  250.             pick = nms(boxes, 0.5'Union')  
  251.             if len(pick) > 0 :  
  252.                 boxes = boxes[pick, :]  
  253.   
  254.         if boxes.shape[0] != 0:  
  255.             total_boxes = np.concatenate((total_boxes, boxes), axis=0)  
  256.            
  257.     #np.save('total_boxes_101.npy', total_boxes)  
  258.   
  259.     #####  
  260.     # 1 #  
  261.     #####  
  262.     # print "[1]:",total_boxes.shape[0]  
  263.     #print total_boxes  
  264.     #return total_boxes, []   
  265.   
  266.   
  267.     numbox = total_boxes.shape[0]  
  268.     if numbox > 0:  
  269.         # nms  
  270.         pick = nms(total_boxes, 0.7'Union')  
  271.         total_boxes = total_boxes[pick, :]  
  272.         # print "[2]:",total_boxes.shape[0]  
  273.           
  274.         # revise and convert to square  
  275.         regh = total_boxes[:,3] - total_boxes[:,1]  
  276.         regw = total_boxes[:,2] - total_boxes[:,0]  
  277.         t1 = total_boxes[:,0] + total_boxes[:,5]*regw  
  278.         t2 = total_boxes[:,1] + total_boxes[:,6]*regh  
  279.         t3 = total_boxes[:,2] + total_boxes[:,7]*regw  
  280.         t4 = total_boxes[:,3] + total_boxes[:,8]*regh  
  281.         t5 = total_boxes[:,4]  
  282.         total_boxes = np.array([t1,t2,t3,t4,t5]).T  
  283.         total_boxes = rerec(total_boxes) # convert box to square  
  284.         # print "[4]:",total_boxes.shape[0]  
  285.           
  286.         total_boxes[:,0:4] = np.fix(total_boxes[:,0:4])  
  287.         # print "[4.5]:",total_boxes.shape[0]  
  288.         #print total_boxes  
  289.         [dy, edy, dx, edx, y, ey, x, ex, tmpw, tmph] = pad(total_boxes, w, h)  
  290.   
  291.   
  292.     numbox = total_boxes.shape[0]  
  293.     if numbox > 0:  
  294.         # second stage  
  295.   
  296.         # construct input for RNet  
  297.         tempimg = np.zeros((numbox, 24243)) # (24, 24, 3, numbox)  
  298.         for k in range(numbox):  
  299.             tmp = np.zeros((int(tmph[k]) +1, int(tmpw[k]) + 1,3))  
  300.             tmp[int(dy[k]):int(edy[k])+1, int(dx[k]):int(edx[k])+1] = img[int(y[k]):int(ey[k])+1, int(x[k]):int(ex[k])+1]  
  301.             #print "y,ey,x,ex", y[k], ey[k], x[k], ex[k]  
  302.             #print "tmp", tmp.shape  
  303.               
  304.             tempimg[k,:,:,:] = cv2.resize(tmp, (2424))  
  305.   
  306.         #print tempimg.shape  
  307.         #print tempimg[0,0,0,:]  
  308.         tempimg = (tempimg-127.5)*0.0078125 # done in imResample function wrapped by python  
  309.   
  310.   
  311.         # RNet  
  312.   
  313.         tempimg = np.swapaxes(tempimg, 13)  
  314.         #print tempimg[0,:,0,0]  
  315.           
  316.         RNet.blobs['data'].reshape(numbox, 32424)  
  317.         RNet.blobs['data'].data[...] = tempimg  
  318.         out = RNet.forward()  
  319.   
  320.         score = out['prob1'][:,1]  
  321.         #print 'score', score  
  322.         pass_t = np.where(score>threshold[1])[0]  
  323.         #print 'pass_t', pass_t  
  324.           
  325.         score =  np.array([score[pass_t]]).T  
  326.         total_boxes = np.concatenate( (total_boxes[pass_t, 0:4], score), axis = 1)  
  327.         # print "[5]:",total_boxes.shape[0]  
  328.         #print total_boxes  
  329.   
  330.         #print "1.5:",total_boxes.shape  
  331.           
  332.         mv = out['conv5-2'][pass_t, :].T  
  333.         #print "mv", mv  
  334.         if total_boxes.shape[0] > 0:  
  335.             pick = nms(total_boxes, 0.7'Union')  
  336.             # print 'pick', pick  
  337.             if len(pick) > 0:  
  338.                 total_boxes = total_boxes[pick, :]  
  339.                 # print "[6]:", total_boxes.shape[0]  
  340.                 total_boxes = bbreg(total_boxes, mv[:, pick])  
  341.                 # print "[7]:", total_boxes.shape[0]  
  342.                 total_boxes = rerec(total_boxes)  
  343.                 # print "[8]:", total_boxes.shape[0]  
  344.   
  345.     return total_boxes  
  346.   
  347.   
  348.   
  349.   
  350. def main():  
  351.     img_dir = "/home/xiao/code/mtcnn-caffe/prepare_data/WIDER_train/images/"  
  352.     imglistfile = "wider_face_train.txt"  
  353.     with open(imglistfile, 'r') as f:  
  354.         annotations = f.readlines()  
  355.     num = len(annotations)  
  356.     print "%d pics in total" % num  
  357.   
  358.     neg_save_dir = "/media/xiao/软件/mtcnn/train/48/negative/"  
  359.     pos_save_dir = "/media/xiao/软件/mtcnn/train/48/positive/"  
  360.     part_save_dir = "/media/xiao/软件/mtcnn/train/48/part/"  
  361.     image_size = 48  
  362.     f1 = open('/media/xiao/软件/mtcnn/train/48/pos_48.txt''w')  
  363.     f2 = open('/media/xiao/软件/mtcnn/train/48/neg_48.txt''w')  
  364.     f3 = open('/media/xiao/软件/mtcnn/train/48/part_48.txt''w')  
  365.   
  366.     p_idx = 0  # positive  
  367.     n_idx = 0  # negative  
  368.     d_idx = 0  # dont care  
  369.     image_idx = 0  
  370.   
  371.     minsize = 20  
  372.     caffe_model_path = "./model"  
  373.     threshold = [0.60.70.7]  
  374.     factor = 0.709  
  375.       
  376.     caffe.set_mode_gpu()  
  377.     PNet = caffe.Net(caffe_model_path+"/det1.prototxt", caffe_model_path+"/det1.caffemodel", caffe.TEST)  
  378.     RNet = caffe.Net(caffe_model_path+"/det2.prototxt", caffe_model_path+"/det2.caffemodel", caffe.TEST)  
  379.   
  380.   
  381.     for annotation in annotations:  
  382.         # imgpath = imgpath.split('\n')[0]  
  383.         annotation = annotation.strip().split(' ')  
  384.         bbox = map(float, annotation[1:])  
  385.         gts = np.array(bbox, dtype=np.float32).reshape(-14)  
  386.         img_path = img_dir + annotation[0] + '.jpg'  
  387.   
  388.         #print "######\n", img_path  
  389.         print image_idx  
  390.         image_idx += 1  
  391.         img = cv2.imread(img_path)  
  392.         img_matlab = img.copy()  
  393.         tmp = img_matlab[:,:,2].copy()  
  394.         img_matlab[:,:,2] = img_matlab[:,:,0]  
  395.         img_matlab[:,:,0] = tmp  
  396.   
  397.         boundingboxes = detect_face(img_matlab, minsize, PNet, RNet, threshold, False, factor)  
  398.   
  399.         #img = drawBoxes(img, boundingboxes)  
  400.         #cv2.imshow('img', img)  
  401.         #cv2.waitKey(1000)  
  402.   
  403.         # generate positive,negative,part samples  
  404.         for box in boundingboxes:  
  405.             x_left, y_top, x_right, y_bottom, _ = box  
  406.             crop_w = x_right - x_left + 1  
  407.             crop_h = y_bottom - y_top + 1  
  408.             # ignore box that is too small or beyond image border  
  409.             if crop_w < image_size / 2 or crop_h < image_size / 2:  
  410.                 continue  
  411.             if x_left < 0 or y_top < 0:  
  412.                 continue  
  413.   
  414.             # compute intersection over union(IoU) between current box and all gt boxes  
  415.             Iou = IoU(box, gts)  
  416.             cropped_im = img[int(y_top):int(y_bottom + 1) , int(x_left):int(x_right + 1) ]  
  417.             resized_im = cv2.resize(cropped_im, (image_size, image_size), interpolation=cv2.INTER_LINEAR)  
  418.             #try:  
  419.             #    resized_im = cv2.resize(cropped_im, (image_size, image_size), interpolation=cv2.INTER_LINEAR)  
  420.             #except  Exception as e:  
  421.             #    print " 1 "  
  422.             #    print e  
  423.   
  424.             # save negative images and write label, 负样本  
  425.             if np.max(Iou) < 0.3:  
  426.                 # Iou with all gts must below 0.3  
  427.                 save_file = os.path.join(neg_save_dir, "%s.jpg" % n_idx)  
  428.                 f2.write("%s/negative/%s.jpg" % (image_size, n_idx) + ' 0')  
  429.                 f2.write(" -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1\n")  
  430.                 cv2.imwrite(save_file, resized_im)  
  431.                 n_idx += 1  
  432.             else:  
  433.                 # find gt_box with the highest iou  
  434.                 idx = np.argmax(Iou)  
  435.                 assigned_gt = gts[idx]  
  436.                 x1, y1, x2, y2 = assigned_gt  
  437.   
  438.                 # compute bbox reg label,offset_x1,offset_y1相对于左上角; offset_x2,offset_y2相对于右上角  
  439.                 offset_x1 = (x1 - x_left) / float(crop_w)  
  440.                 offset_y1 = (y1 - y_top) / float(crop_h)  
  441.                 # offset_x2 = (x2 - x_left) / float(crop_w)  
  442.                 # offset_y2 = (y2 - y_top) / float(crop_h)  
  443.                 offset_x2 = (x2 - x_right)  / float(crop_w)  
  444.                 offset_y2 = (y2 - y_bottom )/ float(crop_h)  
  445.   
  446.                 # save positive and part-face images and write labels,  正样本  
  447.                 if np.max(Iou) >= 0.65:  
  448.                     save_file = os.path.join(pos_save_dir, "%s.jpg" % p_idx)  
  449.                     f1.write("%s/positive/%s.jpg" % (image_size, p_idx) + ' 1 %.6f %.6f %.6f %.6f' % (offset_x1, offset_y1, offset_x2, offset_y2))  
  450.                     f1.write(" -1 -1 -1 -1 -1 -1 -1 -1 -1 -1\n")  
  451.                     cv2.imwrite(save_file, resized_im)  
  452.                     p_idx += 1  
  453.   
  454.                 # part 样本  
  455.                 elif np.max(Iou) >= 0.4:  
  456.                     save_file = os.path.join(part_save_dir, "%s.jpg" % d_idx)  
  457.                     f3.write("%s/part/%s.jpg" % (image_size, d_idx) + ' -1 %.6f %.6f %.6f %.6f' % (offset_x1, offset_y1, offset_x2, offset_y2))  
  458.                     f3.write(" -1 -1 -1 -1 -1 -1 -1 -1 -1 -1\n")  
  459.                     cv2.imwrite(save_file, resized_im)  
  460.                     d_idx += 1  
  461.   
  462.   
  463.     f.close()  
  464.     f1.close()  
  465.     f2.close()  
  466.     f3.close()  
  467.   
  468. if __name__ == "__main__":  
  469.     main()  
  470.   
  471. </span>  


2,生成landmark样本,用作者的net1->net2生成bbox, 根据5个landmark是否都在bbox中作为判别条件:

扫描二维码关注公众号,回复: 1013491 查看本文章

代码如下:


[python]  view plain  copy
  1. #!/usr/bin/env python  
  2. # -*- coding: utf-8 -*-  
  3.   
  4. import _init_paths  
  5. import caffe  
  6. import cv2  
  7. import numpy as np  
  8. #from python_wrapper import *  
  9. import os  
  10.   
  11. def bbreg(boundingbox, reg):  
  12.     reg = reg.T   
  13.       
  14.     # calibrate bouding boxes  
  15.     if reg.shape[1] == 1:  
  16.         print "reshape of reg"  
  17.         pass # reshape of reg  
  18.     w = boundingbox[:,2] - boundingbox[:,0] + 1  
  19.     h = boundingbox[:,3] - boundingbox[:,1] + 1  
  20.   
  21.     bb0 = boundingbox[:,0] + reg[:,0]*w  
  22.     bb1 = boundingbox[:,1] + reg[:,1]*h  
  23.     bb2 = boundingbox[:,2] + reg[:,2]*w  
  24.     bb3 = boundingbox[:,3] + reg[:,3]*h  
  25.       
  26.     boundingbox[:,0:4] = np.array([bb0, bb1, bb2, bb3]).T  
  27.     #print "bb", boundingbox  
  28.     return boundingbox  
  29.   
  30.   
  31. def pad(boxesA, w, h):  
  32.     boxes = boxesA.copy() # shit, value parameter!!!  
  33.   
  34.     tmph = boxes[:,3] - boxes[:,1] + 1  
  35.     tmpw = boxes[:,2] - boxes[:,0] + 1  
  36.     numbox = boxes.shape[0]  
  37.   
  38.     dx = np.ones(numbox)  
  39.     dy = np.ones(numbox)  
  40.     edx = tmpw   
  41.     edy = tmph  
  42.   
  43.     x = boxes[:,0:1][:,0]  
  44.     y = boxes[:,1:2][:,0]  
  45.     ex = boxes[:,2:3][:,0]  
  46.     ey = boxes[:,3:4][:,0]  
  47.      
  48.      
  49.     tmp = np.where(ex > w)[0]  
  50.     if tmp.shape[0] != 0:  
  51.         edx[tmp] = -ex[tmp] + w-1 + tmpw[tmp]  
  52.         ex[tmp] = w-1  
  53.   
  54.     tmp = np.where(ey > h)[0]  
  55.     if tmp.shape[0] != 0:  
  56.         edy[tmp] = -ey[tmp] + h-1 + tmph[tmp]  
  57.         ey[tmp] = h-1  
  58.   
  59.     tmp = np.where(x < 1)[0]  
  60.     if tmp.shape[0] != 0:  
  61.         dx[tmp] = 2 - x[tmp]  
  62.         x[tmp] = np.ones_like(x[tmp])  
  63.   
  64.     tmp = np.where(y < 1)[0]  
  65.     if tmp.shape[0] != 0:  
  66.         dy[tmp] = 2 - y[tmp]  
  67.         y[tmp] = np.ones_like(y[tmp])  
  68.       
  69.     # for python index from 0, while matlab from 1  
  70.     dy = np.maximum(0, dy-1)  
  71.     dx = np.maximum(0, dx-1)  
  72.     y = np.maximum(0, y-1)  
  73.     x = np.maximum(0, x-1)  
  74.     edy = np.maximum(0, edy-1)  
  75.     edx = np.maximum(0, edx-1)  
  76.     ey = np.maximum(0, ey-1)  
  77.     ex = np.maximum(0, ex-1)  
  78.   
  79.     return [dy, edy, dx, edx, y, ey, x, ex, tmpw, tmph]  
  80.   
  81. def IoU(box, boxes):  
  82.     """Compute IoU between detect box and gt boxes 
  83.  
  84.     Parameters: 
  85.     ---------- 
  86.     box: numpy array , shape (5, ): x1, y1, x2, y2, score 
  87.         input box 
  88.     boxes: numpy array, shape (n, 4): x1, y1, x2, y2 
  89.         input ground truth boxes 
  90.  
  91.     Returns: 
  92.     ------- 
  93.     ovr: numpy.array, shape (n, ) 
  94.         IoU 
  95.     """  
  96.     box_area = (box[2] - box[0] + 1) * (box[3] - box[1] + 1)  
  97.     area = (boxes[:, 2] - boxes[:, 0] + 1) * (boxes[:, 3] - boxes[:, 1] + 1)  
  98.     xx1 = np.maximum(box[0], boxes[:, 0])  
  99.     yy1 = np.maximum(box[1], boxes[:, 1])  
  100.     xx2 = np.minimum(box[2], boxes[:, 2])  
  101.     yy2 = np.minimum(box[3], boxes[:, 3])  
  102.   
  103.     # compute the width and height of the bounding box  
  104.     w = np.maximum(0, xx2 - xx1 + 1)  
  105.     h = np.maximum(0, yy2 - yy1 + 1)  
  106.   
  107.     inter = w * h  
  108.     ovr = inter / (box_area + area - inter)  
  109.     return ovr  
  110.   
  111.   
  112. def rerec(bboxA):  
  113.     # convert bboxA to square  
  114.     w = bboxA[:,2] - bboxA[:,0]  
  115.     h = bboxA[:,3] - bboxA[:,1]  
  116.     l = np.maximum(w,h).T  
  117.   
  118.     bboxA[:,0] = bboxA[:,0] + w*0.5 - l*0.5  
  119.     bboxA[:,1] = bboxA[:,1] + h*0.5 - l*0.5   
  120.     bboxA[:,2:4] = bboxA[:,0:2] + np.repeat([l], 2, axis = 0).T   
  121.     return bboxA  
  122.   
  123.   
  124. def nms(boxes, threshold, type):  
  125.     """nms 
  126.     :boxes: [:,0:5] 
  127.     :threshold: 0.5 like 
  128.     :type: 'Min' or others 
  129.     :returns: TODO 
  130.     """  
  131.     if boxes.shape[0] == 0:  
  132.         return np.array([])  
  133.     x1 = boxes[:,0]  
  134.     y1 = boxes[:,1]  
  135.     x2 = boxes[:,2]  
  136.     y2 = boxes[:,3]  
  137.     s = boxes[:,4]  
  138.     area = np.multiply(x2-x1+1, y2-y1+1)  
  139.     I = np.array(s.argsort()) # read s using I  
  140.       
  141.     pick = [];  
  142.     while len(I) > 0:  
  143.         xx1 = np.maximum(x1[I[-1]], x1[I[0:-1]])  
  144.         yy1 = np.maximum(y1[I[-1]], y1[I[0:-1]])  
  145.         xx2 = np.minimum(x2[I[-1]], x2[I[0:-1]])  
  146.         yy2 = np.minimum(y2[I[-1]], y2[I[0:-1]])  
  147.         w = np.maximum(0.0, xx2 - xx1 + 1)  
  148.         h = np.maximum(0.0, yy2 - yy1 + 1)  
  149.         inter = w * h  
  150.         if type == 'Min':  
  151.             o = inter / np.minimum(area[I[-1]], area[I[0:-1]])  
  152.         else:  
  153.             o = inter / (area[I[-1]] + area[I[0:-1]] - inter)  
  154.         pick.append(I[-1])  
  155.         I = I[np.where( o <= threshold)[0]]  
  156.     return pick  
  157.   
  158.   
  159. def generateBoundingBox(map, reg, scale, t):  
  160.     stride = 2  
  161.     cellsize = 12  
  162.     map = map.T  
  163.     dx1 = reg[0,:,:].T  
  164.     dy1 = reg[1,:,:].T  
  165.     dx2 = reg[2,:,:].T  
  166.     dy2 = reg[3,:,:].T  
  167.     (x, y) = np.where(map >= t)  
  168.   
  169.     yy = y  
  170.     xx = x  
  171.   
  172.   
  173.     score = map[x,y]  
  174.     reg = np.array([dx1[x,y], dy1[x,y], dx2[x,y], dy2[x,y]])  
  175.   
  176.     if reg.shape[0] == 0:  
  177.         pass  
  178.     boundingbox = np.array([yy, xx]).T  
  179.   
  180.     bb1 = np.fix((stride * (boundingbox) + 1) / scale).T # matlab index from 1, so with "boundingbox-1"  
  181.     bb2 = np.fix((stride * (boundingbox) + cellsize - 1 + 1) / scale).T # while python don't have to  
  182.     score = np.array([score])  
  183.   
  184.     boundingbox_out = np.concatenate((bb1, bb2, score, reg), axis=0)  
  185.   
  186.     return boundingbox_out.T  
  187.   
  188.   
  189.   
  190. def drawBoxes(im, boxes):  
  191.     x1 = boxes[:,0]  
  192.     y1 = boxes[:,1]  
  193.     x2 = boxes[:,2]  
  194.     y2 = boxes[:,3]  
  195.     for i in range(x1.shape[0]):  
  196.         cv2.rectangle(im, (int(x1[i]), int(y1[i])), (int(x2[i]), int(y2[i])), (0,255,0), 1)  
  197.     return im  
  198.   
  199. def drawBoxes_align(im, boxe):  
  200.     x1 = boxe[0]  
  201.     y1 = boxe[1]  
  202.     x2 = boxe[2]  
  203.     y2 = boxe[3]  
  204.     cv2.rectangle(im, (int(x1), int(y1)), (int(x2), int(y2)), (0,255,0), 1)  
  205.     return im  
  206.   
  207. def drawlandmark(im, points):  
  208.     for i in range(points.shape[0]):  
  209.         for j in range(5):  
  210.             cv2.circle(im, (int(points[i][j]), int(points[i][j+5])), 2, (255,0,0))  
  211.     return im  
  212.   
  213. def drawlandmark_align(im, point):  
  214.     for j in range(5):  
  215.         cv2.circle(im, (int(point[j*2]), int(point[j*2+1])), 2, (255,0,0))  
  216.     return im  
  217.   
  218.   
  219. from time import time  
  220. _tstart_stack = []  
  221. def tic():  
  222.     _tstart_stack.append(time())  
  223. def toc(fmt="Elapsed: %s s"):  
  224.     print fmt % (time()-_tstart_stack.pop())  
  225.   
  226.   
  227. def detect_face(img, minsize, PNet, RNet, threshold, fastresize, factor):  
  228.       
  229.     img2 = img.copy()  
  230.   
  231.     factor_count = 0  
  232.     total_boxes = np.zeros((0,9), np.float)  
  233.     points = []  
  234.     h = img.shape[0]  
  235.     w = img.shape[1]  
  236.     minl = min(h, w)  
  237.     img = img.astype(float)  
  238.     m = 12.0/minsize  
  239.     minl = minl*m  
  240.       
  241.   
  242.     # create scale pyramid  
  243.     scales = []  
  244.     while minl >= 12:  
  245.         scales.append(m * pow(factor, factor_count))  
  246.         minl *= factor  
  247.         factor_count += 1  
  248.       
  249.     # first stage  
  250.     for scale in scales:  
  251.         hs = int(np.ceil(h*scale))  
  252.         ws = int(np.ceil(w*scale))  
  253.   
  254.         if fastresize:  
  255.             im_data = (img-127.5)*0.0078125 # [0,255] -> [-1,1]  
  256.             im_data = cv2.resize(im_data, (ws,hs)) # default is bilinear  
  257.         else:   
  258.             im_data = cv2.resize(img, (ws,hs)) # default is bilinear  
  259.             im_data = (im_data-127.5)*0.0078125 # [0,255] -> [-1,1]  
  260.         #im_data = imResample(img, hs, ws); print "scale:", scale  
  261.   
  262.   
  263.         im_data = np.swapaxes(im_data, 02)  
  264.         im_data = np.array([im_data], dtype = np.float)  
  265.         PNet.blobs['data'].reshape(13, ws, hs)  
  266.         PNet.blobs['data'].data[...] = im_data  
  267.         out = PNet.forward()  
  268.       
  269.         boxes = generateBoundingBox(out['prob1'][0,1,:,:], out['conv4-2'][0], scale, threshold[0])  
  270.         if boxes.shape[0] != 0:  
  271.             pick = nms(boxes, 0.5'Union')  
  272.             if len(pick) > 0 :  
  273.                 boxes = boxes[pick, :]  
  274.   
  275.         if boxes.shape[0] != 0:  
  276.             total_boxes = np.concatenate((total_boxes, boxes), axis=0)  
  277.            
  278.     #np.save('total_boxes_101.npy', total_boxes)  
  279.   
  280.     #####  
  281.     # 1 #  
  282.     #####  
  283.     # print "[1]:",total_boxes.shape[0]  
  284.     #print total_boxes  
  285.     #return total_boxes, []   
  286.   
  287.   
  288.     numbox = total_boxes.shape[0]  
  289.     if numbox > 0:  
  290.         # nms  
  291.         pick = nms(total_boxes, 0.7'Union')  
  292.         total_boxes = total_boxes[pick, :]  
  293.         # print "[2]:",total_boxes.shape[0]  
  294.           
  295.         # revise and convert to square  
  296.         regh = total_boxes[:,3] - total_boxes[:,1]  
  297.         regw = total_boxes[:,2] - total_boxes[:,0]  
  298.         t1 = total_boxes[:,0] + total_boxes[:,5]*regw  
  299.         t2 = total_boxes[:,1] + total_boxes[:,6]*regh  
  300.         t3 = total_boxes[:,2] + total_boxes[:,7]*regw  
  301.         t4 = total_boxes[:,3] + total_boxes[:,8]*regh  
  302.         t5 = total_boxes[:,4]  
  303.         total_boxes = np.array([t1,t2,t3,t4,t5]).T  
  304.         total_boxes = rerec(total_boxes) # convert box to square  
  305.         # print "[4]:",total_boxes.shape[0]  
  306.           
  307.         total_boxes[:,0:4] = np.fix(total_boxes[:,0:4])  
  308.         # print "[4.5]:",total_boxes.shape[0]  
  309.         #print total_boxes  
  310.         [dy, edy, dx, edx, y, ey, x, ex, tmpw, tmph] = pad(total_boxes, w, h)  
  311.   
  312.   
  313.     numbox = total_boxes.shape[0]  
  314.     if numbox > 0:  
  315.         # second stage  
  316.   
  317.         # construct input for RNet  
  318.         tempimg = np.zeros((numbox, 24243)) # (24, 24, 3, numbox)  
  319.         for k in range(numbox):  
  320.             tmp = np.zeros((int(tmph[k]) +1, int(tmpw[k]) + 1,3))  
  321.             tmp[int(dy[k]):int(edy[k])+1, int(dx[k]):int(edx[k])+1] = img[int(y[k]):int(ey[k])+1, int(x[k]):int(ex[k])+1]  
  322.             #print "y,ey,x,ex", y[k], ey[k], x[k], ex[k]  
  323.             #print "tmp", tmp.shape  
  324.               
  325.             tempimg[k,:,:,:] = cv2.resize(tmp, (2424))  
  326.   
  327.         #print tempimg.shape  
  328.         #print tempimg[0,0,0,:]  
  329.         tempimg = (tempimg-127.5)*0.0078125 # done in imResample function wrapped by python  
  330.   
  331.   
  332.         # RNet  
  333.   
  334.         tempimg = np.swapaxes(tempimg, 13)  
  335.         #print tempimg[0,:,0,0]  
  336.           
  337.         RNet.blobs['data'].reshape(numbox, 32424)  
  338.         RNet.blobs['data'].data[...] = tempimg  
  339.         out = RNet.forward()  
  340.   
  341.         score = out['prob1'][:,1]  
  342.         #print 'score', score  
  343.         pass_t = np.where(score>threshold[1])[0]  
  344.         #print 'pass_t', pass_t  
  345.           
  346.         score =  np.array([score[pass_t]]).T  
  347.         total_boxes = np.concatenate( (total_boxes[pass_t, 0:4], score), axis = 1)  
  348.         # print "[5]:",total_boxes.shape[0]  
  349.         #print total_boxes  
  350.   
  351.         #print "1.5:",total_boxes.shape  
  352.           
  353.         mv = out['conv5-2'][pass_t, :].T  
  354.         #print "mv", mv  
  355.         if total_boxes.shape[0] > 0:  
  356.             pick = nms(total_boxes, 0.7'Union')  
  357.             # print 'pick', pick  
  358.             if len(pick) > 0:  
  359.                 total_boxes = total_boxes[pick, :]  
  360.                 # print "[6]:", total_boxes.shape[0]  
  361.                 total_boxes = bbreg(total_boxes, mv[:, pick])  
  362.                 # print "[7]:", total_boxes.shape[0]  
  363.                 total_boxes = rerec(total_boxes)  
  364.                 # print "[8]:", total_boxes.shape[0]  
  365.   
  366.     return total_boxes  
  367.   
  368.   
  369.   
  370.   
  371. def main():  
  372.     img_dir = "/media/xiao/学习/face_alignment/data/CelebA/Img/img_celeba.7z/img_celeba/"  
  373.     anno_file = "celebA_bbox_landmark.txt"  
  374.     with open(anno_file, 'r') as f:  
  375.         annotations = f.readlines()  
  376.     num = len(annotations)  
  377.     print "%d pics in total" % num  
  378.   
  379.     # 图片大小为48*48  
  380.     image_size = 48  
  381.     # landmark_save_dir = "48/landmark/"  
  382.     landmark_save_dir = "/media/xiao/软件/mtcnn/train/48/landmark/"  
  383.     # save_dir = "./" + str(image_size)  
  384.     f1 = open('/media/xiao/软件/mtcnn/train/48/landmark_48.txt''w')  
  385.   
  386.     l_idx = 0  # landmark  
  387.     image_idx = 0  
  388.   
  389.     minsize = 40  
  390.     caffe_model_path = "./model"  
  391.     threshold = [0.60.70.7]  
  392.     factor = 0.709  
  393.       
  394.     caffe.set_mode_gpu()  
  395.     PNet = caffe.Net(caffe_model_path+"/det1.prototxt", caffe_model_path+"/det1.caffemodel", caffe.TEST)  
  396.     RNet = caffe.Net(caffe_model_path+"/det2.prototxt", caffe_model_path+"/det2.caffemodel", caffe.TEST)   
  397.     for annotation in annotations:  
  398.         # imgpath = imgpath.split('\n')[0]  
  399.         annotation = annotation.strip().split(' ')  
  400.   
  401.         im_path = annotation[0]  
  402.         # bbox = map(float, annotation[1:-10])  
  403.         pts = map(float, annotation[-10:])  
  404.         # boxes = np.array(bbox, dtype=np.float32).reshape(-1, 4)  
  405.         im_path = img_dir + im_path  
  406.         backupPts = pts[:]  
  407.   
  408.         #print "######\n", img_path  
  409.         print image_idx  
  410.         image_idx += 1  
  411.         img = cv2.imread(im_path)  
  412.         img_matlab = img.copy()  
  413.         tmp = img_matlab[:,:,2].copy()  
  414.         img_matlab[:,:,2] = img_matlab[:,:,0]  
  415.         img_matlab[:,:,0] = tmp  
  416.   
  417.         # 用作者提供的net1->net2生成人脸框  
  418.         boundingboxes = detect_face(img_matlab, minsize, PNet, RNet, threshold, False, factor)  
  419.   
  420.         #img = drawBoxes(img, boundingboxes)  
  421.         #cv2.imshow('img', img)  
  422.         #cv2.waitKey(1000)  
  423.   
  424.         # generate landmark samples  
  425.         for box in boundingboxes:  
  426.             x_left, y_top, x_right, y_bottom, _ = box    # 得到人脸bbox坐标  
  427.             crop_w = x_right - x_left + 1  
  428.             crop_h = y_bottom - y_top + 1  
  429.             # ignore box that is too small or beyond image border  
  430.             if crop_w < image_size / 2 or crop_h < image_size / 2:  
  431.                 continue  
  432.             if x_left < 0 or y_top < 0:  
  433.                 continue  
  434.   
  435.             # 当五个landmark都在bbox中时,这样的样本作为我们的landmark训练样本  
  436.             if pts[0] < x_left or pts[0] > x_right:  
  437.                 continue  
  438.             if pts[2] < x_left or pts[2] > x_right:  
  439.                 continue  
  440.             if pts[4] < x_left or pts[4] > x_right:  
  441.                 continue  
  442.             if pts[6] < x_left or pts[6] > x_right:  
  443.                 continue  
  444.             if pts[8] < x_left or pts[8] > x_right:  
  445.                 continue  
  446.   
  447.             if pts[1] < y_top or pts[1] > y_bottom:  
  448.                 continue  
  449.             if pts[3] < y_top or pts[3] > y_bottom:  
  450.                 continue  
  451.             if pts[5] < y_top or pts[5] > y_bottom:  
  452.                 continue  
  453.             if pts[7] < y_top or pts[7] > y_bottom:  
  454.                 continue  
  455.             if pts[9] < y_top or pts[9] > y_bottom:  
  456.                 continue  
  457.   
  458.             # show image  
  459.             #img1 = drawBoxes_align(img, box)  
  460.             #img1 = drawlandmark_align(img1, pts)  
  461.             #cv2.imshow('img', img1)  
  462.             #cv2.waitKey(1000)  
  463.   
  464.             # our method, x0,y0,x1,y1,x2,y2,x3,y3,x4,y4  
  465.             #for k in range(len(pts) / 2):  
  466.             #    pts[k * 2] = (pts[k * 2] - x_left) / float(crop_w);  
  467.             #    pts[k * 2 + 1] = (pts[k * 2 + 1] - y_top) / float(crop_h);  
  468.   
  469.             #author method, x0,x1,x2,x3,x4,y0,y1,y2,y3,y4  
  470.             ptsss = pts[:]  
  471.             # landmark标注为其相对于crop区域左上角的归一化值  
  472.             for k in range(len(ptsss) / 2):  
  473.                 pts[k] = (ptsss[k * 2] - x_left) / float(crop_w);  
  474.                 pts[5+k] = (ptsss[k * 2 + 1] - y_top) / float(crop_h);  
  475.   
  476.             # 将crop区域进行resize  
  477.             cropped_im = img[int(y_top):int(y_bottom + 1), int(x_left):int(x_right + 1)]  
  478.             resized_im = cv2.resize(cropped_im, (image_size, image_size), interpolation=cv2.INTER_LINEAR)  
  479.   
  480.             # box_ = box.reshape(1, -1)  
  481.             # 写图片名,class坐标,bbox坐标。  
  482.             save_file = os.path.join(landmark_save_dir, "%s.jpg" % l_idx)  
  483.             f1.write(str(image_size) + "/landmark/%s.jpg" % l_idx + ' -1 -1 -1 -1 -1')  
  484.   
  485.             # 写landmark坐标并保存图片  
  486.             for k in range(len(pts)):  
  487.                 f1.write(" %f" % pts[k])  
  488.             f1.write("\n")  
  489.             cv2.imwrite(save_file, resized_im)  
  490.             l_idx += 1  
  491.     f.close()  
  492.     f1.close()    
  493.   
  494. if __name__ == "__main__":  
  495.     main() 

猜你喜欢

转载自blog.csdn.net/wfei101/article/details/80372598