|
import numpy as np |
|
import matplotlib.pyplot as plt |
|
import cv2 |
|
import threading |
|
import os |
|
import skimage |
|
import random |
|
import time |
|
|
|
TWO_CORNER_MINIMUM_DISTANCE = 5 |
|
SAFE_NUM = 3 |
|
score_weights = (1., 2., 100.) |
|
|
|
|
|
|
|
|
|
|
|
def swap_two_corner_place(corners, edges, id1, id2): |
|
for edge_i in range(edges.shape[0]): |
|
if edges[edge_i, 0] == id1: |
|
edges[edge_i, 0] = id2 |
|
elif edges[edge_i, 0] == id2: |
|
edges[edge_i, 0] = id1 |
|
if edges[edge_i, 1] == id1: |
|
edges[edge_i, 1] = id2 |
|
elif edges[edge_i, 1] == id2: |
|
edges[edge_i, 1] = id1 |
|
temp = corners[id1].copy() |
|
corners[id1] = corners[id2] |
|
corners[id2] = temp |
|
return corners, edges |
|
|
|
|
|
def get_neighbor_corner_id(corner_id, edges): |
|
where = np.where(edges == corner_id) |
|
return edges[where[0], 1 - where[1]] |
|
|
|
|
|
def swap_two_edge_place(edges, id1, id2): |
|
temp = edges[id1].copy() |
|
edges[id1] = edges[id2] |
|
edges[id2] = temp |
|
return edges |
|
|
|
|
|
def degree_of_three_corners(cornerA, cornerB, cornerM): |
|
|
|
AM_length = l2_distance(cornerA, cornerM) |
|
BM_length = l2_distance(cornerB, cornerM) |
|
dot = np.dot((cornerA[0] - cornerM[0], cornerA[1] - cornerM[1]), |
|
(cornerB[0] - cornerM[0], cornerB[1] - cornerM[1])) |
|
cos = dot / (AM_length + 1e-8) / (BM_length + 1e-8) |
|
cos = min(1, max(-1, cos)) |
|
degree = np.arccos(cos) |
|
return degree / np.pi * 180 |
|
|
|
|
|
def sort_graph(corners, edges): |
|
corners = corners.copy() |
|
edges = edges.copy() |
|
for corner_i in range(corners.shape[0]): |
|
min_id = -1 |
|
min_pos = corners[corner_i] |
|
for corner_j in range(corner_i + 1, corners.shape[0]): |
|
if (corners[corner_j, 0] < min_pos[0]) or \ |
|
(corners[corner_j, 0] == min_pos[0] and corners[corner_j, 1] < min_pos[1]): |
|
min_pos = corners[corner_j] |
|
min_id = corner_j |
|
if min_id != -1: |
|
corners, edges = swap_two_corner_place(corners, edges, corner_i, min_id) |
|
|
|
for edge_i in range(edges.shape[0]): |
|
if edges[edge_i, 0] > edges[edge_i, 1]: |
|
temp = edges[edge_i, 0] |
|
edges[edge_i, 0] = edges[edge_i, 1] |
|
edges[edge_i, 1] = temp |
|
|
|
for edge_i in range(edges.shape[0]): |
|
min_id = -1 |
|
min_pos = edges[edge_i] |
|
for edge_j in range(edge_i + 1, edges.shape[0]): |
|
if (edges[edge_j, 0] < min_pos[0]) or \ |
|
(edges[edge_j, 0] == min_pos[0] and edges[edge_j, 1] < min_pos[1]): |
|
min_pos = edges[edge_j] |
|
min_id = edge_j |
|
if min_id != -1: |
|
edges = swap_two_edge_place(edges, edge_i, min_id) |
|
|
|
return corners, edges |
|
|
|
|
|
def IOU(maskA, maskB): |
|
return np.logical_and(maskA, maskB).sum() / np.logical_or(maskA, maskB).sum() |
|
|
|
|
|
def render(corners, edges, render_pad=0, edge_linewidth=2, corner_size=3, scale=1.): |
|
size = int(256 * scale) |
|
mask = np.ones((2, size, size)) * render_pad |
|
|
|
corners = np.round(corners.copy() * scale).astype(np.int) |
|
for edge_i in range(edges.shape[0]): |
|
a = edges[edge_i, 0] |
|
b = edges[edge_i, 1] |
|
mask[0] = cv2.line(mask[0], (int(corners[a, 1]), int(corners[a, 0])), |
|
(int(corners[b, 1]), int(corners[b, 0])), 1.0, thickness=edge_linewidth) |
|
for corner_i in range(corners.shape[0]): |
|
mask[1] = cv2.circle(mask[1], (int(corners[corner_i, 1]), int(corners[corner_i, 0])), corner_size, 1.0, -1) |
|
|
|
return mask |
|
|
|
|
|
def patch_samples(edge_num, batch_size): |
|
num = edge_num // batch_size |
|
patchs = [] |
|
for i in range(num): |
|
patchs.append([i * batch_size + j for j in range(batch_size)]) |
|
|
|
if edge_num % batch_size != 0: |
|
patchs.append([j for j in range(batch_size * num, edge_num)]) |
|
|
|
return patchs |
|
|
|
|
|
def l2_distance(x1, x2): |
|
return np.sqrt((x1[0] - x2[0]) ** 2 + (x1[1] - x2[1]) ** 2) |
|
|
|
|
|
def triangle_region(A, B, C): |
|
l1 = np.linalg.norm(np.array(A) - np.array(B)) |
|
l2 = np.linalg.norm(np.array(A) - np.array(C)) |
|
l3 = np.linalg.norm(np.array(B) - np.array(C)) |
|
p = (l1 + l2 + l3) / 2 |
|
area = np.sqrt(np.abs(p * (p - l1) * (p - l2) * (p - l3))) |
|
return area |
|
|
|
|
|
def remove_intersection_and_duplicate(corners, edges, name): |
|
over_all_flag = False |
|
ori_corners = corners.copy() |
|
ori_edges = edges.copy() |
|
while True: |
|
flag = False |
|
for edge_i in range(edges.shape[0]): |
|
for edge_j in range(edge_i + 1, edges.shape[0]): |
|
corner11 = corners[edges[edge_i, 0]] |
|
corner12 = corners[edges[edge_i, 1]] |
|
corner21 = corners[edges[edge_j, 0]] |
|
corner22 = corners[edges[edge_j, 1]] |
|
|
|
y1 = corner11[0] |
|
x1 = corner11[1] |
|
y2 = corner12[0] |
|
x2 = corner12[1] |
|
a1 = y1 - y2 |
|
b1 = x2 - x1 |
|
c1 = x1 * y2 - x2 * y1 |
|
flag1 = (a1 * corner21[1] + b1 * corner21[0] + c1) * (a1 * corner22[1] + b1 * corner22[0] + c1) |
|
|
|
y1 = corner21[0] |
|
x1 = corner21[1] |
|
y2 = corner22[0] |
|
x2 = corner22[1] |
|
a2 = y1 - y2 |
|
b2 = x2 - x1 |
|
c2 = x1 * y2 - x2 * y1 |
|
flag2 = (a2 * corner11[1] + b2 * corner11[0] + c2) * (a2 * corner12[1] + b2 * corner12[0] + c2) |
|
|
|
if flag1 < -1e-5 and flag2 < -1e-5: |
|
|
|
over_all_flag = True |
|
flag = True |
|
|
|
new_x = (c2 * b1 - c1 * b2) / (a1 * b2 - a2 * b1) |
|
new_y = (a2 * c1 - a1 * c2) / (a1 * b2 - a2 * b1) |
|
|
|
temp_d = 3 |
|
temp_id = -1 |
|
if l2_distance((new_y, new_x), corner11) < temp_d: |
|
temp_id = edges[edge_i, 0] |
|
temp_d = l2_distance((new_y, new_x), corner11) |
|
if l2_distance((new_y, new_x), corner12) < temp_d: |
|
temp_id = edges[edge_i, 1] |
|
temp_d = l2_distance((new_y, new_x), corner12) |
|
if l2_distance((new_y, new_x), corner21) < temp_d: |
|
temp_id = edges[edge_j, 0] |
|
temp_d = l2_distance((new_y, new_x), corner21) |
|
if l2_distance((new_y, new_x), corner22) < temp_d: |
|
temp_id = edges[edge_j, 1] |
|
temp_d = l2_distance((new_y, new_x), corner22) |
|
if temp_id != -1: |
|
if edges[edge_i, 0] != temp_id and edges[edge_i, 1] != temp_id: |
|
tt = edges[edge_i, 0] |
|
edges[edge_i, 0] = temp_id |
|
edges = np.append(edges, np.array([(temp_id, tt)]), 0) |
|
if edges[edge_j, 0] != temp_id and edges[edge_j, 1] != temp_id: |
|
tt = edges[edge_j, 0] |
|
edges[edge_j, 0] = temp_id |
|
edges = np.append(edges, np.array([(temp_id, tt)]), 0) |
|
else: |
|
corners = np.append(corners, np.array([(new_y, new_x)]), 0) |
|
edge_id1 = edges[edge_i, 1] |
|
edge_id2 = edges[edge_j, 1] |
|
edges[edge_i, 1] = corners.shape[0] - 1 |
|
edges[edge_j, 1] = corners.shape[0] - 1 |
|
edges = np.append(edges, np.array([(edge_id1, corners.shape[0] - 1)]), 0) |
|
edges = np.append(edges, np.array([(edge_id2, corners.shape[0] - 1)]), 0) |
|
break |
|
if flag: |
|
break |
|
if flag: |
|
continue |
|
break |
|
|
|
|
|
graph = Graph(np.round(corners), edges) |
|
for corner_i in reversed(range(len(graph.getCorners()))): |
|
corner_ele1 = graph.getCorners()[corner_i] |
|
for corner_j in reversed(range(corner_i)): |
|
corner_ele2 = graph.getCorners()[corner_j] |
|
if l2_distance(corner_ele1.x, corner_ele2.x) < 3: |
|
connected_edge = graph.getEdgeConnected(corner_ele1) |
|
for edge_ele in connected_edge: |
|
if edge_ele.x[0] == corner_ele1: |
|
another = edge_ele.x[1] |
|
else: |
|
another = edge_ele.x[0] |
|
if another == corner_ele2: |
|
graph.remove(edge_ele) |
|
edge_ele.x = (another, corner_ele2) |
|
graph.remove(corner_ele1) |
|
for corner_ele in graph.getCorners(): |
|
if graph.getCornerDegree(corner_ele) == 0: |
|
graph.remove(corner_ele) |
|
|
|
corners = graph.getCornersArray() |
|
edges = graph.getEdgesArray() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return corners, edges |
|
|
|
|
|
def get_two_edge_intersection_location(corner11, corner12, corner21, corner22): |
|
y1 = corner11[0] |
|
x1 = corner11[1] |
|
y2 = corner12[0] |
|
x2 = corner12[1] |
|
a1 = y1 - y2 |
|
b1 = x2 - x1 |
|
c1 = x1 * y2 - x2 * y1 |
|
|
|
y1 = corner21[0] |
|
x1 = corner21[1] |
|
y2 = corner22[0] |
|
x2 = corner22[1] |
|
a2 = y1 - y2 |
|
b2 = x2 - x1 |
|
c2 = x1 * y2 - x2 * y1 |
|
|
|
l = a1 * b2 - a2 * b1 |
|
if l == 0: |
|
l = 1e-5 |
|
|
|
new_x = (c2 * b1 - c1 * b2) / l |
|
new_y = (a2 * c1 - a1 * c2) / l |
|
|
|
return round(new_y), round(new_x) |
|
|
|
|
|
def get_distance_of_corner_and_edge(corner1, corner2, corner): |
|
x = corner[0] |
|
y = corner[1] |
|
x1 = corner1[0] |
|
y1 = corner1[1] |
|
x2 = corner2[0] |
|
y2 = corner2[1] |
|
|
|
cross = (x2 - x1) * (x - x1) + (y2 - y1) * (y - y1) |
|
if cross <= 0: |
|
|
|
return np.linalg.norm((x - x1, y - y1)) |
|
|
|
d2 = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1) |
|
if cross >= d2: |
|
|
|
return np.linalg.norm((x - x2, y - y2)) |
|
|
|
r = cross / d2 |
|
px = x1 + (x2 - x1) * r |
|
py = y1 + (y2 - y1) * r |
|
return np.linalg.norm((x - px, y - py)) |
|
|
|
|
|
|
|
|
|
|
|
def EuclideanDistance(A, B): |
|
BT = B.transpose() |
|
vecProd = np.dot(A, BT) |
|
|
|
SqA = A ** 2 |
|
sumSqA = np.matrix(np.sum(SqA, axis=1)) |
|
sumSqAEx = np.tile(sumSqA.transpose(), (1, vecProd.shape[1])) |
|
|
|
SqB = B ** 2 |
|
sumSqB = np.sum(SqB, axis=1) |
|
sumSqBEx = np.tile(sumSqB, (vecProd.shape[0], 1)) |
|
SqED = sumSqBEx + sumSqAEx - 2 * vecProd |
|
SqED[SqED < 0] = 0.0 |
|
ED = np.sqrt(SqED) |
|
return ED |
|
|
|
|
|
def samedirection(conv_corner_id, gt_corner_id, conv_corners, gt_corners, conv_edges, gt_edges): |
|
|
|
if np.where(conv_edges == conv_corner_id)[0].shape[0] != np.where(gt_edges == gt_corner_id)[0].shape[0]: |
|
return False |
|
|
|
|
|
place = np.where(conv_edges == conv_corner_id) |
|
neighbor_id = conv_edges[place[0], 1 - place[1]] |
|
|
|
distance = conv_corners[conv_corner_id] - conv_corners[neighbor_id] |
|
direction = np.arctan2(distance[:, 0], distance[:, 1]) * 180 / np.pi / 15 |
|
direction = (direction + 24) % 24 |
|
|
|
conv_dir = np.sort(direction) |
|
|
|
place = np.where(gt_edges == gt_corner_id) |
|
neighbor_id = gt_edges[place[0], 1 - place[1]] |
|
|
|
distance = gt_corners[gt_corner_id] - gt_corners[neighbor_id] |
|
direction = np.arctan2(distance[:, 0], distance[:, 1]) * 180 / np.pi / 15 |
|
direction = (direction + 24) % 24 |
|
|
|
gt_dir = np.sort(direction) |
|
|
|
conv_dir = list(conv_dir) |
|
gt_dir = list(gt_dir) |
|
for angle in gt_dir: |
|
temp = sorted(conv_dir, key=lambda x: min(np.abs(x - angle), 24 - np.abs(x - angle))) |
|
if min(np.abs(temp[0] - angle), 24 - np.abs(temp[0] - angle)) <= 1.3: |
|
conv_dir.remove(temp[0]) |
|
else: |
|
return False |
|
return True |
|
|
|
|
|
def simplify_gt(gt_match_location, gt_corner, gt_edge): |
|
graph = Graph(np.round(gt_corner), gt_edge) |
|
for idx, corner in enumerate(graph.getCorners()): |
|
|
|
corner.store_score(gt_match_location[idx]) |
|
|
|
for idx, corner in enumerate(graph.getCorners()): |
|
if corner.get_score() is None: |
|
connected_edges = graph.getEdgeConnected(corner) |
|
neighbor_corners = [] |
|
for edge in connected_edges: |
|
if edge.x[0] != corner: |
|
neighbor_corners.append(edge.x[0]) |
|
continue |
|
if edge.x[1] != corner: |
|
neighbor_corners.append(edge.x[1]) |
|
continue |
|
raise BaseException() |
|
neighbor_corners = sorted(neighbor_corners, key=lambda ele: l2_distance(ele.x, corner.x)) |
|
for neighbor_ele in neighbor_corners: |
|
if l2_distance(neighbor_ele.x, corner.x) > 8: |
|
break |
|
if neighbor_ele.get_score() is None: |
|
continue |
|
|
|
for ele in neighbor_corners: |
|
if ele == neighbor_ele: |
|
continue |
|
graph.add_edge(ele, neighbor_ele) |
|
neighbor_ele.x = (0.7 * neighbor_ele.x[0] + 0.3 * corner.x[0], |
|
0.7 * neighbor_ele.x[1] + 0.3 * corner.x[1]) |
|
graph.remove(corner) |
|
break |
|
return graph.getCornersArray(), graph.getEdgesArray() |
|
|
|
|
|
def get_wrong_corners(corners, gt_corners, edges, gt_edges): |
|
corners = corners.copy() |
|
gt_corners = gt_corners.copy() |
|
edges = edges.copy() |
|
gt_edges = gt_edges.copy() |
|
dist_matrix = EuclideanDistance(gt_corners, corners) |
|
assigned_id = set() |
|
gt_match_same_degree = [] |
|
gt_match_location = [] |
|
for gt_i in range(gt_corners.shape[0]): |
|
sort_id = np.argsort(dist_matrix[gt_i]).__array__()[0] |
|
flag = True |
|
for id_ in sort_id: |
|
if dist_matrix[gt_i, id_] > 7: |
|
break |
|
temete = samedirection(id_, gt_i, corners, gt_corners, edges, gt_edges) |
|
if temete == False: |
|
break |
|
elif id_ not in assigned_id: |
|
assigned_id.add(id_) |
|
gt_match_same_degree.append(id_) |
|
flag = False |
|
break |
|
if flag: |
|
gt_match_same_degree.append(None) |
|
|
|
matched = [] |
|
gt_match_location = [None for _ in range(gt_corners.shape[0])] |
|
for gt_i in sorted(list(range(gt_corners.shape[0])), key=lambda i: np.min(dist_matrix[i])): |
|
sort_id = np.argsort(dist_matrix[gt_i]).__array__()[0] |
|
if dist_matrix[gt_i, sort_id[0]] > 7: |
|
gt_match_location[gt_i] = None |
|
else: |
|
for c_i in sort_id: |
|
if c_i in matched: |
|
continue |
|
if dist_matrix[gt_i, c_i] > 7: |
|
gt_match_location[gt_i] = None |
|
break |
|
else: |
|
gt_match_location[gt_i] = c_i |
|
matched.append(c_i) |
|
break |
|
|
|
return set(range(corners.shape[0])) - assigned_id, gt_match_same_degree, gt_match_location |
|
|
|
|
|
def get_wrong_edges(corners, gt_corners, edges, gt_edges, gt_match): |
|
edges = edges.copy() |
|
gt_edges = gt_edges.copy() |
|
|
|
all_possible_good_edges = [] |
|
for edge_i in range(gt_edges.shape[0]): |
|
if gt_match[gt_edges[edge_i, 0]] is None or gt_match[gt_edges[edge_i, 1]] is None: |
|
continue |
|
all_possible_good_edges.append((gt_match[gt_edges[edge_i, 0]], gt_match[gt_edges[edge_i, 1]])) |
|
false_edge_id = [] |
|
for edge_i in range(edges.shape[0]): |
|
id1 = edges[edge_i][0] |
|
id2 = edges[edge_i][1] |
|
if (id1, id2) not in all_possible_good_edges and (id2, id1) not in all_possible_good_edges: |
|
false_edge_id.append(edge_i) |
|
continue |
|
|
|
return false_edge_id |
|
|
|
|
|
def get_corner_bin_map(corners, corner_list_for_each_bin, bin_size=10): |
|
bin_map = np.zeros((bin_size, 256, 256)) |
|
for bin_i in range(bin_size): |
|
bin_map[bin_i] = render(corners[corner_list_for_each_bin[bin_i]], np.array([]), render_pad=0)[1] |
|
return bin_map |
|
|
|
|
|
|
|
|
|
|
|
def visualization(candidate, show=True): |
|
corners = candidate.graph.getCornersArray() |
|
edges = candidate.graph.getEdgesArray() |
|
mask = render(corners, edges) |
|
mask = np.transpose(np.concatenate((mask, np.zeros((1, 256, 256))), 0), (1, 2, 0)) |
|
plt.imshow(mask) |
|
if show: |
|
plt.show() |
|
|
|
|
|
def check_intersection(edge1, edge2): |
|
corner11 = edge1.x[0].x |
|
corner12 = edge1.x[1].x |
|
corner21 = edge2.x[0].x |
|
corner22 = edge2.x[1].x |
|
|
|
y1 = corner11[0] |
|
x1 = corner11[1] |
|
y2 = corner12[0] |
|
x2 = corner12[1] |
|
a = y1 - y2 |
|
b = x2 - x1 |
|
c = x1 * y2 - x2 * y1 |
|
flag1 = (a * corner21[1] + b * corner21[0] + c) * (a * corner22[1] + b * corner22[0] + c) |
|
|
|
y1 = corner21[0] |
|
x1 = corner21[1] |
|
y2 = corner22[0] |
|
x2 = corner22[1] |
|
a = y1 - y2 |
|
b = x2 - x1 |
|
c = x1 * y2 - x2 * y1 |
|
flag2 = (a * corner11[1] + b * corner11[0] + c) * (a * corner12[1] + b * corner12[0] + c) |
|
|
|
if flag1 < -1e-6 and flag2 < -1e-6: |
|
return True |
|
|
|
return False |
|
|
|
|
|
def adding_a_corner_by_triangle_operation(candidate): |
|
new_candidates = [] |
|
name = candidate.name |
|
gt_mask = region_cache.get_region(name) |
|
gt_mask = gt_mask > 0.4 |
|
gt_mask_grow = cv2.dilate(gt_mask.astype(np.float64), np.ones((3, 3), np.uint8), iterations=6) > 0 |
|
|
|
|
|
conv_mask = render(corners=candidate.graph.getCornersArray(), edges=candidate.graph.getEdgesArray(), |
|
render_pad=0, edge_linewidth=1)[0] |
|
conv_mask = 1 - conv_mask |
|
conv_mask = conv_mask.astype(np.uint8) |
|
labels, region_mask = cv2.connectedComponents(conv_mask, connectivity=4) |
|
|
|
background_label = region_mask[0, 0] |
|
all_masks = [] |
|
for region_i in range(1, labels): |
|
if region_i == background_label: |
|
continue |
|
the_region = region_mask == region_i |
|
if the_region.sum() < 20: |
|
continue |
|
all_masks.append(the_region) |
|
|
|
candidate_mask = (np.sum(all_masks, 0) + (1 - conv_mask)) > 0 |
|
|
|
final_mask = np.logical_xor(gt_mask_grow, np.logical_and(candidate_mask, gt_mask_grow)) |
|
|
|
for corner_i in range(random.randint(0, 16), 256, 16): |
|
for corner_j in range(random.randint(0, 16), 256, 16): |
|
if candidate.addable((corner_i, corner_j)): |
|
if final_mask[corner_i, corner_j] == True: |
|
new_corner = Element((corner_i, corner_j)) |
|
new_candidate = candidate.generate_new_candidate_add_a_corner(new_corner) |
|
new_graph = new_candidate.graph |
|
corners = new_graph.getCorners() |
|
|
|
|
|
for id_A in range(len(corners)): |
|
ele_A = corners[id_A] |
|
if ele_A == new_corner: |
|
continue |
|
for id_B in range(id_A + 1, len(corners)): |
|
ele_B = corners[id_B] |
|
if ele_B == new_corner: |
|
continue |
|
if new_graph.has_edge(new_corner, ele_A) is not None: |
|
raise BaseException('should not have edge in this case') |
|
if new_graph.has_edge(new_corner, ele_B) is not None: |
|
raise BaseException('should not have edge in this case') |
|
temp_edge1 = Element((new_corner, ele_A)) |
|
temp_edge2 = Element((new_corner, ele_B)) |
|
|
|
|
|
if new_candidate.addable(temp_edge1) is False: |
|
continue |
|
if new_candidate.addable(temp_edge2) is False: |
|
continue |
|
|
|
|
|
if new_graph.checkIntersectionEdge(temp_edge1): |
|
continue |
|
if new_graph.checkIntersectionEdge(temp_edge2): |
|
continue |
|
|
|
|
|
if triangle_region(new_corner.x, ele_A.x, ele_B.x) < 20: |
|
continue |
|
|
|
|
|
|
|
neighbor_edges = new_graph.getEdgeConnected(temp_edge1) |
|
flag_ = True |
|
for neighbor in neighbor_edges: |
|
if new_corner in neighbor.x: |
|
raise BaseException('new corner should not in any edge') |
|
elif ele_A in neighbor.x: |
|
shared_corner = ele_A |
|
else: |
|
raise BaseException('error.') |
|
two_neighbor = {neighbor.x[0], neighbor.x[1], ele_A, new_corner} |
|
two_neighbor.remove(shared_corner) |
|
assert len(two_neighbor) == 2 |
|
two_neighbor = tuple(two_neighbor) |
|
|
|
line1 = np.array(shared_corner.x) - np.array(two_neighbor[0].x) |
|
line2 = np.array(shared_corner.x) - np.array(two_neighbor[1].x) |
|
cos = np.dot(line1, line2) / (np.linalg.norm(line1) * np.linalg.norm(line2)) |
|
cos = min(1, max(-1, cos)) |
|
if np.arccos(cos) < np.pi / 9: |
|
flag_ = False |
|
break |
|
if flag_ is False: |
|
continue |
|
|
|
neighbor_edges = new_graph.getEdgeConnected(temp_edge2) |
|
flag_ = True |
|
for neighbor in neighbor_edges: |
|
if new_corner in neighbor.x: |
|
raise BaseException('new corner should not in any edge') |
|
elif ele_B in neighbor.x: |
|
shared_corner = ele_B |
|
else: |
|
raise BaseException('error.') |
|
two_neighbor = {neighbor.x[0], neighbor.x[1], ele_B, new_corner} |
|
two_neighbor.remove(shared_corner) |
|
assert len(two_neighbor) == 2 |
|
two_neighbor = tuple(two_neighbor) |
|
|
|
line1 = np.array(shared_corner.x) - np.array(two_neighbor[0].x) |
|
line2 = np.array(shared_corner.x) - np.array(two_neighbor[1].x) |
|
cos = np.dot(line1, line2) / (np.linalg.norm(line1) * np.linalg.norm(line2)) |
|
cos = min(1, max(-1, cos)) |
|
if np.arccos(cos) < np.pi / 9: |
|
flag_ = False |
|
break |
|
if flag_ is False: |
|
continue |
|
|
|
|
|
try: |
|
new_ = new_candidate.generate_new_candidate_add_an_edge(new_corner, ele_A) |
|
new_ = new_.generate_new_candidate_add_an_edge(new_corner, ele_B) |
|
new_candidates.append(new_) |
|
except: |
|
continue |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return new_candidates |
|
|
|
|
|
def adding_an_edge_from_new_corner_operation(candidate): |
|
new_candidates = [] |
|
name = candidate.name |
|
gt_mask = region_cache.get_region(name) |
|
gt_mask = gt_mask > 0.4 |
|
gt_mask_grow = cv2.dilate(gt_mask.astype(np.float64), np.ones((3, 3), np.uint8), iterations=6) > 0 |
|
|
|
|
|
conv_mask = render(corners=candidate.graph.getCornersArray(), edges=candidate.graph.getEdgesArray(), |
|
render_pad=0, edge_linewidth=1)[0] |
|
conv_mask = 1 - conv_mask |
|
conv_mask = conv_mask.astype(np.uint8) |
|
labels, region_mask = cv2.connectedComponents(conv_mask, connectivity=4) |
|
background_label = region_mask[0, 0] |
|
all_masks = [] |
|
for region_i in range(1, labels): |
|
if region_i == background_label: |
|
continue |
|
the_region = region_mask == region_i |
|
if the_region.sum() < 20: |
|
continue |
|
all_masks.append(the_region) |
|
candidate_mask = (np.sum(all_masks, 0) + (1 - conv_mask)) > 0 |
|
|
|
final_mask = np.logical_xor(gt_mask_grow, np.logical_and(candidate_mask, gt_mask_grow)) |
|
for corner_i in range(random.randint(0, 16), 256, 16): |
|
for corner_j in range(random.randint(0, 16), 256, 16): |
|
if candidate.addable((corner_i, corner_j)): |
|
if final_mask[corner_i, corner_j] == True: |
|
|
|
new_corner = Element((corner_i, corner_j)) |
|
new_candidate = candidate.generate_new_candidate_add_a_corner(new_corner) |
|
new_graph = new_candidate.graph |
|
corners = new_graph.getCorners() |
|
|
|
|
|
|
|
for corner_ele in corners: |
|
if corner_ele == new_corner: |
|
continue |
|
if new_graph.has_edge(new_corner, corner_ele) is not None: |
|
raise BaseException('should not have edge in this case') |
|
temp_edge = Element((new_corner, corner_ele)) |
|
|
|
|
|
if new_candidate.addable(temp_edge) is False: |
|
continue |
|
|
|
|
|
if new_graph.checkIntersectionEdge(temp_edge): |
|
continue |
|
|
|
|
|
neighbor_edges = new_graph.getEdgeConnected(temp_edge) |
|
flag_ = True |
|
for neighbor in neighbor_edges: |
|
if new_corner in neighbor.x: |
|
raise BaseException('new corner should not in any edge') |
|
elif corner_ele in neighbor.x: |
|
shared_corner = corner_ele |
|
else: |
|
raise BaseException('error.') |
|
two_neighbor = {neighbor.x[0], neighbor.x[1], corner_ele, new_corner} |
|
two_neighbor.remove(shared_corner) |
|
assert len(two_neighbor) == 2 |
|
two_neighbor = tuple(two_neighbor) |
|
|
|
line1 = np.array(shared_corner.x) - np.array(two_neighbor[0].x) |
|
line2 = np.array(shared_corner.x) - np.array(two_neighbor[1].x) |
|
cos = np.dot(line1, line2) / (np.linalg.norm(line1) * np.linalg.norm(line2)) |
|
cos = min(1, max(-1, cos)) |
|
if np.arccos(cos) < np.pi / 9: |
|
flag_ = False |
|
break |
|
if flag_ is False: |
|
continue |
|
|
|
|
|
try: |
|
new_ = new_candidate.generate_new_candidate_add_an_edge(new_corner, corner_ele) |
|
new_candidates.append(new_) |
|
except: |
|
continue |
|
|
|
return new_candidates |
|
|
|
|
|
def removing_a_corner_operation(candidate): |
|
new_candidates = [] |
|
graph = candidate.graph |
|
corners = graph.getCorners() |
|
for the_corner in corners: |
|
if candidate.removable(the_corner): |
|
try: |
|
new_ = candidate.generate_new_candidate_remove_a_corner(the_corner) |
|
new_candidates.append(new_) |
|
except: |
|
continue |
|
|
|
return new_candidates |
|
|
|
|
|
def removing_a_colinear_corner_operation(candidate): |
|
new_candidates = [] |
|
graph = candidate.graph |
|
corners = graph.getCorners() |
|
for the_corner in corners: |
|
if candidate.removable(the_corner): |
|
try: |
|
new_ = candidate.generate_new_candidate_remove_a_colinear_corner(the_corner) |
|
|
|
if new_.graph.checkIntersectionEdge(): |
|
continue |
|
new_candidates.append(new_) |
|
except: |
|
continue |
|
|
|
return new_candidates |
|
|
|
|
|
def adding_an_edge_operation(candidate): |
|
new_candidates = [] |
|
graph = candidate.graph |
|
corners = graph.getCorners() |
|
for corner_i in range(len(corners)): |
|
cornerA = corners[corner_i] |
|
for corner_j in range(corner_i + 1, len(corners)): |
|
cornerB = corners[corner_j] |
|
if graph.has_edge(cornerA, cornerB) is not None: |
|
continue |
|
|
|
temp_edge = Element((cornerA, cornerB)) |
|
|
|
if candidate.addable(temp_edge) is False: |
|
continue |
|
|
|
if graph.checkIntersectionEdge(temp_edge): |
|
continue |
|
|
|
|
|
neighbor_edges = graph.getEdgeConnected(temp_edge) |
|
flag_ = True |
|
for neighbor in neighbor_edges: |
|
if cornerA in neighbor.x: |
|
shared_corner = cornerA |
|
elif cornerB in neighbor.x: |
|
shared_corner = cornerB |
|
else: |
|
raise BaseException('error.') |
|
two_neighbor = {neighbor.x[0], neighbor.x[1], cornerA, cornerB} |
|
two_neighbor.remove(shared_corner) |
|
assert len(two_neighbor) == 2 |
|
two_neighbor = tuple(two_neighbor) |
|
|
|
line1 = np.array(shared_corner.x) - np.array(two_neighbor[0].x) |
|
line2 = np.array(two_neighbor[1].x) - np.array(shared_corner.x) |
|
cos = np.dot(line1, line2) / (np.linalg.norm(line1) * np.linalg.norm(line2)) |
|
cos = min(1, max(-1, cos)) |
|
if np.arccos(cos) < np.pi / 18 or np.arccos(cos) > np.pi - np.pi / 18: |
|
flag_ = False |
|
break |
|
if flag_ is False: |
|
continue |
|
|
|
|
|
try: |
|
new_ = candidate.generate_new_candidate_add_an_edge(cornerA, cornerB) |
|
new_candidates.append(new_) |
|
except: |
|
continue |
|
|
|
return new_candidates |
|
|
|
|
|
def removing_an_edge_operation(candidate): |
|
new_candidates = [] |
|
graph = candidate.graph |
|
edges = graph.getEdges() |
|
for edge_ele in edges: |
|
if candidate.removable(edge_ele): |
|
try: |
|
new_ = candidate.generate_new_candidate_remove_an_edge(edge_ele) |
|
new_candidates.append(new_) |
|
except: |
|
continue |
|
|
|
return new_candidates |
|
|
|
|
|
def adding_an_edge_from_gt(candidate, gt_data): |
|
new_candidates = [] |
|
corners_array = candidate.graph.getCornersArray() |
|
edges_array = candidate.graph.getEdgesArray() |
|
|
|
gt_corners = gt_data['corners'].copy() |
|
gt_edges = gt_data['edges'].copy() |
|
|
|
_, _, map_same_location = get_wrong_corners( |
|
corners_array, gt_corners, edges_array, gt_edges) |
|
|
|
gt_corners, gt_edges = simplify_gt(map_same_location, gt_corners, gt_edges) |
|
|
|
_, _, map_same_location = get_wrong_corners( |
|
corners_array, gt_corners, edges_array, gt_edges) |
|
|
|
for corner_i in range(gt_corners.shape[0]): |
|
if map_same_location[corner_i] is None: |
|
|
|
neighbor_id = get_neighbor_corner_id(corner_i, gt_edges) |
|
for corner_j in neighbor_id: |
|
if map_same_location[corner_j] is not None: |
|
|
|
new_candidate = candidate.copy() |
|
new_corner = Element( |
|
( |
|
int(np.round(gt_corners[corner_i, 0])), int(np.round(gt_corners[corner_i, 1])) |
|
) |
|
) |
|
if new_candidate.addable(new_corner) is False: |
|
continue |
|
|
|
flag = False |
|
for edge_ele in new_candidate.graph.getEdges(): |
|
if get_distance_of_corner_and_edge(edge_ele.x[0].x, edge_ele.x[1].x, new_corner.x) < 7: |
|
flag = True |
|
break |
|
if flag: |
|
continue |
|
|
|
new_corner = new_candidate.addCorner(new_corner) |
|
neighbor_index = map_same_location[corner_j] |
|
neighbor_corner = new_candidate.graph.getCorners()[neighbor_index] |
|
new_edge = new_candidate.addEdge(new_corner, neighbor_corner) |
|
if new_candidate.graph.checkIntersectionEdge(new_edge): |
|
continue |
|
new_candidates.append(new_candidate) |
|
|
|
return new_candidates |
|
|
|
|
|
def adding_a_corner_from_two_edges_extension(candidate): |
|
new_candidates = [] |
|
graph = candidate.graph |
|
edges = candidate.graph.getEdges() |
|
for edge_i in range(len(edges)): |
|
for edge_j in range(edge_i + 1, len(edges)): |
|
edgeA = edges[edge_i] |
|
edgeB = edges[edge_j] |
|
if graph.isNeighbor(edgeA, edgeB): |
|
continue |
|
intersection_loc = get_two_edge_intersection_location(edgeA.x[0].x, edgeA.x[1].x, edgeB.x[0].x, |
|
edgeB.x[1].x) |
|
if intersection_loc[0] >= 255 or intersection_loc[1] >= 255 or \ |
|
intersection_loc[0] <= 0 or intersection_loc[1] <= 0: |
|
continue |
|
|
|
flag = False |
|
for edge_ele in graph.getEdges(): |
|
if get_distance_of_corner_and_edge(edge_ele.x[0].x, edge_ele.x[1].x, intersection_loc) < 7: |
|
flag = True |
|
break |
|
if flag: |
|
continue |
|
new_candidate = candidate.copy() |
|
new_graph = new_candidate.graph |
|
new_edgeA = new_graph.getRealElement(edgeA) |
|
new_edgeB = new_graph.getRealElement(edgeB) |
|
new_corner = Element(intersection_loc) |
|
if new_candidate.addable(new_corner) is False: |
|
continue |
|
new_corner = new_candidate.addCorner_v2(new_corner) |
|
|
|
if l2_distance(new_corner.x, new_edgeA.x[0].x) < l2_distance(new_corner.x, new_edgeA.x[1].x): |
|
cornerA = new_edgeA.x[0] |
|
else: |
|
cornerA = new_edgeA.x[1] |
|
if l2_distance(new_corner.x, new_edgeB.x[0].x) < l2_distance(new_corner.x, new_edgeB.x[1].x): |
|
cornerB = new_edgeB.x[0] |
|
else: |
|
cornerB = new_edgeB.x[1] |
|
|
|
|
|
if l2_distance(cornerA.x, new_corner.x) < 7: |
|
continue |
|
if l2_distance(cornerB.x, new_corner.x) < 7: |
|
continue |
|
|
|
|
|
if degree_of_three_corners(cornerA.x, cornerB.x, new_corner.x) > 165: |
|
continue |
|
|
|
flag = False |
|
for edge_ele in new_graph.getEdges(): |
|
if new_corner in edge_ele.x and cornerA in edge_ele.x: |
|
flag = True |
|
break |
|
if edge_ele.x[0] not in (new_corner, cornerA): |
|
l = get_distance_of_corner_and_edge(new_corner.x, cornerA.x, edge_ele.x[0].x) |
|
if l <= 7: |
|
flag = True |
|
break |
|
if edge_ele.x[1] not in (new_corner, cornerA): |
|
l = get_distance_of_corner_and_edge(new_corner.x, cornerA.x, edge_ele.x[1].x) |
|
if l <= 7: |
|
flag = True |
|
break |
|
if flag: |
|
continue |
|
add_edgeA = new_candidate.addEdge(new_corner, cornerA) |
|
if new_graph.checkIntersectionEdge(add_edgeA): |
|
continue |
|
|
|
flag = False |
|
for edge_ele in new_graph.getEdges(): |
|
if new_corner in edge_ele.x and cornerB in edge_ele.x: |
|
flag = True |
|
break |
|
if edge_ele.x[0] not in (new_corner, cornerB): |
|
l = get_distance_of_corner_and_edge(new_corner.x, cornerB.x, edge_ele.x[0].x) |
|
if l <= 7: |
|
flag = True |
|
break |
|
if edge_ele.x[1] not in (new_corner, cornerB): |
|
l = get_distance_of_corner_and_edge(new_corner.x, cornerB.x, edge_ele.x[1].x) |
|
if l <= 7: |
|
flag = True |
|
break |
|
if flag: |
|
continue |
|
add_edgeB = new_candidate.addEdge(new_corner, cornerB) |
|
if new_graph.checkIntersectionEdge(add_edgeB): |
|
continue |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
new_candidates.append(new_candidate) |
|
return new_candidates |
|
|
|
|
|
def adding_a_corner_from_parallel(candidate): |
|
new_candidates = [] |
|
graph = candidate.graph |
|
edges = candidate.graph.getEdges() |
|
for edge_i in range(len(edges)): |
|
for edge_j in range(edge_i + 1, len(edges)): |
|
edgeA = edges[edge_i] |
|
edgeB = edges[edge_j] |
|
|
|
if graph.isNeighbor(edgeA, edgeB): |
|
shared_corner = edgeA.x[0] if edgeA.x[0] in edgeB.x else edgeA.x[1] |
|
intersection_loc = shared_corner.x |
|
else: |
|
intersection_loc = get_two_edge_intersection_location( |
|
edgeA.x[0].x, edgeA.x[1].x, edgeB.x[0].x, edgeB.x[1].x) |
|
if intersection_loc[0] >= 255 or intersection_loc[1] >= 255 or \ |
|
intersection_loc[0] <= 0 or intersection_loc[1] <= 0: |
|
continue |
|
|
|
|
|
locA = edgeA.x[1].x if \ |
|
l2_distance(edgeA.x[0].x, intersection_loc) < l2_distance(edgeA.x[1].x, intersection_loc) else \ |
|
edgeA.x[0].x |
|
locB = edgeB.x[1].x if \ |
|
l2_distance(edgeB.x[0].x, intersection_loc) < l2_distance(edgeB.x[1].x, intersection_loc) else \ |
|
edgeB.x[0].x |
|
|
|
|
|
new_loc = (locA[0] + locB[0] - intersection_loc[0], locA[1] + locB[1] - intersection_loc[1]) |
|
if new_loc[0] >= 255 or new_loc[1] >= 255 or \ |
|
new_loc[0] <= 0 or new_loc[1] <= 0: |
|
continue |
|
|
|
new_corner = Element(new_loc) |
|
new_candidate = candidate.copy() |
|
new_graph = new_candidate.graph |
|
edgeA = new_graph.getRealElement(edgeA) |
|
edgeB = new_graph.getRealElement(edgeB) |
|
if new_candidate.addable(new_corner) is False: |
|
continue |
|
new_corner = new_candidate.addCorner_v2(new_corner) |
|
|
|
cornerA = edgeA.x[1] if l2_distance(edgeA.x[0].x, intersection_loc) < l2_distance(edgeA.x[1].x, |
|
intersection_loc) \ |
|
else edgeA.x[0] |
|
cornerB = edgeB.x[1] if l2_distance(edgeB.x[0].x, intersection_loc) < l2_distance(edgeB.x[1].x, |
|
intersection_loc) \ |
|
else edgeB.x[0] |
|
|
|
|
|
if l2_distance(cornerA.x, new_corner.x) < 12: |
|
continue |
|
if l2_distance(cornerB.x, new_corner.x) < 12: |
|
continue |
|
|
|
flag = False |
|
for edge_ele in new_graph.getEdges(): |
|
if new_corner in edge_ele.x and cornerA in edge_ele.x: |
|
flag = True |
|
break |
|
if edge_ele.x[0] not in (new_corner, cornerA): |
|
l = get_distance_of_corner_and_edge(new_corner.x, cornerA.x, edge_ele.x[0].x) |
|
if l <= 7: |
|
flag = True |
|
break |
|
if edge_ele.x[1] not in (new_corner, cornerA): |
|
l = get_distance_of_corner_and_edge(new_corner.x, cornerA.x, edge_ele.x[1].x) |
|
if l <= 7: |
|
flag = True |
|
break |
|
if flag: |
|
continue |
|
add_edgeA = new_candidate.addEdge(new_corner, cornerA) |
|
if new_graph.checkIntersectionEdge(add_edgeA): |
|
continue |
|
|
|
flag = False |
|
for edge_ele in new_graph.getEdges(): |
|
if new_corner in edge_ele.x and cornerB in edge_ele.x: |
|
flag = True |
|
break |
|
if edge_ele.x[0] not in (new_corner, cornerB): |
|
l = get_distance_of_corner_and_edge(new_corner.x, cornerB.x, edge_ele.x[0].x) |
|
if l <= 7: |
|
flag = True |
|
break |
|
if edge_ele.x[1] not in (new_corner, cornerB): |
|
l = get_distance_of_corner_and_edge(new_corner.x, cornerB.x, edge_ele.x[1].x) |
|
if l <= 7: |
|
flag = True |
|
break |
|
if flag: |
|
continue |
|
add_edgeB = new_candidate.addEdge(new_corner, cornerB) |
|
if new_graph.checkIntersectionEdge(add_edgeB): |
|
continue |
|
|
|
new_candidates.append(new_candidate) |
|
return new_candidates |
|
|
|
|
|
def adding_a_orthogonal_edge(candidate): |
|
new_candidates = [] |
|
graph = candidate.graph |
|
edges = candidate.graph.getEdges() |
|
for edge in edges: |
|
cornerA = edge.x[0] |
|
cornerB = edge.x[1] |
|
|
|
|
|
dir_ = (cornerA.x[1] - cornerB.x[1], cornerB.x[0] - cornerA.x[0]) |
|
|
|
for the_corner in edge.x: |
|
temp_orth_loc = (the_corner.x[0] - dir_[0], the_corner.x[1] - dir_[1]) |
|
for inter_edge in edges: |
|
if inter_edge == edge: |
|
continue |
|
if the_corner in inter_edge.x: |
|
continue |
|
intersection_loc = get_two_edge_intersection_location( |
|
the_corner.x, temp_orth_loc, inter_edge.x[0].x, inter_edge.x[1].x |
|
) |
|
if intersection_loc[0] >= 255 or intersection_loc[1] >= 255 or \ |
|
intersection_loc[0] <= 0 or intersection_loc[1] <= 0: |
|
continue |
|
if np.dot((inter_edge.x[0].x[0] - intersection_loc[0], inter_edge.x[0].x[1] - intersection_loc[1]), |
|
(inter_edge.x[1].x[0] - intersection_loc[0], inter_edge.x[1].x[1] - intersection_loc[1])) > 0: |
|
|
|
continue |
|
if l2_distance(intersection_loc, inter_edge.x[0].x) < 5 or \ |
|
l2_distance(intersection_loc, inter_edge.x[1].x) < 5: |
|
continue |
|
|
|
|
|
flag = False |
|
neighbor_corners = graph.getNeighborCorner(the_corner) |
|
for corner_ele in neighbor_corners: |
|
if corner_ele in edge.x: |
|
continue |
|
if degree_of_three_corners(corner_ele.x, intersection_loc, the_corner.x) < 15: |
|
flag = True |
|
break |
|
if degree_of_three_corners(corner_ele.x, intersection_loc, the_corner.x) > 165: |
|
flag = True |
|
break |
|
if flag: |
|
continue |
|
|
|
new_candidate = candidate.copy() |
|
new_graph = new_candidate.graph |
|
new_corner = Element(intersection_loc) |
|
if new_candidate.addable(new_corner) is False: |
|
continue |
|
new_corner = new_candidate.addCorner_v2(new_corner) |
|
|
|
|
|
if l2_distance(new_corner.x, the_corner.x) < 7: |
|
continue |
|
|
|
add_edge = new_candidate.addEdge(new_corner, new_graph.getRealElement(the_corner)) |
|
if new_graph.checkIntersectionEdge(add_edge): |
|
continue |
|
|
|
new_candidates.append(new_candidate) |
|
return new_candidates |
|
|
|
|
|
class _thread(threading.Thread): |
|
def __init__(self, threadID, name, candidate, lock, result_list, func): |
|
threading.Thread.__init__(self) |
|
self.threadID = threadID |
|
self.name = name |
|
self.candidate = candidate |
|
self.lock = lock |
|
self.result_list = result_list |
|
self.func = func |
|
|
|
def run(self): |
|
print('running id: ', self.name) |
|
start_time = time.time() |
|
candidates = self.func(self.candidate) |
|
print('test: =================================', self.name, len(candidates)) |
|
self.lock.acquire() |
|
self.result_list.extend(candidates) |
|
self.lock.release() |
|
print(self.name, "spend time: {}s".format(time.time() - start_time)) |
|
|
|
|
|
def candidate_enumerate_training(candidate, gt): |
|
new_candidates = [] |
|
|
|
try: |
|
new_ = removing_a_corner_operation(candidate) |
|
if len(new_) > 0: |
|
new_candidates.append(random.choice(new_)) |
|
except: |
|
print('something wrong with remove a corner !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!') |
|
|
|
|
|
try: |
|
new_ = removing_a_colinear_corner_operation(candidate) |
|
if len(new_) > 0: |
|
new_candidates.append(random.choice(new_)) |
|
except: |
|
print('something wrong with remove a colinear corner !!!!!!!!!!!!!!!!!!!!!!!!!!!') |
|
|
|
|
|
try: |
|
new_ = removing_an_edge_operation(candidate) |
|
if len(new_) > 0: |
|
new_candidates.append(random.choice(new_)) |
|
except: |
|
print('something wrong with remove an edge !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!') |
|
|
|
|
|
try: |
|
new_ = adding_an_edge_operation(candidate) |
|
if len(new_) > 0: |
|
new_candidates.append(random.choice(new_)) |
|
except: |
|
print('something wrong with add an edge from existed corner !!!!!!!!!!!!!!!!!!!!') |
|
|
|
|
|
try: |
|
new_ = adding_a_corner_from_two_edges_extension(candidate) |
|
if len(new_) > 0: |
|
new_candidates.append(random.choice(new_)) |
|
except: |
|
print('something wrong with add a corner from two edges !!!!!!!!!!!!!!!!!!!!!!!!') |
|
|
|
try: |
|
new_ = adding_a_corner_from_parallel(candidate) |
|
if len(new_) > 0: |
|
new_candidates.append(random.choice(new_)) |
|
except: |
|
print('something wrong with add a corner from parallel !!!!!!!!!!!!!!!!!!!!!!!!') |
|
|
|
|
|
try: |
|
new_ = adding_an_edge_from_gt(candidate, gt) |
|
if len(new_) > 0: |
|
new_candidates.append(random.choice(new_)) |
|
except: |
|
print('something wrong with add an edge from gt !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!') |
|
|
|
|
|
try: |
|
new_ = adding_a_orthogonal_edge(candidate) |
|
if len(new_) > 0: |
|
new_candidates.append(random.choice(new_)) |
|
except: |
|
print('something wrong with add a orthogonal edge !!!!!!!!!!!!!!!!!!!!!!!!!!!!!') |
|
return new_candidates |
|
|
|
|
|
def candidate_enumerate(candidate): |
|
new_candidates = [] |
|
new_candidates.extend(removing_a_corner_operation(candidate)) |
|
new_candidates.extend(removing_a_colinear_corner_operation(candidate)) |
|
new_candidates.extend(removing_an_edge_operation(candidate)) |
|
new_candidates.extend(adding_an_edge_operation(candidate)) |
|
new_candidates.extend(adding_a_corner_from_two_edges_extension(candidate)) |
|
new_candidates.extend(adding_a_corner_from_parallel(candidate)) |
|
new_candidates.extend(adding_a_orthogonal_edge(candidate)) |
|
|
|
return new_candidates |
|
|
|
|
|
def candidate_enumerate_thread(candidate): |
|
new_candidates = [] |
|
lock = threading.Lock() |
|
|
|
thread1 = _thread(1, 'remove_a_corner', candidate, lock, new_candidates, removing_a_corner_operation) |
|
thread2 = _thread(2, 'remove_a_colinear_corner', candidate, lock, new_candidates, |
|
removing_a_colinear_corner_operation) |
|
thread3 = _thread(3, 'add_an_edge', candidate, lock, new_candidates, adding_an_edge_operation) |
|
thread4 = _thread(4, 'remove_an_edge', candidate, lock, new_candidates, removing_an_edge_operation) |
|
|
|
thread1.start() |
|
thread2.start() |
|
thread3.start() |
|
thread4.start() |
|
|
|
threads = [] |
|
threads.append(thread1) |
|
threads.append(thread2) |
|
threads.append(thread3) |
|
threads.append(thread4) |
|
|
|
for t in threads: |
|
t.join() |
|
|
|
return new_candidates |
|
|
|
|
|
def reduce_duplicate_candidate(candidates): |
|
i = 0 |
|
while i < len(candidates): |
|
for j in reversed(range(i + 1, len(candidates))): |
|
if candidates[i].equal(candidates[j]): |
|
del candidates[j] |
|
i = i + 1 |
|
return candidates |
|
|
|
|
|
def save_candidate_image(candidate, base_path, base_name): |
|
corners = candidate.graph.getCornersArray() |
|
edges = candidate.graph.getEdgesArray() |
|
|
|
svg = svg_generate(corners, edges, base_name, samecolor=True) |
|
svg.saveas(os.path.join(base_path, base_name + '.svg')) |
|
|
|
temp_mask = np.zeros((256, 256)) |
|
for ele in candidate.graph.getCorners(): |
|
if ele.get_score() < 0: |
|
temp_mask = cv2.circle(temp_mask, ele.x[::-1], 3, 1, -1) |
|
fig = plt.figure(frameon=False) |
|
fig.set_size_inches(1, 1) |
|
ax = plt.Axes(fig, [0., 0., 1., 1.]) |
|
ax.set_axis_off() |
|
fig.add_axes(ax) |
|
ax.imshow(temp_mask, aspect='auto') |
|
fig.savefig(os.path.join(base_path, base_name + '_corner.png'), dpi=256) |
|
|
|
temp_mask = np.zeros((256, 256)) |
|
for ele in candidate.graph.getEdges(): |
|
if ele.get_score() < 0: |
|
A = ele.x[0] |
|
B = ele.x[1] |
|
temp_mask = cv2.line(temp_mask, A.x[::-1], B.x[::-1], 1, thickness=1) |
|
ax.imshow(temp_mask, aspect='auto') |
|
fig.savefig(os.path.join(base_path, base_name + '_edge.png'), dpi=256) |
|
|
|
plt.close() |
|
|
|
|
|
|
|
|
|
|
|
|
|
class Element: |
|
def __init__(self, x, safe_count=0): |
|
assert type(x) is tuple |
|
assert type(x[0]) == int or type(x[0]) == Element |
|
assert type(x[1]) == int or type(x[1]) == Element |
|
self.x = x |
|
self.__score = None |
|
self.safe_count = safe_count |
|
|
|
def store_score(self, score): |
|
self.__score = score |
|
|
|
def get_score(self): |
|
return self.__score |
|
|
|
def equal(self, ele): |
|
if type(self.x[0]) != type(ele.x[0]): |
|
return False |
|
if type(self.x[0]) == int: |
|
|
|
return True if self.x[0] == ele.x[0] and self.x[1] == ele.x[1] else False |
|
if type(self.x[0]) == Element: |
|
|
|
if self.x[0].equal(ele.x[0]) and self.x[1].equal(ele.x[1]): |
|
return True |
|
if self.x[1].equal(ele.x[0]) and self.x[0].equal(ele.x[1]): |
|
return True |
|
return False |
|
raise BaseException('no implement type') |
|
|
|
|
|
class regionCache(): |
|
def __init__(self, datapath): |
|
self.cache = {} |
|
self.datapath = datapath |
|
|
|
def get_region(self, name): |
|
if name in self.cache.keys(): |
|
return self.cache[name] |
|
gt_mask = np.load(os.path.join(self.datapath, name + '.npy')) |
|
if len(self.cache) == 5: |
|
self.cache.pop(list(self.cache.keys())[0]) |
|
self.cache[name] = gt_mask |
|
return gt_mask |
|
|
|
|
|
class imgCache(): |
|
def __init__(self, datapath): |
|
self.cache = {} |
|
self.datapath = datapath |
|
|
|
def get_image(self, name): |
|
if name in self.cache.keys(): |
|
return self.cache[name] |
|
img = skimage.img_as_float(plt.imread(os.path.join(self.datapath, 'rgb', name + '.jpg'))) |
|
if len(self.cache) == 5: |
|
self.cache.pop(list(self.cache.keys())[0]) |
|
self.cache[name] = img |
|
return img |
|
|
|
|
|
class Graph: |
|
def __init__(self, corners, edges): |
|
corners, edges = sort_graph(corners, edges) |
|
|
|
self.__corners = [] |
|
for corner_i in range(corners.shape[0]): |
|
self.__corners.append( |
|
Element( |
|
tuple( |
|
(int(corners[corner_i, 0]), int(corners[corner_i, 1])) |
|
) |
|
) |
|
) |
|
self.__edges = [] |
|
for edge_i in range(edges.shape[0]): |
|
self.__edges.append(Element((self.__corners[edges[edge_i, 0]], self.__corners[edges[edge_i, 1]]))) |
|
self.__regions = [] |
|
self.__regions.append(Element((0, 0))) |
|
|
|
@classmethod |
|
def initialFromTuple(cls, corners, edges): |
|
edge_index = [] |
|
for item in edges: |
|
a = corners.index(item[0]) |
|
b = corners.index(item[1]) |
|
edge_index.append((a, b)) |
|
edge_index = np.array(edge_index) |
|
corners = np.array(corners) |
|
return cls(corners, edge_index) |
|
|
|
def store_score(self, corner_score=None, edge_score=None, region_score=None): |
|
''' |
|
:param corner_score: np array size: len(corners) |
|
:param edge_score: np array size: len(edges) |
|
:param region_score: np.array size: len(regions) |
|
:return: |
|
''' |
|
if corner_score is not None: |
|
for idx, element in enumerate(self.__corners): |
|
element.store_score(corner_score[idx]) |
|
if edge_score is not None: |
|
for idx, element in enumerate(self.__edges): |
|
element.store_score(edge_score[idx]) |
|
if region_score is not None: |
|
for idx, element in enumerate(self.__regions): |
|
element.store_score(region_score[idx]) |
|
return |
|
|
|
def getCornersArray(self): |
|
c = [] |
|
for ele in self.__corners: |
|
c.append(ele.x) |
|
return np.array(c) |
|
|
|
def getEdgesArray(self): |
|
c = [] |
|
for ele in self.__edges: |
|
corner1 = ele.x[0] |
|
corner2 = ele.x[1] |
|
idx1 = self.__corners.index(corner1) |
|
idx2 = self.__corners.index(corner2) |
|
c.append([idx1, idx2]) |
|
return np.array(c) |
|
|
|
def getCorners(self): |
|
return self.__corners |
|
|
|
def getRegions(self): |
|
return self.__regions |
|
|
|
def getEdges(self): |
|
return self.__edges |
|
|
|
def graph_score(self): |
|
corner_score = 0 |
|
for ele in self.__corners: |
|
corner_score += ele.get_score() |
|
edge_score = 0 |
|
for ele in self.__edges: |
|
edge_score += ele.get_score() |
|
region_score = 0 |
|
for ele in self.__regions: |
|
region_score += ele.get_score() |
|
return score_weights[0] * corner_score + score_weights[1] * edge_score + score_weights[2] * region_score |
|
|
|
def corner_score(self): |
|
corner_score = 0 |
|
for ele in self.__corners: |
|
corner_score += ele.get_score() |
|
return corner_score |
|
|
|
def edge_score(self): |
|
edge_score = 0 |
|
for ele in self.__edges: |
|
edge_score += ele.get_score() |
|
return edge_score |
|
|
|
def region_score(self): |
|
region_score = 0 |
|
for ele in self.__regions: |
|
region_score += ele.get_score() |
|
return region_score |
|
|
|
def remove(self, ele): |
|
''' |
|
:param ele: remove eles as well as some other related elements |
|
:return: set() of removed elements |
|
''' |
|
|
|
removed = set() |
|
if ele in self.__corners: |
|
self.__corners.remove(ele) |
|
removed.add(ele) |
|
|
|
for idx in reversed(range(len(self.__edges))): |
|
edge_ele = self.__edges[idx] |
|
if ele in edge_ele.x: |
|
removed = removed.union(self.remove(edge_ele)) |
|
|
|
elif ele in self.__edges: |
|
self.__edges.remove(ele) |
|
removed.add(ele) |
|
corner1 = ele.x[0] |
|
corner2 = ele.x[1] |
|
if corner1.safe_count == 0: |
|
|
|
_count = 0 |
|
for edge_ele in self.__edges: |
|
if corner1 in edge_ele.x: |
|
_count += 1 |
|
if _count == 0: |
|
removed = removed.union(self.remove(corner1)) |
|
if corner2.safe_count == 0: |
|
|
|
_count = 0 |
|
for edge_ele in self.__edges: |
|
if corner2 in edge_ele.x: |
|
_count += 1 |
|
if _count == 0: |
|
removed = removed.union(self.remove(corner2)) |
|
return removed |
|
|
|
def has_edge(self, ele1, ele2): |
|
""" |
|
:param ele1: corner1 |
|
:param ele2: corner2 |
|
:return: edge or none |
|
""" |
|
for edge_ele in self.__edges: |
|
if ele1 in edge_ele.x and ele2 in edge_ele.x: |
|
return edge_ele |
|
return None |
|
|
|
def add_edge(self, ele1, ele2): |
|
temp = self.has_edge(ele1, ele2) |
|
if temp is not None: |
|
temp.safe_count = SAFE_NUM |
|
return temp |
|
new_ele = Element((ele1, ele2), safe_count=SAFE_NUM) |
|
self.__edges.append(new_ele) |
|
return new_ele |
|
|
|
def add_corner(self, ele): |
|
for corner in self.__corners: |
|
if corner.x == ele.x: |
|
corner.safe_count = SAFE_NUM |
|
return corner |
|
ele.safe_count = SAFE_NUM |
|
self.__corners.append(ele) |
|
return ele |
|
|
|
def add_corner_v2(self, ele): |
|
|
|
|
|
for corner in self.__corners: |
|
if l2_distance(corner.x, ele.x) < 5: |
|
corner.safe_count = SAFE_NUM |
|
return corner |
|
min_d = 256 |
|
the_edge = None |
|
for edge in self.__edges: |
|
temp = get_distance_of_corner_and_edge(edge.x[0].x, edge.x[1].x, ele.x) |
|
if temp < min_d: |
|
min_d = temp |
|
the_edge = edge |
|
if min_d < 3: |
|
|
|
corner1 = the_edge.x[0] |
|
corner2 = the_edge.x[1] |
|
new_ele = Element((corner1, ele), safe_count=the_edge.safe_count) |
|
self.__edges.append(new_ele) |
|
new_ele = Element((corner2, ele), safe_count=the_edge.safe_count) |
|
self.__edges.append(new_ele) |
|
self.__edges.remove(the_edge) |
|
ele.safe_count = SAFE_NUM |
|
self.__corners.append(ele) |
|
return ele |
|
|
|
def checkColinearCorner(self, ele): |
|
if self.getCornerDegree(ele) != 2: |
|
return False |
|
edge_in = [] |
|
for edge_ele in self.__edges: |
|
if ele in edge_ele.x: |
|
edge_in.append(edge_ele) |
|
if len(edge_in) == 2: |
|
break |
|
two_neighbor = {edge_in[0].x[0], edge_in[0].x[1], edge_in[1].x[0], edge_in[1].x[1]} |
|
two_neighbor.remove(ele) |
|
two_neighbor = tuple(two_neighbor) |
|
if self.has_edge(two_neighbor[0], two_neighbor[1]) is not None: |
|
return False |
|
|
|
line1 = np.array(ele.x) - np.array(two_neighbor[0].x) |
|
line2 = np.array(two_neighbor[1].x) - np.array(ele.x) |
|
cos = np.dot(line1, line2) / (np.linalg.norm(line1) * np.linalg.norm(line2)) |
|
cos = min(1, max(-1, cos)) |
|
if np.arccos(cos) < np.pi / 9: |
|
return True |
|
return False |
|
|
|
def checkIntersectionEdge(self, ele=None): |
|
if ele is None: |
|
for edge_i in range(len(self.__edges)): |
|
for edge_j in range(edge_i + 1, len(self.__edges)): |
|
if check_intersection(self.__edges[edge_i], self.__edges[edge_j]): |
|
return True |
|
return False |
|
for edge_ele in self.__edges: |
|
if ele == edge_ele: |
|
continue |
|
if check_intersection(edge_ele, ele): |
|
return True |
|
return False |
|
|
|
def getCornerDegree(self, ele): |
|
degree = 0 |
|
for edge_ele in self.__edges: |
|
if ele in edge_ele.x: |
|
degree += 1 |
|
return degree |
|
|
|
def getEdgeConnected(self, ele): |
|
out_ = set() |
|
if type(ele.x[0]) == int: |
|
|
|
for edge_ele in self.__edges: |
|
if ele in edge_ele.x: |
|
out_.add(edge_ele) |
|
return out_ |
|
if type(ele.x[0]) == Element: |
|
|
|
out_ = out_.union(self.getEdgeConnected(ele.x[0])) |
|
out_ = out_.union(self.getEdgeConnected(ele.x[1])) |
|
if ele in out_: |
|
out_.remove(ele) |
|
return out_ |
|
|
|
def getNeighborCorner(self, ele): |
|
out_ = set() |
|
for edge_ele in self.__edges: |
|
if ele == edge_ele.x[0]: |
|
out_.add(edge_ele.x[1]) |
|
if ele == edge_ele.x[1]: |
|
out_.add(edge_ele.x[0]) |
|
return out_ |
|
|
|
def getRealElement(self, ele): |
|
|
|
if type(ele.x[0]) == Element: |
|
for e in self.__edges: |
|
if (e.x[0].x == ele.x[0].x and e.x[1].x == ele.x[1].x) or \ |
|
(e.x[1].x == ele.x[0].x and e.x[0].x == ele.x[1].x): |
|
return e |
|
raise BaseException("no same edge exists.") |
|
|
|
elif type(ele.x[0]) == int: |
|
for c in self.__corners: |
|
if c.x == ele.x: |
|
return c |
|
raise BaseException("no same corner exists.") |
|
|
|
def copy(self): |
|
corners = self.getCornersArray() |
|
edges = self.getEdgesArray() |
|
new_graph = Graph(corners, edges) |
|
for idx, ele in enumerate(self.__corners): |
|
new_graph.__corners[idx].store_score(self.__corners[idx].get_score()) |
|
for idx, ele in enumerate(self.__edges): |
|
new_graph.__edges[idx].store_score(self.__edges[idx].get_score()) |
|
for idx, ele in enumerate(self.__regions): |
|
new_graph.__regions[idx].store_score(self.__regions[idx].get_score) |
|
return new_graph |
|
|
|
def update_safe_count(self): |
|
for ele in self.__corners: |
|
if ele.safe_count > 0: |
|
ele.safe_count -= 1 |
|
for ele in self.__edges: |
|
if ele.safe_count > 0: |
|
ele.safe_count -= 1 |
|
|
|
def isNeighbor(self, element1, element2): |
|
''' |
|
:param element1: |
|
:param element2: |
|
:return: True / False |
|
''' |
|
if element1 == element2: |
|
return False |
|
if type(element1.x[0]) != type(element2.x[0]): |
|
|
|
return False |
|
if type(element1.x[0]) == int: |
|
|
|
for edge_ele in self.__edges: |
|
if edge_ele.x[0] == element1 and edge_ele.x[1] == element2: |
|
return True |
|
if edge_ele.x[0] == element2 and edge_ele.x[1] == element1: |
|
return True |
|
return False |
|
if type(element1.x[0]) == Element: |
|
|
|
if len({element1.x[0], element1.x[1], element2.x[0], element2.x[1]}) < 4: |
|
return True |
|
return False |
|
|
|
def equal(self, graph): |
|
if len(self.__corners) != len(graph.__corners) or \ |
|
len(self.__edges) != len(graph.__edges): |
|
return False |
|
for corner_i in range(len(self.__corners)): |
|
if self.__corners[corner_i].equal(graph.__corners[corner_i]) is False: |
|
return False |
|
for edge_i in range(len(self.__edges)): |
|
if self.__edges[edge_i].equal(graph.__edges[edge_i]) is False: |
|
return False |
|
|
|
return True |
|
|
|
|
|
class Candidate: |
|
def __init__(self, graph, name, corner_existed_before, edge_existed_before): |
|
''' |
|
:param graph: Class graph |
|
:param name: string, data name |
|
:param corner_existed_before: dict {(x_i,y_i):c_1 ...} indicates counts for corresponding corners, after one search, |
|
counts -= 1, if count == 0, remove from the set. |
|
:param edge_existed_before: dict {((x_i1,y_i1),(x_i2,y_i2)):ci} |
|
''' |
|
self.graph = graph |
|
self.name = name |
|
self.corner_existed_before = corner_existed_before |
|
self.edge_existed_before = edge_existed_before |
|
|
|
@classmethod |
|
def initial(cls, graph, name): |
|
return cls(graph, name, {}, {}) |
|
|
|
def update(self): |
|
|
|
for key in self.corner_existed_before.keys(): |
|
self.corner_existed_before[key] -= 1 |
|
for key in self.edge_existed_before.keys(): |
|
self.edge_existed_before[key] -= 1 |
|
|
|
|
|
for key in list(self.corner_existed_before.keys()): |
|
if self.corner_existed_before[key] == 0: |
|
self.corner_existed_before.pop(key) |
|
|
|
for key in list(self.edge_existed_before.keys()): |
|
if self.edge_existed_before[key] == 0: |
|
self.edge_existed_before.pop(key) |
|
|
|
|
|
self.graph.update_safe_count() |
|
|
|
def copy(self): |
|
corner_existed_before = self.corner_existed_before.copy() |
|
edge_existed_before = self.edge_existed_before.copy() |
|
new_graph = self.graph.copy() |
|
return Candidate(new_graph, self.name, corner_existed_before, edge_existed_before) |
|
|
|
def removable(self, ele): |
|
''' |
|
:param x: input is element |
|
:return: |
|
''' |
|
assert type(ele) == Element |
|
|
|
return True if ele.safe_count == 0 else False |
|
|
|
def addable(self, ele): |
|
if type(ele) == Element: |
|
if type(ele.x[0]) == Element: |
|
|
|
for edge in self.graph.getEdges(): |
|
c1 = edge.x[0] |
|
c2 = edge.x[1] |
|
if (ele.x[0].x == c1.x and ele.x[1].x == c2.x) or \ |
|
(ele.x[1].x == c1.x and ele.x[0].x == c2.x): |
|
|
|
return False |
|
corner1_loc = ele.x[0].x |
|
corner2_loc = ele.x[1].x |
|
if (corner1_loc, corner2_loc) in self.edge_existed_before.keys() or \ |
|
(corner2_loc, corner1_loc) in self.edge_existed_before.keys(): |
|
return False |
|
return True |
|
else: |
|
|
|
for corner in self.graph.getCorners(): |
|
if l2_distance(ele.x, corner.x) < TWO_CORNER_MINIMUM_DISTANCE: |
|
|
|
return False |
|
if ele.x in self.corner_existed_before.keys(): |
|
return False |
|
return True |
|
else: |
|
if type(ele[0]) == tuple: |
|
|
|
corner1_loc = ele[0] |
|
corner2_loc = ele[1] |
|
for edge in self.graph.getEdges(): |
|
c1 = edge.x[0] |
|
c2 = edge.x[1] |
|
if (corner1_loc == c1.x and corner2_loc == c2.x) or \ |
|
(corner2_loc == c1.x and corner1_loc == c2.x): |
|
|
|
return False |
|
if (corner1_loc, corner2_loc) in self.edge_existed_before.keys() or \ |
|
(corner2_loc, corner1_loc) in self.edge_existed_before.keys(): |
|
return False |
|
return True |
|
else: |
|
|
|
for corner in self.graph.getCorners(): |
|
if l2_distance(ele, corner.x) < TWO_CORNER_MINIMUM_DISTANCE: |
|
|
|
return False |
|
if ele in self.corner_existed_before.keys(): |
|
return False |
|
return True |
|
|
|
def addCorner(self, ele): |
|
if ele.x in self.corner_existed_before.keys(): |
|
raise BaseException('cannot add the corner') |
|
new_ele = self.graph.add_corner(ele) |
|
return new_ele |
|
|
|
def addCorner_v2(self, ele): |
|
if ele.x in self.corner_existed_before.keys(): |
|
raise BaseException('cannot add the corner') |
|
new_ele = self.graph.add_corner_v2(ele) |
|
return new_ele |
|
|
|
def addEdge(self, ele1, ele2): |
|
corner1 = ele1 |
|
corner2 = ele2 |
|
assert corner1 in self.graph.getCorners() |
|
assert corner2 in self.graph.getCorners() |
|
if (corner1.x, corner2.x) in self.edge_existed_before.keys() or \ |
|
(corner2.x, corner1.x) in self.edge_existed_before.keys(): |
|
raise BaseException('cannot add the edge') |
|
new_ele = self.graph.add_edge(corner1, corner2) |
|
return new_ele |
|
|
|
def removeCorner(self, ele): |
|
if ele.x in self.corner_existed_before.keys(): |
|
raise BaseException('already existed.') |
|
self.corner_existed_before[ele.x] = SAFE_NUM |
|
|
|
def removeEdge(self, ele): |
|
corner1 = ele.x[0] |
|
corner2 = ele.x[1] |
|
loc1 = corner1.x |
|
loc2 = corner2.x |
|
if (loc1[0] > loc2[0]) or (loc1[0] == loc2[0] and loc1[1] > loc2[1]): |
|
loc1 = corner2.x |
|
loc2 = corner1.x |
|
if (loc1, loc2) in self.edge_existed_before.keys(): |
|
raise BaseException('already existed.') |
|
self.edge_existed_before[(loc1, loc2)] = SAFE_NUM |
|
|
|
def generate_new_candidate_remove_a_colinear_corner(self, ele): |
|
|
|
new_candidate = self.copy() |
|
new_graph = new_candidate.graph |
|
ele = new_graph.getRealElement(ele) |
|
|
|
|
|
temp = set() |
|
for element in new_graph.getEdgeConnected(ele): |
|
|
|
if type(element.x[0]) == Element: |
|
temp.add(element.x[0]) |
|
temp.add(element.x[1]) |
|
temp.remove(ele) |
|
temp = tuple(temp) |
|
assert len(temp) == 2 |
|
|
|
|
|
|
|
|
|
added = new_graph.add_edge(temp[0], temp[1]) |
|
if (temp[0].x, temp[1].x) in self.edge_existed_before.keys(): |
|
self.edge_existed_before.pop((temp[0].x, temp[1].x)) |
|
if (temp[1].x, temp[0].x) in self.edge_existed_before.keys(): |
|
self.edge_existed_before.pop((temp[1].x, temp[0].x)) |
|
|
|
|
|
removed = new_graph.remove(ele) |
|
|
|
|
|
for element in removed: |
|
|
|
if type(element.x[0]) == Element: |
|
new_candidate.removeEdge(element) |
|
|
|
elif type(element.x[0]) == int: |
|
new_candidate.removeCorner(element) |
|
else: |
|
raise BaseException('wrong type.') |
|
|
|
|
|
|
|
for element in new_graph.getCorners(): |
|
element.store_score(None) |
|
|
|
|
|
for element in new_graph.getEdges(): |
|
for modified_ele in removed.union({added}): |
|
if new_graph.isNeighbor(element, modified_ele): |
|
element.store_score(None) |
|
break |
|
|
|
|
|
for element in new_graph.getRegions(): |
|
element.store_score(None) |
|
|
|
return new_candidate |
|
|
|
def generate_new_candidate_remove_a_corner(self, ele): |
|
|
|
new_candidate = self.copy() |
|
new_graph = new_candidate.graph |
|
ele = new_graph.getRealElement(ele) |
|
removed = new_graph.remove(ele) |
|
|
|
|
|
for element in removed: |
|
|
|
if type(element.x[0]) == Element: |
|
corner1 = element.x[0] |
|
corner2 = element.x[1] |
|
loc1 = corner1.x |
|
loc2 = corner2.x |
|
if (loc1[0] > loc2[0]) or (loc1[0] == loc2[0] and loc1[1] > loc2[1]): |
|
loc1 = corner2.x |
|
loc2 = corner1.x |
|
if (loc1, loc2) in self.edge_existed_before.keys(): |
|
raise BaseException('already existed.') |
|
new_candidate.edge_existed_before[(loc1, loc2)] = SAFE_NUM |
|
|
|
elif type(element.x[0]) == int: |
|
if element.x in self.corner_existed_before.keys(): |
|
raise BaseException('already existed.') |
|
new_candidate.corner_existed_before[element.x] = SAFE_NUM |
|
else: |
|
raise BaseException('wrong type.') |
|
|
|
|
|
|
|
for element in new_graph.getCorners(): |
|
element.store_score(None) |
|
|
|
|
|
for element in new_graph.getEdges(): |
|
for removed_ele in removed: |
|
if new_graph.isNeighbor(element, removed_ele): |
|
element.store_score(None) |
|
break |
|
|
|
|
|
for element in new_graph.getRegions(): |
|
element.store_score(None) |
|
|
|
return new_candidate |
|
|
|
def generate_new_candidate_add_an_edge(self, ele1, ele2): |
|
|
|
new_candidate = self.copy() |
|
new_graph = new_candidate.graph |
|
ele1 = new_graph.getRealElement(ele1) |
|
ele2 = new_graph.getRealElement(ele2) |
|
|
|
|
|
new_ele = new_candidate.addEdge(ele1, ele2) |
|
|
|
|
|
|
|
for element in new_graph.getCorners(): |
|
element.store_score(None) |
|
|
|
|
|
for element in new_graph.getEdges(): |
|
if new_graph.isNeighbor(element, new_ele): |
|
element.store_score(None) |
|
|
|
|
|
for element in new_graph.getRegions(): |
|
element.store_score(None) |
|
|
|
return new_candidate |
|
|
|
def generate_new_candidate_remove_an_edge(self, ele): |
|
|
|
new_candidate = self.copy() |
|
new_graph = new_candidate.graph |
|
ele = new_graph.getRealElement(ele) |
|
removed = new_graph.remove(ele) |
|
|
|
|
|
for element in removed: |
|
|
|
if type(element.x[0]) == Element: |
|
corner1 = element.x[0] |
|
corner2 = element.x[1] |
|
loc1 = corner1.x |
|
loc2 = corner2.x |
|
if (loc1[0] > loc2[0]) or (loc1[0] == loc2[0] and loc1[1] > loc2[1]): |
|
loc1 = corner2.x |
|
loc2 = corner1.x |
|
if (loc1, loc2) in self.edge_existed_before.keys(): |
|
raise BaseException('already existed.') |
|
new_candidate.edge_existed_before[(loc1, loc2)] = SAFE_NUM |
|
|
|
elif type(element.x[0]) == int: |
|
if element.x in self.corner_existed_before.keys(): |
|
raise BaseException('already existed.') |
|
new_candidate.corner_existed_before[element.x] = SAFE_NUM |
|
else: |
|
raise BaseException('wrong type.') |
|
|
|
|
|
|
|
for element in new_graph.getCorners(): |
|
element.store_score(None) |
|
|
|
|
|
for element in new_graph.getEdges(): |
|
for removed_ele in removed: |
|
if new_graph.isNeighbor(element, removed_ele): |
|
element.store_score(None) |
|
break |
|
|
|
|
|
for element in new_graph.getRegions(): |
|
element.store_score(None) |
|
|
|
return new_candidate |
|
|
|
def generate_new_candidate_add_a_new_triangle(self, ele_new, ele1, ele2): |
|
|
|
|
|
new_candidate = self.copy() |
|
new_graph = new_candidate.graph |
|
ele1 = new_graph.getRealElement(ele1) |
|
ele2 = new_graph.getRealElement(ele2) |
|
|
|
|
|
ele_new = new_candidate.addCorner(ele_new) |
|
|
|
|
|
|
|
|
|
new_candidate = new_candidate.generate_new_candidate_add_an_edge(ele_new, ele1) |
|
new_candidate = new_candidate.generate_new_candidate_add_an_edge(ele_new, ele2) |
|
|
|
return new_candidate |
|
|
|
def generate_new_candidate_add_a_corner(self, ele): |
|
|
|
new_candidate = self.copy() |
|
new_graph = new_candidate.graph |
|
|
|
|
|
ele = new_candidate.addCorner(ele) |
|
|
|
|
|
|
|
for element in new_graph.getCorners(): |
|
element.store_score(None) |
|
|
|
|
|
|
|
for element in new_graph.getRegions(): |
|
element.store_score(None) |
|
|
|
return new_candidate |
|
|
|
def equal(self, candidate): |
|
return self.graph.equal(candidate.graph) |
|
|