code: import numpy as np
  import sys
  import os
  import fnmatch
  import argparse
  
  try:
      import cv2 as cv
  except ImportError:
      raise ImportError('Can\'t find OpenCV Python module. If you\'ve built it from sources without installation, '
                        'configure environment variable PYTHONPATH to "opencv_build_dir/lib" directory (with "python3" subdirectory if required)')
  try:
      import torch
  except ImportError:
      raise ImportError('Can\'t find pytorch. Please install it by following instructions on the official site')
  
  from torch.utils.serialization import load_lua
  from pascal_semsegm_test_fcn import eval_segm_result, get_conf_mat, get_metrics, DatasetImageFetch, SemSegmEvaluation
  from imagenet_cls_test_alexnet import Framework, DnnCaffeModel
  
  
  class NormalizePreproc:
      def __init__(self):
          pass
  
      @staticmethod
      def process(img):
          image_data = np.array(img).transpose(2, 0, 1).astype(np.float32)
          image_data = np.expand_dims(image_data, 0)
          image_data /= 255.0
          return image_data
  
  
  class CityscapesDataFetch(DatasetImageFetch):
      img_dir = ''
      segm_dir = ''
      segm_files = []
      colors = []
      i = 0
  
      def __init__(self, img_dir, segm_dir, preproc):
          self.img_dir = img_dir
          self.segm_dir = segm_dir
          self.segm_files = sorted([img for img in self.locate('*_color.png', segm_dir)])
          self.colors = self.get_colors()
          self.data_prepoc = preproc
          self.i = 0
  
      @staticmethod
      def get_colors():
          result = []
          colors_list = (
           (0, 0, 0), (128, 64, 128), (244, 35, 232), (70, 70, 70), (102, 102, 156), (190, 153, 153), (153, 153, 153),
           (250, 170, 30), (220, 220, 0), (107, 142, 35), (152, 251, 152), (70, 130, 180), (220, 20, 60), (255, 0, 0),
           (0, 0, 142), (0, 0, 70), (0, 60, 100), (0, 80, 100), (0, 0, 230), (119, 11, 32))
  
          for c in colors_list:
              result.append(DatasetImageFetch.pix_to_c(c))
          return result
  
      def __iter__(self):
          return self
  
      def next(self):
          if self.i < len(self.segm_files):
              segm_file = self.segm_files[self.i]
              segm = cv.imread(segm_file, cv.IMREAD_COLOR)[:, :, ::-1]
              segm = cv.resize(segm, (1024, 512), interpolation=cv.INTER_NEAREST)
  
              img_file = self.rreplace(self.img_dir + segm_file[len(self.segm_dir):], 'gtFine_color', 'leftImg8bit')
              assert os.path.exists(img_file)
              img = cv.imread(img_file, cv.IMREAD_COLOR)[:, :, ::-1]
              img = cv.resize(img, (1024, 512))
  
              self.i += 1
              gt = self.color_to_gt(segm, self.colors)
              img = self.data_prepoc.process(img)
              return img, gt
          else:
              self.i = 0
              raise StopIteration
  
      def get_num_classes(self):
          return len(self.colors)
  
      @staticmethod
      def locate(pattern, root_path):
          for path, dirs, files in os.walk(os.path.abspath(root_path)):
              for filename in fnmatch.filter(files, pattern):
                  yield os.path.join(path, filename)
  
      @staticmethod
      def rreplace(s, old, new, occurrence=1):
          li = s.rsplit(old, occurrence)
          return new.join(li)
  
  
  class TorchModel(Framework):
      net = object
  
      def __init__(self, model_file):
          self.net = load_lua(model_file)
  
      def get_name(self):
          return 'Torch'
  
      def get_output(self, input_blob):
          tensor = torch.FloatTensor(input_blob)
          out = self.net.forward(tensor).numpy()
          return out
  
  
  class DnnTorchModel(DnnCaffeModel):
      net = cv.dnn.Net()
  
      def __init__(self, model_file):
          self.net = cv.dnn.readNetFromTorch(model_file)
  
      def get_output(self, input_blob):
          self.net.setBlob("", input_blob)
          self.net.forward()
          return self.net.getBlob(self.net.getLayerNames()[-1])
  
  if __name__ == "__main__":
      parser = argparse.ArgumentParser()
      parser.add_argument("--imgs_dir", help="path to Cityscapes validation images dir, imgsfine/leftImg8bit/val")
      parser.add_argument("--segm_dir", help="path to Cityscapes dir with segmentation, gtfine/gtFine/val")
      parser.add_argument("--model", help="path to torch model, download it here: "
                          "https://www.dropbox.com/sh/dywzk3gyb12hpe5/AAD5YkUa8XgMpHs2gCRgmCVCa")
      parser.add_argument("--log", help="path to logging file")
      args = parser.parse_args()
  
      prep = NormalizePreproc()
      df = CityscapesDataFetch(args.imgs_dir, args.segm_dir, prep)
  
      fw = [TorchModel(args.model),
            DnnTorchModel(args.model)]
  
      segm_eval = SemSegmEvaluation(args.log)
      segm_eval.process(fw, df)
   
  import cv2 as cv
  import numpy as np
  import argparse
  
  W = 52          # window size is WxW
  C_Thr = 0.43    # threshold for coherency
  LowThr = 35     # threshold1 for orientation, it ranges from 0 to 180
  HighThr = 57    # threshold2 for orientation, it ranges from 0 to 180
  
  ## [calcGST]
  ## [calcJ_header]
  ## [calcGST_proto]
  def calcGST(inputIMG, w):
  ## [calcGST_proto]
      img = inputIMG.astype(np.float32)
  
      # GST components calculation (start)
      # J =  (J11 J12; J12 J22) - GST
      imgDiffX = cv.Sobel(img, cv.CV_32F, 1, 0, 3)
      imgDiffY = cv.Sobel(img, cv.CV_32F, 0, 1, 3)
      imgDiffXY = cv.multiply(imgDiffX, imgDiffY)
      ## [calcJ_header]
  
      imgDiffXX = cv.multiply(imgDiffX, imgDiffX)
      imgDiffYY = cv.multiply(imgDiffY, imgDiffY)
  
      J11 = cv.boxFilter(imgDiffXX, cv.CV_32F, (w,w))
      J22 = cv.boxFilter(imgDiffYY, cv.CV_32F, (w,w))
      J12 = cv.boxFilter(imgDiffXY, cv.CV_32F, (w,w))
      # GST components calculations (stop)
  
      # eigenvalue calculation (start)
      # lambda1 = 0.5*(J11 + J22 + sqrt((J11-J22)^2 + 4*J12^2))
      # lambda2 = 0.5*(J11 + J22 - sqrt((J11-J22)^2 + 4*J12^2))
      tmp1 = J11 + J22
      tmp2 = J11 - J22
      tmp2 = cv.multiply(tmp2, tmp2)
      tmp3 = cv.multiply(J12, J12)
      tmp4 = np.sqrt(tmp2 + 4.0 * tmp3)
  
      lambda1 = 0.5*(tmp1 + tmp4)    # biggest eigenvalue
      lambda2 = 0.5*(tmp1 - tmp4)    # smallest eigenvalue
      # eigenvalue calculation (stop)
  
      # Coherency calculation (start)
      # Coherency = (lambda1 - lambda2)/(lambda1 + lambda2)) - measure of anisotropism
      # Coherency is anisotropy degree (consistency of local orientation)
      imgCoherencyOut = cv.divide(lambda1 - lambda2, lambda1 + lambda2)
      # Coherency calculation (stop)
  
      # orientation angle calculation (start)
      # tan(2*Alpha) = 2*J12/(J22 - J11)
      # Alpha = 0.5 atan2(2*J12/(J22 - J11))
      imgOrientationOut = cv.phase(J22 - J11, 2.0 * J12, angleInDegrees = True)
      imgOrientationOut = 0.5 * imgOrientationOut
      # orientation angle calculation (stop)
  
      return imgCoherencyOut, imgOrientationOut
  ## [calcGST]
  
  parser = argparse.ArgumentParser(description='Code for Anisotropic image segmentation tutorial.')
  parser.add_argument('-i', '--input', help='Path to input image.', required=True)
  args = parser.parse_args()
  
  imgIn = cv.imread(args.input, cv.IMREAD_GRAYSCALE)
  if imgIn is None:
      print('Could not open or find the image: {}'.format(args.input))
      exit(0)
  
  ## [main_extra]
  ## [main]
  imgCoherency, imgOrientation = calcGST(imgIn, W)
  
  ## [thresholding]
  _, imgCoherencyBin = cv.threshold(imgCoherency, C_Thr, 255, cv.THRESH_BINARY)
  _, imgOrientationBin = cv.threshold(imgOrientation, LowThr, HighThr, cv.THRESH_BINARY)
  ## [thresholding]
  
  ## [combining]
  imgBin = cv.bitwise_and(imgCoherencyBin, imgOrientationBin)
  ## [combining]
  ## [main]
  
  imgCoherency = cv.normalize(imgCoherency, None, alpha=0, beta=1, norm_type=cv.NORM_MINMAX, dtype=cv.CV_32F)
  imgOrientation = cv.normalize(imgOrientation, None, alpha=0, beta=1, norm_type=cv.NORM_MINMAX, dtype=cv.CV_32F)
  
  cv.imshow('result.jpg', np.uint8(0.5*(imgIn + imgBin)))
  cv.imshow('Coherency.jpg', imgCoherency)
  cv.imshow('Orientation.jpg', imgOrientation)
  cv.waitKey(0)
  ## [main_extra]
  
apis: numpy.array torch.utils.serialization.load_lua numpy.expand_dims torch.FloatTensor
apis: numpy.sqrt numpy.uint8