@@ -35,7 +35,7 @@ def load(self, path):
self.validation_data_path.append(path)
label_file = tuple(filter(lambda x: 'txt' in x, os.listdir(path)))
if len(label_file) != 1:
raise FileNotFoundError("Invalid path: {}".format(path))
raise FileNotFoundError("Invalid path (not text file is there): {}".format(path))
with open("{}/{}".format(path, label_file[0]), mode='r') as csvfile:
reader = csv.DictReader(csvfile, dialect="excel-tab")
for row in reader:
@@ -102,7 +102,6 @@ def calc_stats(self, dataset_id, path, *args):
if bool(int(self.validation_data[dataset_id][file]['gate'])) == gate_det:
if bool(int(self.validation_data[dataset_id][file]['gate'])):
# Gate is present and detected
self.current_result[dataset_id][file]["GD"] = "TP"
self.current_result[dataset_id][file]["x0"] = abs(p0[0] - float(self.validation_data[dataset_id][file]["x0"]))
self.current_result[dataset_id][file]["x1"] = abs(p1[0] - float(self.validation_data[dataset_id][file]["x1"]))
self.current_result[dataset_id][file]["x2"] = abs(p2[0] - float(self.validation_data[dataset_id][file]["x2"]))
@@ -111,6 +110,15 @@ def calc_stats(self, dataset_id, path, *args):
self.current_result[dataset_id][file]["y1"] = abs(p1[1] - float(self.validation_data[dataset_id][file]["y1"]))
self.current_result[dataset_id][file]["y2"] = abs(p2[1] - float(self.validation_data[dataset_id][file]["y2"]))
self.current_result[dataset_id][file]["y3"] = abs(p3[1] - float(self.validation_data[dataset_id][file]["y3"]))
x_list = tuple(filter(lambda x: x is not None, [i if float(self.validation_data[dataset_id][file]["x" + str(i)]) != 0 else None for i in range(4)]))
y_list = tuple(filter(lambda x: x is not None, [i if float(self.validation_data[dataset_id][file]["y" + str(i)]) != 0 else None for i in range(4)]))
xs = [self.current_result[dataset_id][file]["x"+str(i)] for i in x_list]
ys = [self.current_result[dataset_id][file]["y"+str(i)] for i in y_list]
if np.max(xs) >50 or np.max(ys) > 50:
self.current_result[dataset_id][file]["GD"] = "FN"
else:
self.current_result[dataset_id][file]["GD"] = "TP"

else:
# Gate is absent and not detected
self.current_result[dataset_id][file]["GD"] = "TN"
@@ -181,21 +189,37 @@ def __str__(self):


if __name__ == "__main__":
# harris 26.66
# template 33.33
path2 = "../data/cad_renders2_dist"
path_bg = "../data/backgrounds"
path3 = "../data/cad_renders3_dist"
path3 = "../data/cad_renders"
path5 = "../data/cad_renders5_dist"

# path6 = "/home/kit/projects/find-me/data/20June2/GateRenders360Rotation/GateRenders360Rotation_animation"
path_valid_35 = "../data/validation/3-5"
path_valid_360 = "../data/validation/3-60"
path_valid_53 = "../data/validation/5-3"
path_valid_560 = "../data/validation/5-60"
from src.template_matching import TemplateMatching
from src.harris_detector import Harris_detector

harrs = Harris_detector()

path_corners = "../data/corners"
tm = TemplateMatching()
tm.load_corners(path_corners)

b = Benchmark(tm)
b.load(path_valid_35)
b.load(path_valid_360)
b.load(path_valid_53)
b.load(path_valid_560)

# b.load(path_bg)
# b.load(path2)
# b.load(path3)
b.load(path5)
b.test(None, "cv2.TM_CCOEFF_NORMED", 0.95)
# b.load(path)
a = b.test(None, "cv2.TM_CCORR_NORMED", 0.95)
print(b)
b.false_positive_curve()
print(a)
# b.false_positive_curve()
@@ -0,0 +1,125 @@
import cv2
import numpy as np
import os
from shutil import copyfile
import random
from src.image_distr import DistortImages


