Spaces:
Sleeping
Sleeping
| # Code taken from | |
| # https://github.com/maciejczyzewski/neural-chessboard/ | |
| from laps import laps_intersections, laps_cluster | |
| from slid import slid_tendency | |
| import scipy | |
| import cv2 | |
| import pyclipper | |
| import numpy as np | |
| import matplotlib.path | |
| import matplotlib.pyplot as plt | |
| import matplotlib.path as mplPath | |
| import collections | |
| import itertools | |
| import random | |
| import math | |
| import sklearn.cluster | |
| from copy import copy | |
| na = np.array | |
| ################################################################################ | |
| def llr_normalize(points): return [[int(a), int(b)] for a, b in points] | |
| def llr_correctness(points, shape): | |
| __points = [] | |
| for pt in points: | |
| if pt[0] < 0 or pt[1] < 0 or \ | |
| pt[0] > shape[1] or \ | |
| pt[1] > shape[0]: | |
| continue | |
| __points += [pt] | |
| return __points | |
| def llr_unique(a): | |
| indices = sorted(range(len(a)), key=a.__getitem__) | |
| indices = set(next(it) for k, it in | |
| itertools.groupby(indices, key=a.__getitem__)) | |
| return [x for i, x in enumerate(a) if i in indices] | |
| def llr_polysort(pts): | |
| """sort points clockwise""" | |
| mlat = sum(x[0] for x in pts) / len(pts) | |
| mlng = sum(x[1] for x in pts) / len(pts) | |
| def __sort(x): # main math --> found on MIT site | |
| return (math.atan2(x[0]-mlat, x[1]-mlng) + | |
| 2*math.pi) % (2*math.pi) | |
| pts.sort(key=__sort) | |
| return pts | |
| def llr_polyscore(cnt, pts, cen, alfa=5, beta=2): | |
| a = cnt[0] | |
| b = cnt[1] | |
| c = cnt[2] | |
| d = cnt[3] | |
| area = cv2.contourArea(cnt) | |
| t2 = area < (4 * alfa * alfa) * 5 | |
| if t2: | |
| return 0 | |
| gamma = alfa/1.5 | |
| pco = pyclipper.PyclipperOffset() | |
| pco.AddPath(cnt, pyclipper.JT_MITER, pyclipper.ET_CLOSEDPOLYGON) | |
| pcnt = matplotlib.path.Path(pco.Execute(gamma)[0]) # FIXME: alfa/1.5 | |
| wtfs = pcnt.contains_points(pts) | |
| pts_in = min(np.count_nonzero(wtfs), 49) | |
| t1 = pts_in < min(len(pts), 49) - 2 * beta - 1 | |
| if t1: | |
| return 0 | |
| A = pts_in | |
| B = area | |
| def nln(l1, x, dx): return \ | |
| np.linalg.norm(np.cross(na(l1[1])-na(l1[0]), | |
| na(l1[0])-na(x)))/dx | |
| pcnt_in = [] | |
| i = 0 | |
| for pt in wtfs: | |
| if pt: | |
| pcnt_in += [pts[i]] | |
| i += 1 | |
| def __convex_approx(points, alfa=0.001): | |
| hull = scipy.spatial.ConvexHull(na(points)).vertices | |
| cnt = na([points[pt] for pt in hull]) | |
| return cnt | |
| cnt_in = __convex_approx(na(pcnt_in)) | |
| points = cnt_in | |
| x = [p[0] for p in points] | |
| y = [p[1] for p in points] | |
| cen2 = (sum(x) / len(points), | |
| sum(y) / len(points)) | |
| G = np.linalg.norm(na(cen)-na(cen2)) | |
| """ | |
| cnt_in = __convex_approx(na(pcnt_in)) | |
| S = cv2.contourArea(na(cnt_in)) | |
| if S < B: E += abs(S - B) | |
| cnt_in = __convex_approx(na(list(cnt_in)+list(cnt))) | |
| S = cv2.contourArea(na(cnt_in)) | |
| if S > B: E += abs(S - B) | |
| """ | |
| a = [cnt[0], cnt[1]] | |
| b = [cnt[1], cnt[2]] | |
| c = [cnt[2], cnt[3]] | |
| d = [cnt[3], cnt[0]] | |
| lns = [a, b, c, d] | |
| E = 0 | |
| F = 0 | |
| for l in lns: | |
| d = np.linalg.norm(na(l[0])-na(l[1])) | |
| for p in cnt_in: | |
| r = nln(l, p, d) | |
| if r < gamma: | |
| E += r | |
| F += 1 | |
| if F == 0: | |
| return 0 | |
| E /= F | |
| if B == 0 or A == 0: | |
| return 0 | |
| # See Eq.11 and Sec.3.4 in the paper | |
| C = 1+(E/A)**(1/3) | |
| D = 1+(G/A)**(1/5) | |
| R = (A**4)/((B**2) * C * D) | |
| # print(R*(10**12), A, "|", B, C, D, "|", E, G) | |
| return R | |
| ################################################################################ | |
| # LAPS, SLID | |
| def LLR(img, points, lines): | |
| old = points | |
| def __convex_approx(points, alfa=0.01): | |
| hull = scipy.spatial.ConvexHull(na(points)).vertices | |
| cnt = na([points[pt] for pt in hull]) | |
| approx = cv2.approxPolyDP(cnt, alfa * | |
| cv2.arcLength(cnt, True), True) | |
| return llr_normalize(itertools.chain(*approx)) | |
| __cache = {} | |
| def __dis(a, b): | |
| idx = hash("__dis" + str(a) + str(b)) | |
| if idx in __cache: | |
| return __cache[idx] | |
| __cache[idx] = np.linalg.norm(na(a)-na(b)) | |
| return __cache[idx] | |
| def nln(l1, x, dx): return \ | |
| np.linalg.norm(np.cross(na(l1[1])-na(l1[0]), | |
| na(l1[0])-na(x)))/dx | |
| pregroup = [[], []] | |
| S = {} | |
| points = llr_correctness(llr_normalize(points), img.shape) | |
| __points = {} | |
| points = llr_polysort(points) | |
| __max, __points_max = 0, [] | |
| alfa = math.sqrt(cv2.contourArea(na(points))/49) | |
| X = sklearn.cluster.DBSCAN(eps=alfa*4).fit(points) | |
| for i in range(len(points)): | |
| __points[i] = [] | |
| for i in range(len(points)): | |
| if X.labels_[i] != -1: | |
| __points[X.labels_[i]] += [points[i]] | |
| for i in range(len(points)): | |
| if len(__points[i]) > __max: | |
| __max = len(__points[i]) | |
| __points_max = __points[i] | |
| if len(__points) > 0 and len(points) > 49/2: | |
| points = __points_max | |
| # print(X.labels_) | |
| ring = __convex_approx(llr_polysort(points)) | |
| n = len(points) | |
| beta = n*(5/100) | |
| alfa = math.sqrt(cv2.contourArea(na(points))/49) | |
| x = [p[0] for p in points] | |
| y = [p[1] for p in points] | |
| centroid = (sum(x) / len(points), | |
| sum(y) / len(points)) | |
| # print(alfa, beta, centroid) | |
| def __v(l): | |
| y_0, x_0 = l[0][0], l[0][1] | |
| y_1, x_1 = l[1][0], l[1][1] | |
| x_2 = 0 | |
| t = (x_0-x_2)/(x_0-x_1+0.0001) | |
| a = [int((1-t)*x_0+t*x_1), int((1-t)*y_0+t*y_1)][::-1] | |
| x_2 = img.shape[0] | |
| t = (x_0-x_2)/(x_0-x_1+0.0001) | |
| b = [int((1-t)*x_0+t*x_1), int((1-t)*y_0+t*y_1)][::-1] | |
| poly1 = llr_polysort([[0, 0], [0, img.shape[0]], a, b]) | |
| s1 = llr_polyscore(na(poly1), points, centroid, beta=beta, alfa=alfa/2) | |
| poly2 = llr_polysort([a, b, | |
| [img.shape[1], 0], [img.shape[1], img.shape[0]]]) | |
| s2 = llr_polyscore(na(poly2), points, centroid, beta=beta, alfa=alfa/2) | |
| return [a, b], s1, s2 | |
| def __h(l): | |
| x_0, y_0 = l[0][0], l[0][1] | |
| x_1, y_1 = l[1][0], l[1][1] | |
| x_2 = 0 | |
| t = (x_0-x_2)/(x_0-x_1+0.0001) | |
| a = [int((1-t)*x_0+t*x_1), int((1-t)*y_0+t*y_1)] | |
| x_2 = img.shape[1] | |
| t = (x_0-x_2)/(x_0-x_1+0.0001) | |
| b = [int((1-t)*x_0+t*x_1), int((1-t)*y_0+t*y_1)] | |
| poly1 = llr_polysort([[0, 0], [img.shape[1], 0], a, b]) | |
| s1 = llr_polyscore(na(poly1), points, centroid, beta=beta, alfa=alfa/2) | |
| poly2 = llr_polysort([a, b, | |
| [0, img.shape[0]], [img.shape[1], img.shape[0]]]) | |
| s2 = llr_polyscore(na(poly2), points, centroid, beta=beta, alfa=alfa/2) | |
| return [a, b], s1, s2 | |
| for l in lines: | |
| for p in points: | |
| t1 = nln(l, p, __dis(*l)) < alfa | |
| t2 = nln(l, centroid, __dis(*l)) > alfa * 2.5 | |
| if t1 and t2: | |
| tx, ty = l[0][0]-l[1][0], l[0][1]-l[1][1] | |
| if abs(tx) < abs(ty): | |
| ll, s1, s2 = __v(l) | |
| o = 0 | |
| else: | |
| ll, s1, s2 = __h(l) | |
| o = 1 | |
| if s1 == 0 and s2 == 0: | |
| continue | |
| pregroup[o] += [ll] | |
| pregroup[0] = llr_unique(pregroup[0]) | |
| pregroup[1] = llr_unique(pregroup[1]) | |
| # print("---------------------") | |
| # print(pregroup) | |
| for v in itertools.combinations(pregroup[0], 2): | |
| for h in itertools.combinations(pregroup[1], 2): | |
| poly = laps_intersections([v[0], v[1], h[0], h[1]]) | |
| poly = llr_correctness(poly, img.shape) | |
| if len(poly) != 4: | |
| continue | |
| poly = na(llr_polysort(llr_normalize(poly))) | |
| if not cv2.isContourConvex(poly): | |
| continue | |
| # print("Poly:", -llr_polyscore(poly, points, centroid, | |
| # beta=beta, alfa=alfa/2)) | |
| S[-llr_polyscore(poly, points, centroid, | |
| beta=beta, alfa=alfa/2)] = poly | |
| # print(bool(S)) | |
| S = collections.OrderedDict(sorted(S.items())) | |
| K = next(iter(S)) | |
| # print("key --", K) | |
| four_points = llr_normalize(S[K]) | |
| # print("POINTS:", len(points)) | |
| # print("LINES:", len(lines)) | |
| return four_points | |
| def llr_pad(four_points, img): | |
| pco = pyclipper.PyclipperOffset() | |
| pco.AddPath(four_points, pyclipper.JT_MITER, pyclipper.ET_CLOSEDPOLYGON) | |
| padded = pco.Execute(60)[0] | |
| # 60,70/75 is best (with buffer/for debug purpose) | |
| return pco.Execute(60)[0] | |