code: def inference(net, img=None, device=None):
      """
  
      :param net:
      :return:
      """
      # adj
      adj2_ = torch.from_numpy(graph.cihp2pascal_nlp_adj).float()
      adj2_test = (
          adj2_.unsqueeze(0)
          .unsqueeze(0)
          .expand(1, 1, 7, 20)
          .to(device)
          .transpose(2, 3)
      )
  
      adj1_ = Variable(
          torch.from_numpy(
              graph.preprocess_adj(graph.pascal_graph)
          ).float()
      )
      adj3_test = (
          adj1_.unsqueeze(0).unsqueeze(0).expand(1, 1, 7, 7).to(device)
      )
  
      cihp_adj = graph.preprocess_adj(graph.cihp_graph)
      adj3_ = Variable(torch.from_numpy(cihp_adj).float())
      adj1_test = (
          adj3_.unsqueeze(0)
          .unsqueeze(0)
          .expand(1, 1, 20, 20)
          .to(device)
      )
  
      # multi-scale
      scale_list = [1, 0.5, 0.75, 1.25, 1.5, 1.75]
      # scale_list = [1, 0.5, 0.75, 1.25]
      # NOTE: this part of the code assumes img is PIL image in RGB color space
      # We provide torch tensor in range [-1, 1]
      # Bring range to [0, 255]
      img = torch.clamp(img, -1, 1)
      img = (img + 1.0) / 2.0
      img *= 255
  
      testloader_list = []
      testloader_flip_list = []
      for pv in scale_list:
          composed_transforms_ts = transforms.Compose(
              [
                  tr.Scale_only_img(pv),
                  tr.Normalize_xception_tf_only_img(),
                  tr.ToTensor_only_img(),
              ]
          )
  
          composed_transforms_ts_flip = transforms.Compose(
              [
                  tr.Scale_only_img(pv),
                  tr.HorizontalFlip_only_img(),
                  tr.Normalize_xception_tf_only_img(),
                  tr.ToTensor_only_img(),
              ]
          )
          # NOTE: img [1, 3, 256, 256], (min, max) = (0, 255)
  
          # print("original:", img.shape, img.min(), img.max())
          testloader_list.append(
              img_transform(img, composed_transforms_ts)
          )
          # print(img_transform(img, composed_transforms_ts))
          testloader_flip_list.append(
              img_transform(img, composed_transforms_ts_flip)
          )
      # print(testloader_list)
      start_time = timeit.default_timer()
      # One testing epoch
      # net.eval()
      # 1 0.5 0.75 1.25 1.5 1.75 ; flip:
  
      # NOTE: testloader_list[0]['image'].shape = 3, 420, 620
  
      for iii, sample_batched in enumerate(
          zip(testloader_list, testloader_flip_list)
      ):
          inputs, labels = (
              sample_batched[0]["image"],
              sample_batched[0]["label"],
          )
          inputs_f, _ = (
              sample_batched[1]["image"],
              sample_batched[1]["label"],
          )
          inputs = inputs.unsqueeze(0)
          inputs_f = inputs_f.unsqueeze(0)
          inputs = torch.cat((inputs, inputs_f), dim=0)
          if iii == 0:
              _, _, h, w = inputs.size()
          # assert inputs.size() == inputs_f.size()
  
          # Forward pass of the mini-batch
  
          # TODO: check requires grad functionality
          # inputs = Variable(inputs, requires_grad=False)
  
          with torch.no_grad():
              if device is not None:
                  inputs = inputs.to(device)
              # outputs = net.forward(inputs)
              outputs = net.forward(
                  inputs,
                  adj1_test.to(device),
                  adj3_test.to(device),
                  adj2_test.to(device),
              )
              outputs = (
                  outputs[0] + flip(flip_cihp(outputs[1]), dim=-1)
              ) / 2
              outputs = outputs.unsqueeze(0)
              if iii > 0:
                  outputs = F.upsample(
                      outputs,
                      size=(h, w),
                      mode="bilinear",
                      align_corners=True,
                  )
                  outputs_final = outputs_final + outputs
              else:
                  outputs_final = outputs.clone()
      ################ plot pic
      predictions = torch.max(outputs_final, 1)[1]
      # results = predictions.cpu().numpy()
      # vis_res = decode_labels(results)
      # parsing_im = Image.fromarray(vis_res[0])
      # return parsing_im
  
      hair_mask, face_mask = custom_decode_labels(predictions)
  
      return outputs_final, hair_mask, face_mask
  
file_path: insightface/reconstruction/ostec/external/graphonomy/FaceHairMask/graphonomy_inference.py
imports: import cv2
  import torch
  import timeit
  import numpy
  from PIL import Image
  import torch.nn.functional
  from torch.autograd import Variable
  from torchvision import transforms
  from FaceHairMask import graph
  from FaceHairMask import graphonomy_process
label_desc: Use image node_id 8 for calling a global function with example usage: inference(net, img, device) and returns: outputs_final,  hair_mask,  face_mask