def detect_onet(self, im, dets): """Get face candidates using onet Parameters: ---------- im: numpy array input image array dets: numpy array detection results of rnet Returns: ------- boxes: numpy array detected boxes before calibration boxes_c: numpy array boxes after calibration """ h, w, c = im.shape dets = convert_to_square(dets) dets[:, 0:4] = np.round(dets[:, 0:4]) [dy, edy, dx, edx, y, ey, x, ex, tmpw, tmph] = pad(dets, w, h) num_boxes = dets.shape[0] ''' # helper for setting ONet batch size batch_size = self.onet_detector.batch_size ratio = float(num_boxes) / batch_size if ratio > 3 or ratio < 0.3: print "You may need to reset ONet batch size if this info appears frequently, \ face candidates:%d, current batch_size:%d"%(num_boxes, batch_size) ''' cropped_ims = np.zeros((num_boxes, 48, 48, 3), dtype=np.float32) for i in range(num_boxes): tmp = np.zeros((tmph[i], tmpw[i], 3), dtype=np.uint8) tmp[dy[i]:edy[i] + 1, dx[i]:edx[i] + 1, :] = im[y[i]:ey[i] + 1, x[i]:ex[i] + 1, :] cropped_ims[i, :, :, :] = cv2.resize(tmp, (48, 48)) / 127.5 cls_scores, reg = self.onet_detector.predict(cropped_ims) keep_inds = np.where(cls_scores > self.thresh[2])[0] if len(keep_inds) > 0: boxes = dets[keep_inds] boxes[:, 4] = cls_scores[keep_inds] reg = reg[keep_inds] else: return None, None boxes_c = calibrate_box(boxes, reg) keep = py_nms(boxes_c, 0.7, "Minimum") boxes_c = boxes_c[keep] return boxes, boxes_c
def detect_pnet(self, im): """Get face candidates through pnet Parameters: ---------- im: numpy array input image array Returns: ------- boxes: numpy array detected boxes before calibration boxes_c: numpy array boxes after calibration """ h, w, c = im.shape net_size = 12 current_scale = float( net_size) / self.min_face_size # find initial scale im_resized = resize_image(im, current_scale) current_height, current_width, _ = im_resized.shape if self.slide_window: # sliding window temp_rectangles = list() # rectangles = list() # list of rectangles [x11, y11, x12, y12, confidence] (corresponding to original image) all_cropped_ims = list() while min(current_height, current_width) > net_size: current_y_list = range(0, current_height - net_size + 1, self.stride) if ( current_height - net_size) % self.stride == 0 \ else list(range(0, current_height - net_size + 1, self.stride)) + [current_height - net_size] current_x_list = range(0, current_width - net_size + 1, self.stride) if ( current_width - net_size) % self.stride == 0 \ else list(range(0, current_width - net_size + 1, self.stride)) + [current_width - net_size] for current_y in current_y_list: for current_x in current_x_list: cropped_im = im_resized[current_y:current_y + net_size, current_x:current_x + net_size, :] current_rectangle = [ int(w * float(current_x) / current_width), int(h * float(current_y) / current_height), int(w * float(current_x) / current_width) + int(w * float(net_size) / current_width), int(h * float(current_y) / current_height) + int(w * float(net_size) / current_width), 0.0 ] temp_rectangles.append(current_rectangle) all_cropped_ims.append(cropped_im) current_scale *= self.scale_factor im_resized = resize_image(im, current_scale) current_height, current_width, _ = im_resized.shape ''' # helper for setting PNet batch size num_boxes = len(all_cropped_ims) batch_size = self.pnet_detector.batch_size ratio = float(num_boxes) / batch_size if ratio > 3 or ratio < 0.3: print "You may need to reset PNet batch size if this info appears frequently, \ face candidates:%d, current batch_size:%d"%(num_boxes, batch_size) ''' all_cropped_ims = np.vstack(all_cropped_ims) cls_scores, reg = self.pnet_detector.predict(all_cropped_ims) cls_scores = cls_scores[:, 1].flatten() keep_inds = np.where(cls_scores > self.thresh[0])[0] if len(keep_inds) > 0: boxes = np.vstack(temp_rectangles[ind] for ind in keep_inds) boxes[:, 4] = cls_scores[keep_inds] reg = reg[keep_inds].reshape(-1, 4) else: return None, None keep = py_nms(boxes, 0.7, 'Union') boxes = boxes[keep] boxes_c = calibrate_box(boxes, reg[keep]) else: # fcn all_boxes = list() while min(current_height, current_width) > net_size: cls_map, reg = self.pnet_detector.predict(im_resized) boxes = generate_bbox(cls_map[0, :, :], reg, current_scale, self.thresh[0]) current_scale *= self.scale_factor im_resized = resize_image(im, current_scale) current_height, current_width, _ = im_resized.shape if boxes.size == 0: continue keep = py_nms(boxes[:, :5], 0.5, 'Union') boxes = boxes[keep] all_boxes.append(boxes) if len(all_boxes) == 0: return None, None all_boxes = np.vstack(all_boxes) # merge the detection from first stage keep = py_nms(all_boxes[:, 0:5], 0.7, 'Union') all_boxes = all_boxes[keep] boxes = all_boxes[:, :5] bbw = all_boxes[:, 2] - all_boxes[:, 0] + 1 bbh = all_boxes[:, 3] - all_boxes[:, 1] + 1 # refine the boxes boxes_c = np.vstack([ all_boxes[:, 0] + all_boxes[:, 5] * bbw, all_boxes[:, 1] + all_boxes[:, 6] * bbh, all_boxes[:, 2] + all_boxes[:, 7] * bbw, all_boxes[:, 3] + all_boxes[:, 8] * bbh, all_boxes[:, 4] ]) boxes_c = boxes_c.T return boxes, boxes_c