metrics.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. #
  2. # Copyright (C) 2023, Inria
  3. # GRAPHDECO research group, https://team.inria.fr/graphdeco
  4. # All rights reserved.
  5. #
  6. # This software is free for non-commercial, research and evaluation use
  7. # under the terms of the LICENSE.md file.
  8. #
  9. # For inquiries contact george.drettakis@inria.fr
  10. #
  11. from pathlib import Path
  12. import os
  13. from PIL import Image
  14. import torch
  15. import torchvision.transforms.functional as tf
  16. from utils.loss_utils import ssim
  17. from lpipsPyTorch import lpips
  18. import json
  19. from tqdm import tqdm
  20. from utils.image_utils import psnr
  21. from argparse import ArgumentParser
  22. def readImages(renders_dir, gt_dir):
  23. renders = []
  24. gts = []
  25. image_names = []
  26. for fname in os.listdir(renders_dir):
  27. render = Image.open(renders_dir / fname)
  28. gt = Image.open(gt_dir / fname)
  29. renders.append(tf.to_tensor(render).unsqueeze(0)[:, :3, :, :].cuda())
  30. gts.append(tf.to_tensor(gt).unsqueeze(0)[:, :3, :, :].cuda())
  31. image_names.append(fname)
  32. return renders, gts, image_names
  33. def evaluate(model_paths):
  34. full_dict = {}
  35. per_view_dict = {}
  36. full_dict_polytopeonly = {}
  37. per_view_dict_polytopeonly = {}
  38. print("")
  39. for scene_dir in model_paths:
  40. try:
  41. print("Scene:", scene_dir)
  42. full_dict[scene_dir] = {}
  43. per_view_dict[scene_dir] = {}
  44. full_dict_polytopeonly[scene_dir] = {}
  45. per_view_dict_polytopeonly[scene_dir] = {}
  46. test_dir = Path(scene_dir) / "test"
  47. for method in os.listdir(test_dir):
  48. print("Method:", method)
  49. full_dict[scene_dir][method] = {}
  50. per_view_dict[scene_dir][method] = {}
  51. full_dict_polytopeonly[scene_dir][method] = {}
  52. per_view_dict_polytopeonly[scene_dir][method] = {}
  53. method_dir = test_dir / method
  54. gt_dir = method_dir/ "gt"
  55. renders_dir = method_dir / "renders"
  56. renders, gts, image_names = readImages(renders_dir, gt_dir)
  57. ssims = []
  58. psnrs = []
  59. lpipss = []
  60. for idx in tqdm(range(len(renders)), desc="Metric evaluation progress"):
  61. ssims.append(ssim(renders[idx], gts[idx]))
  62. psnrs.append(psnr(renders[idx], gts[idx]))
  63. lpipss.append(lpips(renders[idx], gts[idx], net_type='vgg'))
  64. print(" SSIM : {:>12.7f}".format(torch.tensor(ssims).mean(), ".5"))
  65. print(" PSNR : {:>12.7f}".format(torch.tensor(psnrs).mean(), ".5"))
  66. print(" LPIPS: {:>12.7f}".format(torch.tensor(lpipss).mean(), ".5"))
  67. print("")
  68. full_dict[scene_dir][method].update({"SSIM": torch.tensor(ssims).mean().item(),
  69. "PSNR": torch.tensor(psnrs).mean().item(),
  70. "LPIPS": torch.tensor(lpipss).mean().item()})
  71. per_view_dict[scene_dir][method].update({"SSIM": {name: ssim for ssim, name in zip(torch.tensor(ssims).tolist(), image_names)},
  72. "PSNR": {name: psnr for psnr, name in zip(torch.tensor(psnrs).tolist(), image_names)},
  73. "LPIPS": {name: lp for lp, name in zip(torch.tensor(lpipss).tolist(), image_names)}})
  74. with open(scene_dir + "/results.json", 'w') as fp:
  75. json.dump(full_dict[scene_dir], fp, indent=True)
  76. with open(scene_dir + "/per_view.json", 'w') as fp:
  77. json.dump(per_view_dict[scene_dir], fp, indent=True)
  78. except:
  79. print("Unable to compute metrics for model", scene_dir)
  80. if __name__ == "__main__":
  81. device = torch.device("cuda:0")
  82. torch.cuda.set_device(device)
  83. # Set up command line argument parser
  84. parser = ArgumentParser(description="Training script parameters")
  85. parser.add_argument('--model_paths', '-m', required=True, nargs="+", type=str, default=[])
  86. args = parser.parse_args()
  87. evaluate(args.model_paths)