def separate(path, save_path):
"""
This function separates object images from color images, in order to generate dataset for CNN.
:param path: str
:return: None
"""

if not os.path.exists(path):
raise FileNotFoundError("Invalid path: {}".format(path))

if not os.path.exists(save_path):
os.makedirs(save_path)
if not os.path.exists(os.path.join(save_path, "targets")):
os.makedirs(os.path.join(save_path, "targets"))
os.makedirs(os.path.join(save_path, 'inputs'))

for file_name in os.listdir(path):
if "_Object" in file_name:
f_name = os.path.join(save_path, "targets", file_name[:-len("_Object.jpg")] + file_name[-len(".jpg"):])
copyfile(os.path.join(path, file_name), f_name)
img = cv2.imread(f_name)
flip = cv2.flip(img, flipCode=0)
rever = cv2.rotate(img, rotateCode=cv2.ROTATE_180)
flip_name = os.path.join(save_path, "targets", file_name[:-len("_Object.jpg")] + "_flip" + file_name[-len(".jpg"):])
rever_name = os.path.join(save_path, "targets", file_name[:-len("_Object.jpg")] + "_revers" + file_name[-len(".jpg"):])
cv2.imwrite(flip_name, flip)
cv2.imwrite(rever_name, rever)
else:
f_name = os.path.join(save_path, "inputs", file_name)
copyfile(os.path.join(path, file_name), f_name)
img = cv2.imread(f_name)
flip = cv2.flip(img, flipCode=0)
rever = cv2.rotate(img, rotateCode=cv2.ROTATE_180)
flip_name = os.path.join(save_path, "inputs", file_name[:-len(".jpg")] + "_flip" + file_name[-len(".jpg"):])
rever_name = os.path.join(save_path, "inputs", file_name[:-len(".jpg")] + "_revers" + file_name[-len(".jpg"):])
cv2.imwrite(flip_name, flip)
cv2.imwrite(rever_name, rever)


def change_bg(load_bg, core_path, number_of_new):
bg_lst = []
for bg in filter(lambda x: 'txt' not in x, os.listdir(load_bg)):
bg_img = cv2.imread(os.path.join(load_bg, bg))
if bg_img is not None:
bg_img = cv2.resize(bg_img, (512, 288))

# print(bg_img)

assert bg_img.shape == (288, 512, 3)
# assert False
bg_lst.append(bg_img)

for i, image_name in enumerate(random.choices(os.listdir(os.path.join(core_path, 'inputs')), k=number_of_new)):
mask = cv2.imread(os.path.join(core_path, "targets", image_name), 0)
ret, mask = cv2.threshold(mask, 20,255, cv2.THRESH_BINARY)
img = cv2.imread(os.path.join(core_path, "inputs", image_name))
bg = random.choice(bg_lst)
mask_inv = cv2.bitwise_not(mask)
gate = cv2.bitwise_and(img, img, mask=mask)
new_bg = cv2.bitwise_and(bg, bg, mask=mask_inv)
new_gate_with_bg = new_bg + gate
new_f_name = image_name[:-4] + "random{:05d}".format(i) + image_name[-4:]
cv2.imwrite(os.path.join(core_path, "inputs", new_f_name), new_gate_with_bg)
cv2.imwrite(os.path.join(core_path, "targets", new_f_name), mask)


def jpeg_all_inputs(path):
d = DistortImages()
d.load(os.path.join(path, "inputs"), ".jpg")
d.distort(os.path.join(path, "inputs_mod"), compression=(10,), blur=((10,),(3,3)), gaussian_noise=((10,),))
for file_name in os.listdir(os.path.join(path, 'targets')):
new_name_compr = file_name[:-4] + "_compression{:03d}".format(10) + file_name[-4:]
new_name_blur = file_name[:-4] + "_blur{:03d}".format(10) + file_name[-4:]
new_name_noise = file_name[:-4] + "_gaussian_noise{:03d}".format(10) + file_name[-4:]
copyfile(os.path.join(path, 'targets', file_name), os.path.join(path, 'targets', new_name_compr))
copyfile(os.path.join(path, 'targets', file_name), os.path.join(path, 'targets', new_name_blur))
copyfile(os.path.join(path, 'targets', file_name), os.path.join(path, 'targets', new_name_noise))
# os.rename(os.path.join(path, 'targets', file_name), os.path.join(path, 'targets', new_name))
os.remove(os.path.join(path, 'targets', file_name))


