text: import os
  import copy
  from argparse import ArgumentParser
  import glob
  import cv2
  import numpy as np
  import torch
  
  from PIL import Image
  from torchvision import transforms
  import dataset_classifier
  import dataset_classifier_id
  
  from Unet import Unet
  from classifier import Resnet
  from classifier_id import Resnet as Resnet_id
  from corners_to_crop import crop_to_corners
  from dataset import DirDataset
  
  from torchvision import datasets, models, transforms
  
  
  from scipy.spatial import distance as dist
  from scipy import stats
  
  
  import torch
  
  
  
  import operator
  import math
  from functools import reduce
  
  
  cv_time_wait = 1
  def nonzero_mode(arr):
      return stats.mode(arr[np.nonzero(arr)]).mode
  
  from scipy.spatial import distance as dist
  import numpy as np
  import cv2
  
  inf_ind = 0
  def order_points(pts):
  	coords = pts
  	center = tuple(map(operator.truediv, reduce(lambda x, y: map(operator.add, x, y), coords), [len(coords)] * 2))
  	out = sorted(coords, key=lambda coord: (-135 - math.degrees(math.atan2(*tuple(map(operator.sub, coord, center))[::-1]))) % 360)
  	return np.array(out, dtype="float32")
  
  
  def reduce_to_tags(net, net_id, img, response_1, response_2,homography_mat, filename, hparams):
      global inf_ind
      device = 'cuda' if torch.cuda.is_available() else 'cpu'
  
      filename = filename.split('/')[-1]
  
      mask_segmentation = response_1
      mask_corners = response_2
      segregates = []
      print(mask_corners.max())
      cv2.waitKey(cv_time_wait)
      mask_corners =  (mask_corners>0.25).astype(np.uint8)
      print(mask_corners.shape)
  
      kernel = np.ones((5,5),np.uint8)
      mask_segmentation = cv2.erode(mask_segmentation,kernel,iterations = 2)
  
  
      cv2.namedWindow('mask_segmentation', cv2.WINDOW_NORMAL)
      cv2.imshow("mask_segmentation", mask_segmentation*255)
      cv2.waitKey(cv_time_wait)
  
      mask_real_corners = np.zeros(mask_corners.shape[1:], dtype=np.uint8)
  
      mask_real_corners = (mask_corners!=0).astype(np.uint8)
      print(mask_real_corners)
      print(mask_real_corners.shape)
  
      cv2.namedWindow('mask_garbage', cv2.WINDOW_NORMAL)
      cv2.imshow("mask_garbage", mask_real_corners.astype(np.float32)*60)
      cv2.waitKey(cv_time_wait)
  
      contours, _ = cv2.findContours(
          mask_segmentation, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
  
      temp_img = img.copy()
      coords = np.argwhere(mask_corners > 0)
  
      cv2.drawContours(temp_img, contours, -1, (0, 255, 0), 3)
  
      cv2.namedWindow('contours_img', cv2.WINDOW_NORMAL)
      cv2.imshow("contours_img", temp_img)
      cv2.waitKey(cv_time_wait)
      index = 0
  
      dictionary = cv2.aruco.Dictionary_get(cv2.aruco.DICT_APRILTAG_36h11)
  
      # Initialize the detector parameters using default values
      parameters =  cv2.aruco.DetectorParameters_create()
      parameters.cornerRefinementMethod = cv2.aruco.CORNER_REFINE_APRILTAG
      # parameters.maxErroneousBitsInBorderRate = 0.8
      # parameters.errorCorrectionRate = 0.8
      # parameters.aprilTagMaxLineFitMse = 100
      # parameters.perspectiveRemoveIgnoredMarginPerCell = 0.43
      # parameters.perspectiveRemovePixelPerCell = 10
  
  
      markerCorners, markerIds, rejectedCandidates = cv2.aruco.detectMarkers(img, dictionary, parameters=parameters)
  
      with open("./data_out/file_classic_count.txt", "a") as diff_file:
  
          diff_file.write(str(len(markerIds))+"\n")
      # img_make_clone = img.copy()
      # cv2.aruco.drawDetectedMarkers(img_make_clone, markerCorners, markerIds);
  
      # cv2.namedWindow('drawDetectedMarkers', cv2.WINDOW_NORMAL)
      # cv2.imshow('drawDetectedMarkers', img_make_clone)
      # cv2.waitKey(cv_time_wait)
  
      # gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
  
      # # find Harris corners
      # gray = np.float32(gray)
      # dst = cv2.cornerHarris(gray,2,3,0.04)
      # # dst = cv2.dilate(dst,None)
      # ret, dst = cv2.threshold(dst,0.001*dst.max(),255,0)
      # dst = np.uint8(dst)
  
      # # find centroids
      # ret, labels, stats, centroids = cv2.connectedComponentsWithStats(dst)
  
      # # define the criteria to stop and refine the corners
      # criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 200, 0.0001)
      # corners = cv2.cornerSubPix(gray,np.float32(centroids),(5,5),(-1,-1),criteria)
  
      # # Now draw them
      # res = np.hstack((centroids,corners))
      # print(corners)
  
  
      for ind in range(len(contours)):
          segregates = []
          if cv2.contourArea(contours[ind]) <=50:
              continue
          internal_mask = np.zeros(mask_real_corners.shape, dtype=np.uint8)
  
  
          cv2.drawContours(internal_mask, contours, ind, 255, -1)
          kernel = np.ones((5,5),np.uint8)
          internal_mask = cv2.dilate(internal_mask,kernel,iterations = 4)
  
          # cv2.namedWindow('internal_mask', cv2.WINDOW_NORMAL)
          # cv2.imshow("internal_mask", internal_mask)
          # cv2.waitKey(cv_time_wait)
  
          internal_mask = cv2.bitwise_and(
              internal_mask, mask_real_corners.astype(np.uint8))
  
          internal_contours, _ = cv2.findContours(
              internal_mask, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
  
          for inner_ind in range(len(internal_contours)):
              internal_internal_mask = np.zeros(
                  mask_real_corners.shape, dtype=np.uint8)
              cv2.drawContours(internal_internal_mask,
                               internal_contours, inner_ind, 255, -1)
              internal_internal_mask = cv2.bitwise_and(
                  internal_internal_mask, mask_real_corners.astype(np.uint8))
  
              # cv2.namedWindow('internal_internal_mask', cv2.WINDOW_NORMAL)
              # cv2.imshow("internal_internal_mask", internal_internal_mask)
              # cv2.waitKey(cv_time_wait)
  
              mode = map(nonzero_mode, internal_internal_mask)
              #find the center of contours
              M = cv2.moments(internal_contours[inner_ind])
              cX = (M["m10"] / (M["m00"]+1e-18))
              cY = (M["m01"] / (M["m00"]+1e-18))
              segregates.append([cX, cY])
  
  
          _segregates  = []
  
          for x in segregates:
              if(x!=[0,0]):
                  _segregates.append((int(x[0]), int(x[1])))
          if len(_segregates) <=2:
              continue
  
          print(_segregates)
  
          hull = cv2.convexHull(np.array(_segregates))
          t_segregates = []
  
          epsilon = 0.05*cv2.arcLength(hull,True)
          hull = cv2.approxPolyDP(hull,epsilon,True)
          print(hull)
          print(segregates)
  
          for p in hull:
              for x in segregates:
                  if( (x[0]-p[0][0])**2 + (x[1] - p[0][1])**2<=10):
                      t_segregates.append(x);
  
          segregates = t_segregates
          print(segregates)
  
          # if len(segregates) < 4:
          #     continue
  
  
          segregates = order_points(segregates)
          # print(len(segregates))
          # if len(segregates) != 4:
          #     continue
  
          corner_list = []
          # print(segregates)
          for i in segregates:
              corner_list.append((i[0], i[1]))
  
          if len(corner_list) != 4:
              # cv2.waitKey(0)
              continue
  
  
  
          # real_corner_list = []
          # for corner in corner_list:
          #     min_dist = 10000000.0
          #     closest = []
          #     for inner_corner in corners:
          #         dist = (inner_corner[0] - corner[0])**2 + (inner_corner[1] - corner[1])**2
          #         dist = math.sqrt(dist);
          #         if(dist<min_dist):
          #             closest = inner_corner
          #             min_dist = dist;
          #     if(min_dist < 0):
          #         real_corner_list.append(closest);
          #     else:
          #         real_corner_list.append(corner);
          # subpix_corner_list = real_corner_list
  
  
  
          # res = np.int0(res)
          # # img[res[:,1],res[:,0]]=[0,250,255]
          # # img[res[:,3],res[:,2]] = [0,255,0]
          # img_clone = img.copy()
          # for corner in corner_list:
          #     img_clone[np.int(corner[1]),np.int(corner[0])] =[0,0,255]
  
          # cv2.namedWindow('subpixel5.png', cv2.WINDOW_NORMAL)
          # cv2.imshow('subpixel5.png',img_clone)
          # cv2.waitKey(cv_time_wait)
  
          # print(corner_list)
  
  
          # pad = 30
          # tag_size = 224
          # h, status = cv2.findHomography(
          #     np.array(corner_list), np.array([[pad, pad], [pad, tag_size-pad],[tag_size-pad, tag_size-pad],  [tag_size-pad, 0+pad]]))
          # # corner_list = np.array([[pad, pad], [pad, tag_size-pad],[tag_size-pad, tag_size-pad],  [tag_size-pad, 0+pad]])
  
          # height, width, channels = img.shape
  
          # im1Reg = cv2.warpPerspective(img, h, (tag_size, tag_size))
  
          # # cv2.namedWindow('unrotated_tag', cv2.WINDOW_NORMAL)
          # # cv2.imshow('unrotated_tag', im1Reg)
          # # cv2.waitKey(cv_time_wait)
  
          # # im1Reg = cv2.cvtColor(im1Reg, cv2.COLOR_BGR2GRAY)
          # # blur = cv2.GaussianBlur(im1Reg,(5,5),0)
          # # reg,im1Reg = cv2.threshold(blur,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
          # # kernel = np.array([[-1,-1,-1], [-1,9,-1], [-1,-1,-1]])
          # # im1Reg = cv2.filter2D(im1Reg, -1, kernel)
  
          # # cv2.namedWindow('threshold_tag', cv2.WINDOW_NORMAL)
          # # cv2.imshow('threshold_tag', im1Reg)
          # # cv2.waitKey(cv_time_wait)
  
          # im2Reg = Image.fromarray(im1Reg)
  
          # ds = dataset_classifier.DirDataset('', '')
          # im2Reg = (ds.preprocess(im2Reg))
          # out = net(im2Reg.unsqueeze(0).to(device))
          # print(out)
          # rotation = ((np.argmax(out.squeeze(0).cpu())+2)*-90).item()
          # print(rotation)
  
          # (h, w) = im1Reg.shape[:2]
  
          # # calculate the center of the image
          # center = (w / 2, h / 2)
          # scale = 1
  
          # M = cv2.getRotationMatrix2D(center, rotation, scale)
          # im3Reg = cv2.warpAffine(im1Reg, M, (h, w))
  
          # # cv2.namedWindow('rotated_tag', cv2.WINDOW_NORMAL)
          # # cv2.imshow('rotated_tag', im3Reg)
          # # cv2.waitKey(cv_time_wait)
  
          # im31Reg = Image.fromarray(im1Reg)
  
          # ds = dataset_classifier_id.DirDataset('', '')
          # im31Reg = (ds.preprocess(im31Reg))
          # out = net_id(im31Reg.unsqueeze(0).to(device))
  
          # glb_id = ((np.argmax(out.squeeze(0).cpu()))).item()
          # if(torch.softmax(out,dim = 1)[0][glb_id]<0.5):
          #     continue;
  
          # if( glb_id == 587):
          #     continue
          inf_ind+=1
          print(inf_ind)
          with open("./data_out/file_n.txt", "a") as diff_file:
  
              diff_file.write(str(inf_ind)+"\n")
  
          # cv2.putText(im3Reg, "id: "+str(glb_id), (tag_size//2-20, tag_size//2), cv2.FONT_HERSHEY_SIMPLEX, 1, (100,255,100), 2)
          # cv2.putText(im3Reg, "tag_used: "+str(inf_ind), (20, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255,0,255), 1)
  
          # im3Reg[pad,pad] = [0,255,255]
          # im3Reg[pad,tag_size-pad] = [0,255,255]
          # im3Reg[tag_size-pad,pad] = [0,255,255]
          # im3Reg[tag_size-pad,tag_size-pad] = [0,255,255]
  
          # cv2.namedWindow('Unet-prediction', cv2.WINDOW_NORMAL)
          # cv2.imshow('Unet-prediction', im3Reg)
          # cv2.waitKey(cv_time_wait)
  
  
  
  
  
          # markerCorners, markerIds, rejectedCandidates = cv2.aruco.detectMarkers(im1Reg, dictionary, parameters=parameters)
          # print(im1Reg)
          # print(im1Reg.max())
          # print(im1Reg.min())
  
          # print(markerCorners)
          # print(rejectedCandidates)
          # pad = pad
          if markerCorners is not None and markerIds is not None:
              for corners, id in zip(markerCorners, markerIds):
                  print(corners)
                  corner = corners[0]
                  print(corner)
  
  
                  corner_out = corner
  
                  print(corner_list)
                  print(corner_out)
                  real_corner_list = []
                  fake_corner_list = []
                  for corner in corner:
                      min_dist = 10.0
                      closest = []
                      for inner_corner in corner_list:
                          dist = (inner_corner[0] - corner[0])**2 + (inner_corner[1] - corner[1])**2
                          dist = math.sqrt(dist);
                          if(dist<min_dist):
                              closest = inner_corner
                              min_dist = dist;
  
                      if(closest != []):
                          real_corner_list.append(closest);
                          fake_corner_list.append(corner);
  
  
                  if len(real_corner_list) == 4:
                      print(real_corner_list, corner_out)
                      for p1,p2 in zip(real_corner_list, fake_corner_list  ):
                          with open("./data_out/data.txt", "a") as diff_file:
  
                              diff_file.write(str(p1[0])+","+str(p1[1]) + "," + str(p2[0]) + "," + str(p2[1]) + ","+ str(id)[1:-1]+"," + str(p2[0]-p1[0])+"," + str(p2[1]-p1[1]) +"\n")
                          x_diff = p1[0] - p2[0]
                          y_diff = p1[1] - p2[1]
                          with open("./data_out/diff_file_" + str(id) + ".csv", "a") as diff_file:
  
                              diff_file.write(str(p1[0])+","+str(p1[1]) + "," + str(p2[0]) + "," + str(p2[1]) + ","+ str(id)[1:-1]+"," + str(p2[0]-p1[0])+"," + str(p2[1]-p1[1]) +"\n")
  
                          with open("./data_out/img/" + filename + ".csv", "a") as diff_file:
  
                              diff_file.write(str(p1[0])+","+str(p1[1]) + "," + str(p2[0]) + "," + str(p2[1]) + ","+ str(id)[1:-1]+"," + str(p2[0]-p1[0])+"," + str(p2[1]-p1[1]) +"\n")
  
  
  
  
  
  
          # print(corner_list)
  
          # cv2.imwrite(os.path.join(args.out_folder, 'simg',
          #                          filename[:-4] + "_" + str(index) + '.jpg'), im1Reg)
  
  
          # print(f"{mask_corners[int(corner_list[0][1])][int(corner_list[0][0])]}")
          # with open(os.path.join(args.out_folder, 'simg',filename[:-4] + "_" + str(index) + '.txt'), "w") as text_file:
          #     print(f"{mask_corners[int(corner_list[0][1])][int(corner_list[0][0])]}", file=text_file)
  
          index = index + 1
  
  
  
  def predict(net, img, device='cuda', threshold=0.5, kernel = 768, stride =512):
      with torch.no_grad():
          ds = DirDataset('', '')
          _img = (ds.preprocess(img))
  
  
          # cv2.imshow("predict", _img.cpu().numpy().transpose((2, 1, 0)))
          # cv2.waitKey(cv_time_wait)
          _img = _img.unsqueeze(0)
          _img = _img.to(device=device, dtype=torch.float32)
  
          mask =  torch.zeros(_img.shape[2:], device = device, dtype = torch.float32)
          _mask =  torch.zeros(_img.shape[2:], device = device, dtype = torch.float32)
          rows,cols = _img.shape[2:]
  
          with torch.no_grad():
  
              for start_row in range(0,rows, stride):
                  for start_col in range(0,cols,stride):
  
                      patch = _img[:,:, start_row:start_row+kernel, start_col:start_col+kernel ]
                      o = net(patch)
  
                      _o = o[:, 1, :, :]
                      o = o[:, :1,:,:]
  
                      # probs = torch.nn.functional.softmax(o, dim=1)
                      print(o.shape)
                      probs = torch.sigmoid(o)
                      print(o.max())
                      print(probs.shape)
                      probs = probs.squeeze(0)
                      mask_patch = probs
  
                      _probs = torch.sigmoid(_o)
                      _probs = _probs.squeeze(0)
                      _mask_patch = _probs
  
                      mask[start_row:start_row+kernel, start_col:start_col+kernel] = torch.max(mask[start_row:start_row+kernel, start_col:start_col+kernel], mask_patch);
                      _mask[start_row:start_row+kernel, start_col:start_col+kernel] = torch.max(_mask[start_row:start_row+kernel, start_col:start_col+kernel], _mask_patch);
          return (mask.cpu().numpy(), _mask.cpu().numpy() > threshold )
  
  
  def mask_to_image(mask):
      return Image.fromarray(( mask ).astype(np.uint8))
  
  
  def main(hparams):
      board	=	cv2.aruco.GridBoard_create(	5, 5, 2.4, 1.2, cv2.aruco.getPredefinedDictionary(cv2.aruco.DICT_APRILTAG_36h11), 300)
      print(board)
      csv_file_name= hparams.csv
  
      counter = []
      img_list = [str(item) for item in glob.glob(hparams.csv)]
  
      corners_original = []
      corners_april = []
      corners_id = []
  
      corners_original_temp = []
      corners_april_temp = []
      corners_id_temp = None
      ind = 0
      for csv_file_name in img_list:
          with open(csv_file_name) as f:
              content = f.readlines()
          # you may also want to remove whitespace characters like `\n` at the end of each line
          content = [x.strip() for x in content]
          if(len(content) == 0):
              continue
  
  
          for line in content:
              data = line.split(",")
              corners_original_temp.append([int(float(data[0])), int(float(data[1]))])
              corners_april_temp.append([int(float(data[2])), int(float(data[3]))])
  
              corners_id_temp = int(data[4])
              ind+=1
              if(ind%4 == 0):
                  corners_april.append([copy.deepcopy(corners_april_temp)])
                  corners_original.append([copy.deepcopy(corners_original_temp)])
                  corners_id.append([copy.deepcopy(corners_id_temp)])
  
                  corners_original_temp = []
                  corners_april_temp = []
                  corners_id_temp = None
          counter.append(len(content)//4)
          if(ind>=4):
              break
  
      print(np.array(corners_april))
      print(np.array(corners_id))
      print(np.array(counter))
  
  
      retval, cameraMatrix_april, distCoeffs_april, rvecs, tvecs	=	cv2.aruco.calibrateCameraAruco(	np.array(corners_april), np.array(corners_id), np.array(counter), board, (2048//4, 2048//4), None,None)
  
      print(retval)
      print(cameraMatrix_april)
  if __name__ == '__main__':
      parent_parser = ArgumentParser(add_help = False)
      # parent_parser.add_argument('--fit_out_net', required=True, help = "Network for tag classification")
      parent_parser.add_argument('--csv', required=True, type = str)
  
      parser = Unet.add_model_specific_args(parent_parser)
      hparams = parser.parse_args()
  
      main(hparams)
  