123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- import torch
- import numpy as np
- import math
- import cv2
- import os
- import torchvision
- from PIL import Image
- from basic_ops import *
- def draw_line(y, x, angle, image, color=(0,0,255), num_directions=24):
- '''
- Draw a line with point y, x, angle in image with color.
- '''
- cv2.circle(image, (x, y), 2, color, 2)
- H, W = image.shape[:2]
- angle = int2arc(angle, num_directions)
- point1, point2 = get_boundary_point(y, x, angle, H, W)
- cv2.line(image, point1, point2, color, 2)
- return image
- def convert_line_to_hough(line, size=(32, 32)):
- H, W = size
- theta = line.angle()
- alpha = theta + np.pi / 2
- if theta == -np.pi / 2:
- r = line.coord[1] - W/2
- else:
- k = np.tan(theta)
- y1 = line.coord[0] - H/2
- x1 = line.coord[1] - W/2
- r = (y1 - k*x1) / np.sqrt(1 + k**2)
- return alpha, r
- def line2hough(line, numAngle, numRho, size=(32, 32)):
- H, W = size
- alpha, r = convert_line_to_hough(line, size)
- irho = int(np.sqrt(H*H + W*W) + 1) / ((numRho - 1))
- itheta = np.pi / numAngle
- r = int(np.round(r / irho)) + int((numRho) / 2)
- alpha = int(np.round(alpha / itheta))
- if alpha >= numAngle:
- alpha = numAngle - 1
- return alpha, r
- def line2hough_float(line, numAngle, numRho, size=(32, 32)):
- H, W = size
- alpha, r = convert_line_to_hough(line, size)
- irho = int(np.sqrt(H*H + W*W) + 1) / ((numRho - 1))
- itheta = np.pi / numAngle
- r = r / irho + numRho / 2
- alpha = alpha / itheta
- if alpha >= numAngle:
- alpha = numAngle - 1
- return alpha, r
- def reverse_mapping(point_list, numAngle, numRho, size=(32, 32)):
- #return type: [(y1, x1, y2, x2)]
- H, W = size
- irho = int(np.sqrt(H*H + W*W) + 1) / ((numRho - 1))
- itheta = np.pi / numAngle
- b_points = []
- for (thetai, ri) in point_list:
- theta = thetai * itheta
- r = ri - numRho // 2
- cosi = np.cos(theta) / irho
- sini = np.sin(theta) / irho
- if sini == 0:
- x = np.round(r / cosi + W / 2)
- b_points.append((0, int(x), H-1, int(x)))
- else:
- # print('k = %.4f', - cosi / sini)
- # print('b = %.2f', np.round(r / sini + W * cosi / sini / 2 + H / 2))
- angle = np.arctan(- cosi / sini)
- y = np.round(r / sini + W * cosi / sini / 2 + H / 2)
- p1, p2 = get_boundary_point(int(y), 0, angle, H, W)
- if p1 is not None and p2 is not None:
- b_points.append((p1[1], p1[0], p2[1], p2[0]))
- return b_points
- def visulize_mapping(b_points, size, filename):
- img = cv2.imread(os.path.join('./data/NKL', filename)) #change the path when using other dataset.
- img = cv2.resize(img, size)
- for (y1, x1, y2, x2) in b_points:
- img = cv2.line(img, (x1, y1), (x2, y2), (255, 255, 0), thickness=int(0.01*max(size[0], size[1])))
- return img
- def caculate_precision(b_points, gt_coords, thresh=0.90):
- N = len(b_points)
- if N == 0:
- return 0, 0
- ea = np.zeros(N, dtype=np.float32)
- for i, coord_p in enumerate(b_points):
- if coord_p[0]==coord_p[2] and coord_p[1]==coord_p[3]:
- continue
- l_pred = Line(list(coord_p))
- for coord_g in gt_coords:
- l_gt = Line(list(coord_g))
- ea[i] = max(ea[i], EA_metric(l_pred, l_gt))
- return (ea >= thresh).sum(), N
- def caculate_recall(b_points, gt_coords, thresh=0.90):
- N = len(gt_coords)
- if N == 0:
- return 1.0, 0
- ea = np.zeros(N, dtype=np.float32)
- for i, coord_g in enumerate(gt_coords):
- l_gt = Line(list(coord_g))
- for coord_p in b_points:
- if coord_p[0]==coord_p[2] and coord_p[1]==coord_p[3]:
- continue
- l_pred = Line(list(coord_p))
- ea[i] = max(ea[i], EA_metric(l_pred, l_gt))
- return (ea >= thresh).sum(), N
- def coords_sort(coords):
- y1, x1, y2, x2 = coords
- if x1 > x2 or (x1 == x2 and y1 > y2):
- yy1, xx1, yy2, xx2 = y2, x2, y1, x1
- else:
- yy1, xx1, yy2, xx2 = y1, x1, y2, x2
- return yy1, xx1, yy2, xx2
- def get_density(filename, x1, y1, x2, y2):
- hed_path = '/home/hanqi/JTLEE_code/pytorch-hed/hed_results/'
- filename = filename.split('_')[0]
- hed_file_path = os.path.join(hed_path, filename + '.png')
- hed = np.array(Image.open(hed_file_path).convert('L')) / 255
- mask = np.zeros_like(hed)
- mask = cv2.line(mask, (x1, y1), (x2, y2), color=1.0, thickness=7)
- density = (mask * hed).sum() / mask.sum()
- return density
- def local_search(coords, coords_ring, d=1):
- y1, x1 = coords
-
- length = len(coords_ring)
- idx = coords_ring.index((x1, y1))
- new_x1, new_y1 = coords_ring[(idx + d) % length]
- return new_y1, new_x1
- def overflow(x, size=400):
- return x < 0 or x >= size
- def edge_align(coords, filename, size, division=9):
- y1, x1, y2, x2 = coords
- ry1, rx1, ry2, rx2 = y1, x1, y2, x2
- if overflow(y1, size[0]) or overflow(x1, size[1]) or overflow(y2, size[0]) or overflow(x2, size[1]):
- return [ry1, rx1, ry2, rx2]
- density = 0
- hed_path = './data/sl6500_hed_results/'
- # hed_path = '/home/hanqi/JTLEE_code/pytorch-hed/hed_results/'
- filename = filename.split('.')[0]
- hed_file_path = os.path.join(hed_path, filename + '.png')
- hed = np.array(Image.open(hed_file_path).convert('L')) / 255
-
- coords_ring = [] #(x, y)
- #size = (400, 400)
- for i in range(0, size[1]):
- coords_ring.append((i, 0))
- for i in range(1, size[0]):
- coords_ring.append((size[1]-1, i))
- for i in range(size[1]-2, 0, -1):
- coords_ring.append((i, size[0]-1))
- for i in range(size[0]-1, 0, -1):
- coords_ring.append((0, i))
- for d1 in range(-division, division+1):
- for d2 in range(-division, division+1):
- ny1, nx1 = local_search([y1, x1], coords_ring, d=d1)
- ny2, nx2 = local_search([y2, x2], coords_ring, d=d2)
- mask = np.zeros_like(hed)
- mask = cv2.line(mask, (nx1, ny1), (nx2, ny2), color=1.0, thickness=3)
- dens = (mask * hed).sum() / mask.sum()
- if dens > density:
- density = dens
- ry1, rx1, ry2, rx2 = ny1, nx1, ny2, nx2
- return [ry1, rx1, ry2, rx2]
|