def check(path):
inputs = os.listdir(os.path.join(path, 'inputs_mod'))
for file_name in os.listdir(os.path.join(path, 'targets')):
if file_name not in inputs:
print(file_name)
assert False
print("CHECK - OK")


def add_fake(from_path, save_path):
empty = np.zeros((288, 512, 3))
for img_name in os.listdir(from_path):
try:
img = cv2.imread(os.path.join(from_path, img_name))
# bg_img = cv2.resize(bg_img, (512, 288))
img = cv2.resize(img, (512, 288))
cv2.imwrite(os.path.join(save_path, "inputs_mod", img_name), img)
cv2.imwrite(os.path.join(save_path, "targets", img_name), empty)
except cv2.error:
print("REMOVED: ", img_name)
os.remove(os.path.join(from_path, img_name))


if __name__ == "__main__":
path_to_bg = "../data/all"
paths = "../data/20June2/"
to_path = "../data/cnn_data7"
# all_paths = os.listdir(paths)
# for path in all_paths:
# # print(os.listdir(os.path.join(paths, path)))
# folder_in_folder = os.listdir(os.path.join(paths, path))[0]
# separate(os.path.join(paths, path, folder_in_folder), to_path)
# change_bg(path_to_bg, to_path, 3000)
# jpeg_all_inputs(to_path)
# add_fake('../data/all', to_path)
check(to_path)
@@ -9,21 +9,18 @@
# TODO: Be able tochange Camera Center, shifts and rotations
# http://www.songho.ca/opengl/gl_projectionmatrix.html - Clear explanation of Perspective Frustum
# Gate information
CAMERA_RES = (1280, 720)

