|
import cv2 |
|
from cv2 import imread |
|
import numpy as np |
|
from numpy import unique, load |
|
import argparse |
|
import os, os.path as osp |
|
import tqdm |
|
import pdb |
|
|
|
def parse_args(): |
|
parser = argparse.ArgumentParser() |
|
parser.add_argument('--root', type=str, required=True, help='root dir of one identity') |
|
parser.add_argument('--cam_file', type=str, default='camera.npz') |
|
|
|
parser.add_argument('--depth_dir', help='depth map path', default='depth', type=str) |
|
parser.add_argument('--out_dir', '-n', help='outputnormal path', default='normal_depth', type=str) |
|
parser.add_argument('--mask_dir', help='mask path', default='masks', type=str) |
|
parser.add_argument('--mask_total_dir', help='total mask path', default='masks_total', type=str) |
|
args = parser.parse_args() |
|
return args |
|
|
|
def get_surface_normal_by_depth(depth, fx, fy): |
|
""" |
|
depth: (h, w) of float, the unit of depth is meter |
|
K: (3, 3) of float, the depth camere's intrinsic |
|
""" |
|
|
|
dz_dv, dz_du = np.gradient(depth) |
|
|
|
|
|
|
|
|
|
du_dx = fx / depth |
|
dv_dy = fy / depth |
|
|
|
dz_dx = dz_du * du_dx |
|
dz_dy = dz_dv * dv_dy |
|
|
|
normal_cross = np.dstack((-dz_dx, -dz_dy, np.ones_like(depth))) |
|
|
|
normal_unit = normal_cross / np.linalg.norm(normal_cross, axis=2, keepdims=True) |
|
|
|
|
|
nan_mask = np.isfinite(normal_unit).all(2) |
|
normal_unit[~np.isfinite(normal_unit).all(2)] = [-1, -1, -1] |
|
return normal_unit, nan_mask |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def denoise(img): |
|
|
|
kernel = np.ones((11, 11), np.uint8) |
|
img= cv2.erode(img, kernel, iterations=2) |
|
img= cv2.dilate(img, kernel, iterations=2) |
|
|
|
return img |
|
|
|
def main(): |
|
args = parse_args() |
|
root = args.root |
|
cam_file = osp.join(root, args.cam_file) |
|
depth_dir = osp.join(root, args.depth_dir) |
|
out_dir = osp.join(root, args.out_dir) |
|
os.makedirs(out_dir, exist_ok=True) |
|
mask_dir = osp.join(root, args.mask_dir) |
|
mask_total_dir = osp.join(root, args.mask_total_dir) |
|
os.makedirs(mask_total_dir, exist_ok=True) |
|
|
|
cam = np.load(cam_file) |
|
fx, fy = cam['fx'], cam['fy'] |
|
|
|
assert osp.exists(depth_dir), 'depth dir not exists' |
|
|
|
depth_paths = sorted([ |
|
osp.join(depth_dir, f) for f in os.listdir(depth_dir)]) |
|
mask_paths = sorted([osp.join(mask_dir, f) for f in os.listdir(mask_dir)]) |
|
|
|
|
|
assert depth_paths[0].endswith('.npy'), 'depth dir must be .npy' |
|
|
|
|
|
vis_normal = lambda normal: np.uint8((normal + 1) / 2 * 255)[..., ::-1] |
|
for idx, depth_p in enumerate(depth_paths): |
|
|
|
|
|
mask = cv2.imread(mask_paths[idx], -1)[..., 0] / 255 |
|
assert len(mask.shape) == 2, 'dims of mask are not 2' |
|
|
|
depth = np.load(depth_p) |
|
|
|
normal, nan_mask = get_surface_normal_by_depth(depth, fx, fy) |
|
mask_total = nan_mask * mask |
|
|
|
|
|
normal = vis_normal(normal) * mask_total[..., None] |
|
|
|
cv2.imwrite(osp.join(out_dir, f'{idx:05d}.png'), normal) |
|
cv2.imwrite(osp.join(mask_total_dir, f'{idx:05d}.png'), mask_total.astype(np.uint8) * 255) |
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__': |
|
|
|
main() |
|
''' if args.totalmaskPath: |
|
os.makedirs(args.totalmaskPath, exist_ok = True) |
|
for img_name in tqdm.tqdm(sorted(os.listdir(args.depthPath))): |
|
img_path = os.path.join(args.depthPath, img_name) |
|
depth = cv2.imread(img_path, -1) / 1000.0 |
|
normal, nan_mask = get_surface_normal_by_depth(depth) |
|
|
|
vis_normal = lambda normal: np.uint8((normal + 1) / 2 * 255)[..., ::-1] |
|
normal = vis_normal(normal) |
|
if args.maskPath: |
|
mask_path = os.path.join(args.maskPath, img_name[:-4] + '_mask' + img_name[-4:]) |
|
mask = cv2.imread(mask_path) |
|
mask = cv2.rotate(mask, cv2.ROTATE_90_CLOCKWISE) |
|
total_mask = mask[..., 0] * nan_mask |
|
# cv2.imwrite(os.path.join(args.totalmaskPath, img_name), np.uint8(nan_mask*255)) |
|
# cv2.imwrite(os.path.join(args.totalmaskPath, img_name), total_mask) |
|
kernel = np.ones((11, 11), np.uint8) |
|
total_mask = cv2.erode(total_mask, kernel, iterations=1) |
|
total_mask = cv2.dilate(total_mask, kernel, iterations=1) |
|
# pdb.set_trace() |
|
normal = np.uint8(total_mask[..., None]/255) * normal |
|
|
|
if args.totalmaskPath: |
|
# cv2.imwrite(os.path.join(args.totalmaskPath, img_name), delete_holes(total_mask)) |
|
total_mask = cv2.rotate(total_mask, cv2.ROTATE_90_COUNTERCLOCKWISE) |
|
cv2.imwrite(os.path.join(args.totalmaskPath, img_name), total_mask) |
|
# pdb.set_trace() |
|
|
|
normal_path = os.path.join(args.normalPath, img_name) |
|
normal = cv2.rotate(normal, cv2.ROTATE_90_COUNTERCLOCKWISE) |
|
cv2.imwrite(normal_path, normal) |
|
|
|
''' |
|
|
|
|