def mainloop(): global config, masks, layers, config_mtime config, config_mtime_new = load_config(config_mtime, config) if config_mtime != config_mtime_new: config['width'] = width config['height'] = height layers = [] # Allow filters to run their destructors layers = reload_layers(config) config_mtime = config_mtime_new if static_image is not None: success, frame = True, static_image else: success, frame = cap.read() if not success: print("Error getting a webcam image!") sys.exit(1) # BGR to RGB frame = frame[..., ::-1] frame = frame.astype(np.float) input_height, input_width = frame.shape[:2] internal_resolution = config.get("internal_resolution", 0.5) target_height, target_width = to_input_resolution_height_and_width( internal_resolution, output_stride, input_height, input_width) padT, padB, padL, padR = calc_padding(frame, target_height, target_width) resized_frame = tf.image.resize_with_pad( frame, target_height, target_width, method=tf.image.ResizeMethod.BILINEAR) resized_height, resized_width = resized_frame.shape[:2] # Preprocessing if model_type == "mobilenet": resized_frame = np.divide(resized_frame, 127.5) resized_frame = np.subtract(resized_frame, 1.0) elif model_type == "resnet50": m = np.array([-123.15, -115.90, -103.06]) resized_frame = np.add(resized_frame, m) else: assert (False) sample_image = resized_frame[tf.newaxis, ...] results = sess.run(output_tensor_names, feed_dict={input_tensor: sample_image}) if model_type == "mobilenet": segment_logits = results[1] part_heatmaps = results[2] heatmaps = results[4] else: segment_logits = results[6] part_heatmaps = results[5] heatmaps = results[2] scaled_segment_scores = scale_and_crop_to_input_tensor_shape( segment_logits, input_height, input_width, padT, padB, padL, padR, True) scaled_part_heatmap_scores = scale_and_crop_to_input_tensor_shape( part_heatmaps, input_height, input_width, padT, padB, padL, padR, True) scaled_heatmap_scores = scale_and_crop_to_input_tensor_shape( heatmaps, input_height, input_width, padT, padB, padL, padR, True) mask = to_mask_tensor(scaled_segment_scores, config.get("segmentation_threshold", 0.75)) mask = np.reshape(mask, mask.shape[:2]) part_masks = to_mask_tensor(scaled_part_heatmap_scores, 0.999) part_masks = np.array(part_masks) heatmap_masks = to_mask_tensor(scaled_heatmap_scores, 0.99) heatmap_masks = np.array(heatmap_masks) # Average over the last N masks to reduce flickering # (at the cost of seeing afterimages) num_average_masks = max(1, config.get("average_masks", 3)) masks.insert(0, mask) masks = masks[:num_average_masks] mask = np.mean(masks, axis=0) mask = (mask * 255).astype(np.uint8) dilate_value = config.get("dilate", 0) erode_value = config.get("erode", 0) blur_value = config.get("blur", 0) if dilate_value: mask = cv2.dilate(mask, np.ones((dilate_value, dilate_value), np.uint8), iterations=1) if erode_value: mask = cv2.erode(mask, np.ones((erode_value, erode_value), np.uint8), iterations=1) if blur_value: mask = cv2.blur(mask, (blur_value, blur_value)) frame = np.append(frame, np.expand_dims(mask, axis=2), axis=2) input_frame = frame.copy() frame = np.zeros(input_frame.shape) for layer_type, layer_filters in layers: # Initialize the layer frame layer_frame = np.zeros(frame.shape) # transparent black if layer_type == "foreground": layer_frame = input_frame.copy() elif layer_type == "input": layer_frame = input_frame.copy() # make the frame opaque layer_frame[:, :, 3] = 255 * np.ones(input_frame.shape[:2]) elif layer_type == "previous": layer_frame = frame.copy() # make the frame opaque layer_frame[:, :, 3] = 255 * np.ones(input_frame.shape[:2]) elif layer_type == "empty": pass layer_frame = filters.apply_filters(layer_frame, mask, part_masks, heatmap_masks, layer_filters) if layer_frame.shape[2] == 4: transparency = layer_frame[:, :, 3] / 255.0 transparency = np.expand_dims(transparency, axis=2) frame[:,:,:3] = frame[:,:,:3] * \ (1.0 - transparency) + layer_frame[:,:,:3] * transparency else: frame[:, :, :3] = layer_frame[:, :, :3].copy() # Remove alpha channel frame = frame[:, :, :3] if config.get("debug_show_mask") is not None: mask_id = int(config.get("debug_show_mask", None)) if mask_id > -1 and mask_id < 24: mask = part_masks[:, :, mask_id] * 255.0 frame[:, :, 0] = mask frame[:, :, 1] = mask frame[:, :, 2] = mask elif config.get("debug_show_heatmap") is not None: heatmap_id = int(config.get("debug_show_heatmap", None)) if heatmap_id > -1 and heatmap_id < 17: mask = heatmap_masks[:, :, heatmap_id] * 255.0 frame[:, :, 0] = mask frame[:, :, 1] = mask frame[:, :, 2] = mask frame = frame.astype(np.uint8) fakewebcam.schedule_frame(frame)
def mainloop(): global config, masks, replacement_bgs, overlays config = load_config(config) success, frame = cap.read() if not success: print("Error getting a webcam image!") sys.exit(1) if config.get("flip_horizontal"): frame = cv2.flip(frame, 1) if config.get("flip_vertical"): frame = cv2.flip(frame, 0) image_filters = get_imagefilters(config.get("background_filters", [])) image_name = config.get("background_image", "background.jpg") replacement_bgs = load_images(replacement_bgs, image_name, height, width, "replacement_bgs", config.get("background_interpolation_method"), image_filters) frame = frame[...,::-1] if replacement_bgs is None: if len(image_filters) == 0: fakewebcam.schedule_frame(frame) return replacement_bg = np.copy(frame) for image_filter in image_filters: try: replacement_bg = image_filter(replacement_bg) except TypeError: # caused by a wrong number of arguments in the config pass replacement_bgs = [replacement_bg] input_height, input_width = frame.shape[:2] target_height, target_width = to_input_resolution_height_and_width( internal_resolution, output_stride, input_height, input_width) padT, padB, padL, padR = calc_padding(frame, target_height, target_width) resized_frame = tf.image.resize_with_pad(frame, target_height, target_width, method=tf.image.ResizeMethod.BILINEAR) resized_height, resized_width = resized_frame.shape[:2] # Preprocessing for resnet #m = np.array([-123.15, -115.90, -103.06]) #resized_frame = np.add(resized_frame, m) # Preprocessing for mobilenet resized_frame = np.divide(resized_frame, 127.5) resized_frame = np.subtract(resized_frame, 1.0) sample_image = resized_frame[tf.newaxis, ...] results = sess.run(output_tensor_names, feed_dict={input_tensor: sample_image}) segments = np.squeeze(results[1], 0) segment_logits = results[1] scaled_segment_scores = scale_and_crop_to_input_tensor_shape( segment_logits, input_height, input_width, padT, padB, padL, padR, True ) mask = to_mask_tensor(scaled_segment_scores, config["segmentation_threshold"]) mask = tf.dtypes.cast(mask, tf.int32) mask = np.reshape(mask, mask.shape[:2]) # Average over the last N masks to reduce flickering # (at the cost of seeing afterimages) masks.insert(0, mask) num_average_masks = max(1, config.get("average_masks", 3)) masks = masks[:num_average_masks] mask = np.mean(masks, axis=0) mask *= 255 if config["dilate"]: mask = cv2.dilate(mask, np.ones((config["dilate"], config["dilate"]), np.uint8), iterations=1) if config["erode"]: mask = cv2.erode(mask, np.ones((config["erode"], config["erode"]), np.uint8), iterations=1) if config["blur"]: mask = cv2.blur(mask, (config["blur"], config["blur"])) mask /= 255. mask_inv = 1.0 - mask # Filter the foreground image_filters = get_imagefilters(config.get("foreground_filters", [])) for image_filter in image_filters: try: frame = image_filter(frame) except TypeError: # caused by a wrong number of arguments in the config pass replacement_bgs_idx = config.get("replacement_bgs_idx", 0) for c in range(3): frame[:,:,c] = frame[:,:,c] * mask + \ replacement_bgs[replacement_bgs_idx][:,:,c] * mask_inv if time.time() - config.get("last_frame_bg", 0) > 1.0 / config.get("background_fps", 1): config["replacement_bgs_idx"] = (replacement_bgs_idx + 1) % len(replacement_bgs) config["last_frame_bg"] = time.time() # Filter the result image_filters = get_imagefilters(config.get("result_filters", [])) for image_filter in image_filters: try: frame = image_filter(frame) except TypeError: # caused by a wrong number of arguments in the config pass overlays_idx = config.get("overlays_idx", 0) overlays = load_images(overlays, config.get("overlay_image", ""), height, width, "overlays", get_imagefilters(config.get("overlay_filters", []))) if overlays: overlay = overlays[overlays_idx] assert(overlay.shape[2] == 4) # The image has an alpha channel for c in range(3): frame[:,:,c] = frame[:,:,c] * (1.0 - overlay[:,:,3] / 255.0) + \ overlay[:,:,c] * (overlay[:,:,3] / 255.0) if time.time() - config.get("last_frame_overlay", 0) > 1.0 / config.get("overlay_fps", 1): config["overlays_idx"] = (overlays_idx + 1) % len(overlays) config["last_frame_overlay"] = time.time() if config.get("debug_show_mask", False): frame[:,:,0] = mask * 255 frame[:,:,1] = mask * 255 frame[:,:,2] = mask * 255 fakewebcam.schedule_frame(frame) last_frame_time = time.time()