class FaceGenderAge(object): WRN_WEIGHTS_PATH = "https://github.com/Tony607/Keras_age_gender/releases/download/V1.0/weights.18-4.06.hdf5" def __init__(self, depth=16, width=8, face_size=64): self.face_size = face_size self.model = WideResNet(face_size, depth=depth, k=width)() model_dir = os.path.join(os.getcwd(), "models") fpath = get_file('weights.18-4.06.hdf5', self.WRN_WEIGHTS_PATH, cache_subdir=model_dir) self.model.load_weights(fpath) self.model._make_predict_function() def predict_agge(self, frame): inference_frame = cv2.resize(frame, (self.face_size, self.face_size)) inference_frame = inference_frame[np.newaxis, :, :, :] results = self.model.predict(inference_frame) predicted_genders = results[0] ages = np.arange(0, 101).reshape(101, 1) predicted_ages = results[1].dot(ages).flatten() label = "Age: {}, Gender: {}".format( int(predicted_ages), "F" if predicted_genders[0][0] > 0.5 else "M") return label
def detection(self): depth = 16 width = 8 img_size = 64 model = WideResNet(img_size, depth=depth, k=width)() model.load_weights(r'models/weights.hdf5') detector = dlib.get_frontal_face_detector() image_np = cv2.imdecode(np.fromfile(self.fname, dtype=np.uint8), -1) img_h = image_np.shape[0] img_w = image_np.shape[1] detected = detector(image_np, 1) gender_faces = [] labels = [] original_faces = [] photo_position = [] change_male_to_female_path = r'models/netG_A2B.pth' change_female_to_male_path = r'models/netG_B2A.pth' # 加载CycleGAN模型 netG_male2female = Generator(3, 3) netG_female2male = Generator(3, 3) netG_male2female.load_state_dict( torch.load(change_male_to_female_path, map_location='cpu')) netG_female2male.load_state_dict( torch.load(change_female_to_male_path, map_location='cpu')) # 设置模型为预测模式 netG_male2female.eval() netG_female2male.eval() transform_list = [ transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)) ] transform = transforms.Compose(transform_list) """ 这段内容为图片数据处理frame """ if len(detected) > 0: for i, d in enumerate(detected): # weight和height表示原始图片的宽度和高度,因为我们需要不停地resize处理图片 # 最后要贴回到原始图片中去,w和h就用来做最后的resize x0, y0, x1, y1, w, h = d.left(), d.top(), d.right(), d.bottom( ), d.width(), d.height() x0 = max(int(x0 - 0.25 * w), 0) y0 = max(int(y0 - 0.45 * h), 0) x1 = min(int(x1 + 0.25 * w), img_w - 1) y1 = min(int(y1 + 0.05 * h), img_h - 1) w = x1 - x0 h = y1 - y0 if w > h: x0 = x0 + w // 2 - h // 2 w = h x1 = x0 + w else: y0 = y0 + h // 2 - w // 2 h = w y1 = y0 + h original_faces.append( cv2.resize(image_np[y0:y1, x0:x1, :], (256, 256))) gender_faces.append( cv2.resize(image_np[y0:y1, x0:x1, :], (img_size, img_size))) photo_position.append([y0, y1, x0, x1, w, h]) gender_faces = np.array(gender_faces) results = model.predict(gender_faces) predicted_genders = results[0] for i in range(len(original_faces)): labels.append('F' if predicted_genders[i][0] > 0.5 else 'M') for i, gender in enumerate(labels): # 这几个变量用于接下来图片缩放和替换 y0, y1, x0, x1, w, h = photo_position[i] # 将数据转换成Pytorch可以处理的格式 picture = transform(original_faces[i]) picture = Variable(picture) input_picture = picture.unsqueeze(0) if gender == "M": fake_female = 0.5 * (netG_male2female(input_picture).data + 1.0) out_img = fake_female.detach().squeeze(0) else: fake_male = 0.5 * (netG_female2male(input_picture).data + 1.0) out_img = fake_male.detach().squeeze(0) # 需要将Pytorch处理之后得到的数据,转换为OpenCV可以处理的格式 # 下面代码就是转换代码 image_numpy = out_img.float().numpy() image_numpy = (np.transpose(image_numpy, (1, 2, 0)) + 1) / 2.0 * 255.0 image_numpy = image_numpy.clip(0, 255) image_numpy = image_numpy.astype(np.uint8) # 将转换好的性别图片替换到原始图片中去 # 使用泊松融合使生成图像和背景图像浑然一体 # 使用方法:cv2.seamlessClone(src, dst, mask, center, flags) generate_face = cv2.resize(image_numpy, (w, h)) # Create an all white mask, 感兴趣的需要替换的目标区域,精确地mask可以更好的替换,这里mask就是生成图片的大小 mask = 255 * np.ones((w, h), image_np.dtype) # center是目标影像的中心在背景图像上的坐标! center_y = y0 + h // 2 center_x = x0 + w // 2 center = (center_x, center_y) output_face = cv2.seamlessClone(generate_face, image_np, mask, center, cv2.NORMAL_CLONE) self.out_img = output_face
emotion_labels = get_labels('fer2013') gender_labels = get_labels('imdb') race_labels = get_labels('race') font = cv2.FONT_HERSHEY_SIMPLEX # hyper-parameters for bounding boxes shape frame_window = 10 gender_offsets = (30, 60) emotion_offsets = (20, 40) # loading models face_detection = load_detection_model(detection_model_path) emotion_classifier = load_model(emotion_model_path, compile=False) # race_classifier = load_model(race_model_path, compile=False) age_gender_classifier = WideResNet(64, depth=16, k=8)() age_gender_classifier.load_weights(age_gender_model_path) # getting input model shapes for inference emotion_target_size = emotion_classifier.input_shape[1:3] age_gender_target_size = age_gender_classifier.input_shape[1:3] # race_target_size = race_classifier.input_shape[1:3] # starting lists for calculating modes gender_window = [] emotion_window = [] # starting video streaming cv2.namedWindow('window_frame') video_capture = cv2.VideoCapture(video_path) fourcc = cv2.VideoWriter_fourcc(*'MJPG')