GATE_WIDTH = 1.4
FOV = 105 /2 * np.pi / 180
CAMERA_CENTER_PX = np.array([[1280 // 2 ], [ 720 // 2 ], [0]])
# SHIFT_Y = 0.15523613963039012
SHIFT_Y = 0.15
SHIFT_X = 0


# TODO : Change parameters (n,f to better values?)
# Camera planes parameters
n = 24.3 ** 10**-3 # Near plane
t = np.tan(FOV / 2 ) * n # right
r = 1280 / 720 * t # top
t = np.tan(FOV) * n # right
r = 512 / 288 * t # top
f = 10 # Far plane
scale = 1 / np.tan(FOV / 2)
# scale = 1 / np.tan(FOV /2)
# Perspective transformation matrix
M = np.array([[n / r, 0, 0, 0],
[0, n / t, 0, 0],
@@ -60,15 +57,22 @@ def get_corner(R, alpha, beta, POINT_REAL):
# point_real_rot = POINT_REAL - camera_pos
# point_real_rot = POINT_REAL
# print(rot_x(alpha*np.pi / 180) @ rot_y(beta*np.pi / 180) @ POINT_REAL)
point_real_rot = np.vstack((point_real_rot * np.tan(FOV/2)*R * 2 / 1280, 1))
point_real_rot = np.vstack((point_real_rot * np.tan(FOV/2)*R * 2 / 512, 1))
# print(point_real_rot)
c_c = M @ point_real_rot
# print(c_c)
corner = c_c[:3] / c_c[3]
return corner


def generate_label_file(path, ext, with_gate):
def generate_label_file(path, ext, with_gate,*,camera_res,shift_y, shift_x):
CAMERA_RES = camera_res
CAMERA_CENTER_PX = np.array([[CAMERA_RES[0] // 2], [CAMERA_RES[1] // 2], [0]])
# SHIFT_Y = 0.15523613963039012
# SHIFT_Y = -0.15
# SHIFT_X = 0.081451
SHIFT_Y = shift_y
SHIFT_X = shift_x
# gi = GeneralImage(path)
print("Generating corner position for {}".format(path))
stored_labels = []
@@ -81,12 +85,11 @@ def generate_label_file(path, ext, with_gate):
R = float(img_lab[key]['R'])
alpha = float(img_lab[key]['alpha'])
beta = float(img_lab[key]['beta'])

SHIFT_X = 0.*np.sin(beta*2)
POINT_REAL1 = np.array([[GATE_WIDTH / 2 - SHIFT_X], [GATE_WIDTH / 2 - SHIFT_Y], [-R]])
POINT_REAL2 = np.array([[-GATE_WIDTH / 2 - SHIFT_X], [GATE_WIDTH / 2 - SHIFT_Y], [-R]])
POINT_REAL3 = np.array([[-GATE_WIDTH / 2 - SHIFT_X], [-GATE_WIDTH / 2 - SHIFT_Y], [-R]])
POINT_REAL4 = np.array([[GATE_WIDTH / 2 - SHIFT_X], [-GATE_WIDTH / 2 - SHIFT_Y], [-R]])
SHIFT_X = shift_x*np.sin(beta*np.pi/180*2)
POINT_REAL1 = np.array([[GATE_WIDTH / 2 + SHIFT_X], [GATE_WIDTH / 2 + SHIFT_Y], [-R]])
POINT_REAL2 = np.array([[-GATE_WIDTH / 2 + SHIFT_X], [GATE_WIDTH / 2 + SHIFT_Y], [-R]])
POINT_REAL3 = np.array([[-GATE_WIDTH / 2 + SHIFT_X], [-GATE_WIDTH / 2 + SHIFT_Y], [-R]])
POINT_REAL4 = np.array([[GATE_WIDTH / 2 + SHIFT_X], [-GATE_WIDTH / 2 + SHIFT_Y], [-R]])

x1, y1, z1 = get_corner(R, alpha, beta, POINT_REAL1)
x2, y2, z2 = get_corner(R, alpha, beta, POINT_REAL2)
@@ -101,8 +104,8 @@ def generate_label_file(path, ext, with_gate):
# y2 = f * POINT_REAL2[1] / POINT_REAL2[2]
# y3 = f * POINT_REAL3[1] / POINT_REAL3[2]
# y4 = f * POINT_REAL4[1] / POINT_REAL4[2]
xs = np.array([x1, x4, x3, x2, x1])
ys = np.array([y1, y4, y3, y2, y1])
xs = 1280/512*np.array([x1, x4, x3, x2, x1])
ys = 1280/512*np.array([y1, y4, y3, y2, y1])

xs = CAMERA_CENTER_PX[0] + xs*CAMERA_RES[0] / 2 # TODO: change name
ys = CAMERA_CENTER_PX[1] + ys*CAMERA_RES[1] / 2
@@ -116,8 +119,8 @@ def generate_label_file(path, ext, with_gate):

plt.subplot(3, 3, counter)

plt.plot(xs, ys, color='red')

plt.plot(xs, ys, color='red',label=R)
plt.legend()
font = cv2.FONT_HERSHEY_SIMPLEX
img = cv2.imread(os.path.join(path, img_lab[key]["name"]))
cv2.putText(img, 'c0', (xs[0], ys[0]), font, 4, (255, 255, 255), 2, cv2.LINE_AA)
@@ -146,9 +149,14 @@ def generate_label_file(path, ext, with_gate):

def copy_images(from_path, to_path):
store_stash = []
for file_name in os.listdir(from_path):
import random
files = random.choices(os.listdir(from_path), k=15)
for file_name in files:
if file_name[-4:] != ".txt":
copyfile(os.path.join(from_path, file_name), os.path.join(to_path, file_name))
# copyfile(os.path.join(from_path, file_name), os.path.join(to_path, file_name))
img = cv2.imread(os.path.join(from_path, file_name))
img = cv2.resize(img, (512, 288))
cv2.imwrite(os.path.join(to_path, file_name), img)
else:
with open(os.path.join(from_path, file_name), mode='r') as csvfile:
reader = csv.DictReader(csvfile, dialect="excel-tab")
@@ -161,9 +169,21 @@ def copy_images(from_path, to_path):
writer.writerow(line)

if __name__ == "__main__":
bg_path = "../data/bg_less"
path_valid_35 = "../data/validation/3-5"
path_valid_360 = "../data/validation/3-60"
path_valid_53 = "..data/validation/5-3"
path_valid_560 = "../data/validation/5-60"
# for i in (2,3,5):
# path = "../data/cad_renders{}_dist".format(i)
# path = "../data/backgrounds"
# generate_label_file(path, '.jpg', True)
generate_label_file("../data/cad_renders", '.jpg', True)
# copy_images("../data/backgrounds", "../data/cad_renders2_dist")
# path = '../data/validation/5-3'
# generate_label_file(path, '.jpg', True, camera_res=(512, 288), shift_y=-0.0, shift_x=-np.tan(FOV)*2*20./512) # by radius, and around 20px
# generate_label_file(bg_path, '.jpg', False)
generate_label_file(bg_path, '.jpg', False, camera_res=(512, 288), shift_y=-0.0, shift_x=-np.tan(FOV) * 2 * 20. / 512)
copy_images(bg_path, path_valid_35)
copy_images(bg_path, path_valid_360)
copy_images(bg_path, path_valid_53)
copy_images(bg_path, path_valid_560)

@@ -42,7 +42,7 @@ def distort(self, save_path, **kwargs):
for img_name, img in self.images:
for func in kwargs:
if func != "compression":
self.__class__.__dict__[func].__func__(img_name, img, save_path, kwargs[func])
self.__class__.__dict__[func].__func__(img_name, img, save_path, *kwargs[func])
else:
self.compression(img_name, save_path, kwargs[func])

@@ -112,11 +112,11 @@ def __str__(self):
if __name__ == "__main__":

# path = "../data/cad_renders/GateRenders.jpg"
path_load = "../data/cad_renders5_bench"
save_path = "../data/cad_renders5_dist"
path_load = "../data/cad_renders2_new"
save_path = "../data/cad_renders2_dist"

d = DistortImages()
d.load(path_load, ".jpg")
d.distort(save_path, blur=(3,5,10), compression=np.arange(5,15,1, dtype=np.uint8).tolist(), dilation=(1,3,5), erosion=(1,3,5))

# d.distort(save_path, blur=(3,5,10), compression=np.arange(5,15,1, dtype=np.uint8).tolist(), dilation=(1,3,5), erosion=(1,3,5))
d.distort(save_path, blur=((5,10,20,50,100),(7,7)))

@@ -4,6 +4,7 @@
from src.benchmark import Benchmark
from copy import deepcopy

import matplotlib.pyplot as plt

class TemplateMatching:
"""
@@ -12,32 +13,67 @@ class TemplateMatching:
methods = ['cv2.TM_CCOEFF', 'cv2.TM_CCOEFF_NORMED', 'cv2.TM_CCORR',
'cv2.TM_CCORR_NORMED', 'cv2.TM_SQDIFF', 'cv2.TM_SQDIFF_NORMED']

def __init__(self, method="cv2.TM_CCORR_NORMED", threshold=0.95):
# self.method = eval(method)
# self.threshold = threshold
def __init__(self):
self.images = None
self.corners = None
self.w = None
self.h = None
self.transformation = None
self.pts1 = None

def load_corners(self, path):
if self.corners is None:
self.corners = {}
corner_normal = cv2.imread(os.path.join(path, "template_corner.png"), 0)
tl = cv2.imread(os.path.join(path, "top_left_4.png"), 0)
tr = cv2.imread(os.path.join(path, "top_right_2.png"), 0)
corner = cv2.imread(os.path.join(path, "template_orange.png"))

example = [tl, tr, np.flip(tr, axis=0), np.flip(tl, axis=0)]
corner_normal = cv2.cvtColor(corner, cv2.COLOR_BGR2GRAY)
self.w, self.h = corner_normal.shape
# tl = cv2.imread(os.path.join(path, "top_left_4.png"), 0)
# tr = cv2.imread(os.path.join(path, "top_right_2.png"), 0)

# example = [tl, tr, np.flip(tr, axis=0), np.flip(tl, axis=0)]
self.corners["nominal"] = [np.rot90(corner_normal)] # TODO: small mistake
self.corners["top_left"] = [example]
# self.corners["top_left"] = [example]
for i in range(3):
self.corners["nominal"].append(np.rot90(self.corners["nominal"][i]))
self.corners["top_left"].append([np.rot90(self.corners["top_left"][i][j-1], axes=(1, 0)) for j in range(4)])
# self.corners["top_left"].append([np.rot90(self.corners["top_left"][i][j-1], axes=(1, 0)) for j in range(4)])

# if corner_normal.shape == tl.shape == tr.shape:
# self.w, self.h = corner_normal.shape
# else:
# raise IndexError("Corners of templates have different sizes")

center_x, center_y, r = (8, 11, 7)
pts1 = np.float32([[center_x, center_y-r], [center_x, center_y], [center_x+r, center_y]])
transformation = lambda alpha: np.float32([[center_x, center_y - r],
[center_x, center_y],
[center_x + r * np.cos(np.pi / 180 * alpha), center_y - r * np.sin(np.pi / 180*alpha)]])

# generate new rotated templates
for new_angle in np.arange(-60, 61, 5):
pts2 = transformation(new_angle)
M = cv2.getAffineTransform(pts1, pts2)
dst = cv2.warpAffine(corner_normal, M, (16,16))
# averages = [np.mean(dst[:, i][dst[:, i] > 25], axis=0) for i in range(dst.shape[0])]

if corner_normal.shape == tl.shape == tr.shape:
self.w, self.h = corner_normal.shape
else:
raise IndexError("Corners of templates have different sizes")
# fill empty space
for i in range(dst.shape[0]):
# col = dst[:, i]
# col[np.where(col < 25)[0]] = averages[i]
# dst[:, i] = col
self.corners[new_angle] = dst
# self.corners[new_angle] = cv2.dilate(dst[int(7*np.sin(abs(new_angle)*np.pi/180)/2):int(19-7*np.sin(abs(new_angle)*np.pi/180) /2),
# int(2+7*np.sin(abs(new_angle)*np.pi/180)/2):int(19-7*np.sin(abs(new_angle)*np.pi/180) /2)], (3,3), iterations=2)
# self.corners[new_angle] = cv2.cvtColor(dst[int(7*np.sin(abs(new_angle)*np.pi/180)/2):int(19-7*np.sin(abs(new_angle)*np.pi/180) /2),
# int(2+7*np.sin(abs(new_angle)*np.pi/180)/2):int(19-7*np.sin(abs(new_angle)*np.pi/180) /2)],
# cv2.COLOR_BGR2GRAY)
# plt.imshow(self.corners[new_angle])
# plt.show()
# print(self.)
for i, angle in enumerate([0,30,-30]):
plt.subplot(131+i)
plt.imshow(self.corners[angle], 'gray')
# plt.show()

def test_single(self, path, method, threshold):
if method not in self.methods:
@@ -94,33 +130,50 @@ def find_gate(self, img_name, *args):

# TODO: Does 1 extra template matching for curved corners (1st time)
# TODO: Smarter use of TM (if 2 points are far away, or not feasible, stop doing TM)
if not gate_detected:
corner_selection = self.find_corners(img, map(lambda x: x[0], self.corners["top_left"]), method, threshold)
selected = sorted(corner_selection, key=lambda x: x["max_val"])[-1] # selected template by maximum value
# selected_index = [i for i in corner_selection if i == selected]
if selected["max_val"] > threshold:
# continue with other 3 corners
corners = self.find_corners(img, self.corners["top_left"][selected["id"]], method, threshold)
# Change order of corners, so it matches order of benchmark
corners = [corners[2], corners[1], corners[0], corners[3]]
# Re-check obtained corners to gate
gate_detected = self.find_gate_detected(corners)
# if not gate_detected:
# # corner_selection = self.find_corners(img, map(lambda x: x[0], self.corners["top_left"]), method, threshold)
# curved_corners = [self.corners[i] for i in np.arange(0, 60, 5)]
# corner_selection = self.find_corners(img, curved_corners, method, threshold, True)
# selected = sorted(corner_selection, key=lambda x: x["max_val"])[-1] # selected template by maximum value
# # selected_index = [i for i in corner_selection if i == selected]
# if selected["max_val"] > threshold:
# # continue with other 3 corners
# # corners = self.find_corners(img, self.corners["top_left"][selected["id"]], method, threshold)
# f_angle = selected["angle"]
# print(f_angle)
# other_3 = [np.flip(self.corners[f_angle], axis=0),
# np.flip(self.corners[-abs(f_angle)], axis=1),
# np.flip(np.flip(self.corners[-abs(f_angle)], axis=1), axis=0)]
# # for i in range(4):
# # if i == 0:
# # plt.subplot(221)
# # plt.imshow(self.corners[f_angle], cmap="gray")
# # else:
# # plt.subplot(221+i)
# # plt.imshow(other_3[i-1], cmap="gray")
# # plt.show()
# corners = self.find_corners(img, other_3, method, threshold)
# # Change order of corners, so it matches order of benchmark
# corners = [corners[1], corners[2], corners[0], selected]
# # Re-check obtained corners to gate
# gate_detected = self.find_gate_detected(corners)

return gate_detected, corners[0]["max_loc"], corners[1]["max_loc"], corners[2]["max_loc"], corners[3]["max_loc"]

def find_corners(self, img, templates, method, threshold):
def find_corners(self, img, templates, method, threshold, angle=False):
corners = []
for i, template in enumerate(templates):
try:
res = cv2.matchTemplate(img, template, method)
except TypeError:
print("Invalid img", img)
return False, (0, 0), (0, 0), (0, 0), (0, 0)
raise TypeError("Invalid img ", img)

min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
top_left = max_loc if max_val > threshold else (0, 0)
bottom_right = (top_left[0] + self.w, top_left[1] + self.h)
corners.append({"id": i, "det": top_left != (0, 0), "res": res, "max_val": max_val, "max_loc": max_loc,
"top_left": top_left, "bot_right": bottom_right})
"top_left": top_left, "bot_right": bottom_right, "angle": 0 if not angle else 0+i*5}) # TODO: change hardcode
# print(i)
return corners

def find_gate_detected(self, corners):
@@ -129,7 +182,8 @@ def find_gate_detected(self, corners):
if self.corners_ordered(corners):
if self.corners_dont_cross(corners):
if self.check_shape(corners):
return True
if self.check_scale(corners):
return True
return False

@staticmethod
@@ -154,25 +208,35 @@ def corners_dont_cross(corners):
@staticmethod
def check_shape(corners, threshold=20):
if abs(corners[0]["max_loc"][0]-corners[1]["max_loc"][0]) < threshold:
if abs(corners[2]["max_loc"][0] - corners[3]["max_loc"][0]) < threshold:
if abs(corners[0]["max_loc"][1] - corners[3]["max_loc"][1]) < threshold:
return True
elif abs(corners[1]["max_loc"][1] - corners[2]["max_loc"][1]) < threshold:
return True
if abs(corners[2]["max_loc"][0] - corners[3]["max_loc"][0]) < threshold:
if abs(corners[2]["max_loc"][1] - corners[1]["max_loc"][1]) < threshold:
return True
elif abs(corners[3]["max_loc"][1] - corners[0]["max_loc"][1]) < threshold:
return True
return False

def animation(self, path, progress=False):
@staticmethod
def check_scale(corners):
d = [np.linalg.norm(np.array(corners[i % 4]["max_loc"]) - np.array(corners[(i+1) % 4]["max_loc"])) for i in range(4)]
f = 0
for i in range(4):
if not (0.5 < d[i % 4]/d[(i+1) % 4] < 1.5):
f += 1
return True if f < 2 else False

def animation(self, path):
print("Rendering images")
images = []

if progress:
import progressbar
import time
bar = progressbar.ProgressBar(max_value=len(tuple(filter(lambda x: 'jpg' in x, os.listdir(path)))))
i = 0

for filename in sorted(os.listdir(path)):
if '.jpg' in filename:
path_to_file = os.path.join(path, filename)
img = cv2.imread(path_to_file)
gd, c0, c1, c2, c3 = tm.find_gate(path_to_file, "cv2.TM_CCORR_NORMED", 0.95)
gd, c0, c1, c2, c3 = self.find_gate(path_to_file, "cv2.TM_CCORR_NORMED", 0.95)

cv2.rectangle(img, (c0[0]+self.w,) + (c0[1]+self.h,),
(c0[0]-self.w,) + (c0[1]-self.h,), (255, 0, 0), thickness=3)
@@ -191,9 +255,6 @@ def animation(self, path, progress=False):
cv2.putText(img, str(gd), (50, 100), font, 4, (255, 0, 0), 2, cv2.LINE_AA)
images.append(img)

if progress:
i += 1
bar.update(i)

print("Rendering Done")
i = 0
@@ -210,10 +271,65 @@ def __str__(self):


if __name__ == "__main__":
path = "../data/cad_renders2_test"
path = "../data/cad_renders3_new"
path = "/home/kit/projects/find-me/data/20June2/GateRenders360Rotation/GateRenders360Rotation_animation"
path_corners = "../data/corners"
tm = TemplateMatching()
tm.load_corners(path_corners)
times = []
import time
import random
files = random.choices(os.listdir("../data/validation/5-3"), k=10)

# 0.05964167339843698 -> 16.766799840096485 Hz
for i in range(10):
t1 = time.perf_counter()
print(files[i])
tm.find_gate(os.path.join("../data/validation/5-3", files[i]), "cv2.TM_CCORR_NORMED", 0.95)
t = time.perf_counter() - t1
times.append(t)
print(times)
print(np.mean(times))


# tm.animation(path)
tm.test_many(path, methods=["cv2.TM_CCOEFF_NORMED"])
# # tm.test_many(path, methods=["cv2.TM_CCOEFF_NORMED"])
# tm.animation(path, True)
# cv2.warpPerspective()
# euler = lambda point, alpha: [point[0]*np.cos(alpha), point[1]*np.sin(alpha)]
# import matplotlib.pyplot as plt
# # func = lambda alpha: np.float32([[8-7*np.sin(np.pi/180*alpha), 11-7*np.cos(np.pi/180*alpha)],
# # [8, 11],
# # [8+7*np.cos(np.pi/180*alpha), 11-7*np.sin(np.pi/180*alpha)]])
#
# func = lambda alpha: np.float32([[8-0*np.sin(np.pi/180*alpha), 4-0*np.cos(np.pi/180*alpha)],
# [8, 11],
# [8+7*np.cos(np.pi/180*alpha), 11-7*np.sin(np.pi/180*alpha)]])
# #
# img = cv2.imread(os.path.join(path_corners, "template_corner.png"))
# rows, cols, ch = img.shape
#
# pts1 = np.float32([[8, 4], [8, 11], [15, 11]])
# pts2 = func(45)
#
# M = cv2.getAffineTransform(pts1, pts2)
#
# dst = cv2.warpAffine(img, M, (20, 20))
#
# averages = [np.mean(dst[:, i, :], axis=0) for i in range(dst.shape[0])]
#
# for i in range(dst.shape[0]):
# col = dst[:, i,:]
# col[np.where(col < (25,25,25))[0]] = averages[i]
# dst[:, i, :] = col
# # print(col == (0,0,0))
#
# plt.subplot(133), plt.imshow(dst[:, 1:18, :]) # TODO : figure out
#
# # dst = cv2.morphologyEx(dst, cv2.MORPH_OPEN, (15, 15), iterations=3)
# # dst = cv2.GaussianBlur(dst, (5,5), sigmaX=10, sigmaY=10)
# # dst = cv2.dilate(dst, (5, 5), iterations=2)
# plt.subplot(131), plt.imshow(img), plt.plot([i[0] for i in pts1], [i[1] for i in pts1]), plt.title('Input')
# plt.subplot(132), plt.imshow(dst), plt.plot([i[0] for i in pts2], [i[1] for i in pts2]), plt.title('Output')
# # print(dst)
# plt.show()