utils.py 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. import torch
  2. import numpy as np
  3. import math
  4. import cv2
  5. import os
  6. import torchvision
  7. from PIL import Image
  8. from basic_ops import *
  9. def draw_line(y, x, angle, image, color=(0,0,255), num_directions=24):
  10. '''
  11. Draw a line with point y, x, angle in image with color.
  12. '''
  13. cv2.circle(image, (x, y), 2, color, 2)
  14. H, W = image.shape[:2]
  15. angle = int2arc(angle, num_directions)
  16. point1, point2 = get_boundary_point(y, x, angle, H, W)
  17. cv2.line(image, point1, point2, color, 2)
  18. return image
  19. def convert_line_to_hough(line, size=(32, 32)):
  20. H, W = size
  21. theta = line.angle()
  22. alpha = theta + np.pi / 2
  23. if theta == -np.pi / 2:
  24. r = line.coord[1] - W/2
  25. else:
  26. k = np.tan(theta)
  27. y1 = line.coord[0] - H/2
  28. x1 = line.coord[1] - W/2
  29. r = (y1 - k*x1) / np.sqrt(1 + k**2)
  30. return alpha, r
  31. def line2hough(line, numAngle, numRho, size=(32, 32)):
  32. H, W = size
  33. alpha, r = convert_line_to_hough(line, size)
  34. irho = int(np.sqrt(H*H + W*W) + 1) / ((numRho - 1))
  35. itheta = np.pi / numAngle
  36. r = int(np.round(r / irho)) + int((numRho) / 2)
  37. alpha = int(np.round(alpha / itheta))
  38. if alpha >= numAngle:
  39. alpha = numAngle - 1
  40. return alpha, r
  41. def line2hough_float(line, numAngle, numRho, size=(32, 32)):
  42. H, W = size
  43. alpha, r = convert_line_to_hough(line, size)
  44. irho = int(np.sqrt(H*H + W*W) + 1) / ((numRho - 1))
  45. itheta = np.pi / numAngle
  46. r = r / irho + numRho / 2
  47. alpha = alpha / itheta
  48. if alpha >= numAngle:
  49. alpha = numAngle - 1
  50. return alpha, r
  51. def reverse_mapping(point_list, numAngle, numRho, size=(32, 32)):
  52. #return type: [(y1, x1, y2, x2)]
  53. H, W = size
  54. irho = int(np.sqrt(H*H + W*W) + 1) / ((numRho - 1))
  55. itheta = np.pi / numAngle
  56. b_points = []
  57. for (thetai, ri) in point_list:
  58. theta = thetai * itheta
  59. r = ri - numRho // 2
  60. cosi = np.cos(theta) / irho
  61. sini = np.sin(theta) / irho
  62. if sini == 0:
  63. x = np.round(r / cosi + W / 2)
  64. b_points.append((0, int(x), H-1, int(x)))
  65. else:
  66. # print('k = %.4f', - cosi / sini)
  67. # print('b = %.2f', np.round(r / sini + W * cosi / sini / 2 + H / 2))
  68. angle = np.arctan(- cosi / sini)
  69. y = np.round(r / sini + W * cosi / sini / 2 + H / 2)
  70. p1, p2 = get_boundary_point(int(y), 0, angle, H, W)
  71. if p1 is not None and p2 is not None:
  72. b_points.append((p1[1], p1[0], p2[1], p2[0]))
  73. return b_points
  74. def visulize_mapping(b_points, size, filename):
  75. img = cv2.imread(os.path.join('./data/NKL', filename)) #change the path when using other dataset.
  76. img = cv2.resize(img, size)
  77. for (y1, x1, y2, x2) in b_points:
  78. img = cv2.line(img, (x1, y1), (x2, y2), (255, 255, 0), thickness=int(0.01*max(size[0], size[1])))
  79. return img
  80. def caculate_precision(b_points, gt_coords, thresh=0.90):
  81. N = len(b_points)
  82. if N == 0:
  83. return 0, 0
  84. ea = np.zeros(N, dtype=np.float32)
  85. for i, coord_p in enumerate(b_points):
  86. if coord_p[0]==coord_p[2] and coord_p[1]==coord_p[3]:
  87. continue
  88. l_pred = Line(list(coord_p))
  89. for coord_g in gt_coords:
  90. l_gt = Line(list(coord_g))
  91. ea[i] = max(ea[i], EA_metric(l_pred, l_gt))
  92. return (ea >= thresh).sum(), N
  93. def caculate_recall(b_points, gt_coords, thresh=0.90):
  94. N = len(gt_coords)
  95. if N == 0:
  96. return 1.0, 0
  97. ea = np.zeros(N, dtype=np.float32)
  98. for i, coord_g in enumerate(gt_coords):
  99. l_gt = Line(list(coord_g))
  100. for coord_p in b_points:
  101. if coord_p[0]==coord_p[2] and coord_p[1]==coord_p[3]:
  102. continue
  103. l_pred = Line(list(coord_p))
  104. ea[i] = max(ea[i], EA_metric(l_pred, l_gt))
  105. return (ea >= thresh).sum(), N
  106. def coords_sort(coords):
  107. y1, x1, y2, x2 = coords
  108. if x1 > x2 or (x1 == x2 and y1 > y2):
  109. yy1, xx1, yy2, xx2 = y2, x2, y1, x1
  110. else:
  111. yy1, xx1, yy2, xx2 = y1, x1, y2, x2
  112. return yy1, xx1, yy2, xx2
  113. def get_density(filename, x1, y1, x2, y2):
  114. hed_path = '/home/hanqi/JTLEE_code/pytorch-hed/hed_results/'
  115. filename = filename.split('_')[0]
  116. hed_file_path = os.path.join(hed_path, filename + '.png')
  117. hed = np.array(Image.open(hed_file_path).convert('L')) / 255
  118. mask = np.zeros_like(hed)
  119. mask = cv2.line(mask, (x1, y1), (x2, y2), color=1.0, thickness=7)
  120. density = (mask * hed).sum() / mask.sum()
  121. return density
  122. def local_search(coords, coords_ring, d=1):
  123. y1, x1 = coords
  124. length = len(coords_ring)
  125. idx = coords_ring.index((x1, y1))
  126. new_x1, new_y1 = coords_ring[(idx + d) % length]
  127. return new_y1, new_x1
  128. def overflow(x, size=400):
  129. return x < 0 or x >= size
  130. def edge_align(coords, filename, size, division=9):
  131. y1, x1, y2, x2 = coords
  132. ry1, rx1, ry2, rx2 = y1, x1, y2, x2
  133. if overflow(y1, size[0]) or overflow(x1, size[1]) or overflow(y2, size[0]) or overflow(x2, size[1]):
  134. return [ry1, rx1, ry2, rx2]
  135. density = 0
  136. hed_path = './data/sl6500_hed_results/'
  137. # hed_path = '/home/hanqi/JTLEE_code/pytorch-hed/hed_results/'
  138. filename = filename.split('.')[0]
  139. hed_file_path = os.path.join(hed_path, filename + '.png')
  140. hed = np.array(Image.open(hed_file_path).convert('L')) / 255
  141. coords_ring = [] #(x, y)
  142. #size = (400, 400)
  143. for i in range(0, size[1]):
  144. coords_ring.append((i, 0))
  145. for i in range(1, size[0]):
  146. coords_ring.append((size[1]-1, i))
  147. for i in range(size[1]-2, 0, -1):
  148. coords_ring.append((i, size[0]-1))
  149. for i in range(size[0]-1, 0, -1):
  150. coords_ring.append((0, i))
  151. for d1 in range(-division, division+1):
  152. for d2 in range(-division, division+1):
  153. ny1, nx1 = local_search([y1, x1], coords_ring, d=d1)
  154. ny2, nx2 = local_search([y2, x2], coords_ring, d=d2)
  155. mask = np.zeros_like(hed)
  156. mask = cv2.line(mask, (nx1, ny1), (nx2, ny2), color=1.0, thickness=3)
  157. dens = (mask * hed).sum() / mask.sum()
  158. if dens > density:
  159. density = dens
  160. ry1, rx1, ry2, rx2 = ny1, nx1, ny2, nx2
  161. return [ry1, rx1, ry2, rx2]