Beate Scheibel 3 years ago
parent
commit
71661355b4

BIN
__pycache__/algoritm_knn.cpython-37.pyc


BIN
__pycache__/clustering_precomputed_dbscan_noParallels.cpython-37.pyc


BIN
__pycache__/read_from_clustered_merged.cpython-37.pyc


+ 171 - 0
algoritm_knn.py

@@ -0,0 +1,171 @@
+import subprocess
+import PyPDF2
+import numpy as np
+#import csv
+import order_bounding_boxes_in_each_block
+import read_from_clustered_merged
+import get_distances
+from clustering_precomputed import clustering_precomputed_dbscan_noParallels as dbscan
+
+with open('/home/bscheibel/PycharmProjects/clustering/config.txt', 'r') as myfile:
+    config_path = myfile.read()
+    print("Path: ", config_path)
+
+def calculate_inner_distance(result):
+    min_size_x,max_size_x, min_size_y, max_size_y, diagonal = get_distances.size_blocks(result)
+    #print("inner distance: ", diagonal)
+
+def find_nearest_above(my_array, target):
+    diff = my_array - target
+    mask = np.ma.less_equal(diff, 0)
+    # We need to mask the negative differences and zero
+    # since we are looking for values above
+    if np.all(mask):
+        return None # returns None if target is greater than any value
+    masked_diff = np.ma.masked_array(diff, mask)
+    return masked_diff.argmin()
+
+def avg_words_block_clustered(words, cluster):
+    blocks = cluster
+    avg_words = words/blocks
+    return avg_words
+
+def convert_pdf_img(filename):
+    subprocess.call(['pdftoppm', '-jpeg', '-singlefile',
+                     filename, config_path + '/temporary/out'])
+
+def read_pdf(filename):
+    pdf = PyPDF2.PdfFileReader(filename, strict=False)
+    p = pdf.getPage(0)
+    w = p.mediaBox.getWidth()
+    h = p.mediaBox.getHeight()
+    orientation = p.get('/Rotate')
+    return w, h, orientation
+
+def read_webpage(filename):
+    return "test"
+
+
+def get_min_nn(result, path):
+    dm = get_distances.distance_btw_blocks(result, path)
+    knn = get_distances.distance_knn(dm)
+    knn = list(set(knn))
+    knn = sorted(knn)
+    return knn
+
+def show_boxes(filepath, clean_arrays, eps):
+    img_path = config_path + '/temporary/out.jpg'
+    w, h, orientation = read_pdf(filepath)
+    convert_pdf_img(filepath)
+    filename = filepath.split("/")[-1]
+    filename = filename.split(".pdf")[0]
+    read_from_clustered_merged.highlight_image(clean_arrays, img_path, w, h, orientation, eps, filename)
+    return filename
+
+def main(uuid=123, filepath=config_path+"/"+ "drawings/Stahl_Adapterplatte.PDF"):
+    path = config_path
+    filename = order_bounding_boxes_in_each_block.pdf_to_html(uuid, filepath, path)
+    result, number_blocks, number_words = order_bounding_boxes_in_each_block.get_bound_box(filename)  #get coordinates+text out of html file into array of arrays
+    print("number_blocks:", number_blocks)
+    print("number_words:", number_words)
+    avg_words_block = number_words / number_blocks
+    print("avg words/blocks", avg_words_block)
+    result_df = get_distances.get_average_xy(result, path)
+
+    # get min_nn
+    knn = get_min_nn(result_df, path)
+    #print("knn: ", knn)
+    eps = min(knn)
+    print("min_knn: ", eps)
+
+
+
+    #try one clustering iteration, with eps=smallest value
+    res, number_clusters, dbs, chs_old, silhoutte, dm = dbscan.cluster_and_preprocess(result, eps, path)
+    # res = res.drop(res.columns[[0, 1]], axis=1).to_csv("test.csv", header=False)
+    # #res = res.reset_index().tolist()
+    # with open(path+"/test.csv") as csvfile:
+    #     readCSV = csv.reader(csvfile, delimiter=';')
+    #     res = list(readCSV)
+    # print(res)
+    #get_distances.get_average_xy(res, path)
+    res, number_clusters, dbs, chs_old, silhoutte, dm = dbscan.cluster_and_preprocess(result, eps, path)
+
+    #read default value
+    clean_arrays = read_from_clustered_merged.read_default(path + "/temporary/list_to_csv_with_corner_points.csv")
+    show_boxes(filepath, clean_arrays, "default")
+
+    #print(number_clusters)
+
+    clean_arrays = read_from_clustered_merged.read(path + "/temporary/values_clusteredfrom_precomputed_dbscan.csv")
+
+    # show results
+    show_boxes(filepath, clean_arrays, eps)
+    #look at stop criterion
+    avg_words_block = avg_words_block_clustered(number_words, number_clusters)
+    print("a/w first clustering eps=1: ", avg_words_block)
+    #cluster as long as stop criterion is not met
+    print("cluster, eps: ", eps)
+    chs = chs_old
+
+    while(1):    # this condition has to be changed to the breaking condition
+
+        print("cluster, eps: ", eps)
+        dbs_old = dbs
+        chs_old = chs
+        silhoutte_old = silhoutte
+        res, number_clusters, dbs, chs, silhoutte = dbscan.clustering(dm, eps, path)
+
+        # stop criterion, has to be established (silhoutte, davis-bouldin, c...?), or combination of these three
+        avg_words_block_new = avg_words_block_clustered(number_words, number_clusters)
+        print("avg_words_blocks:", avg_words_block_new)
+        #stop_criterion = avg_words_block_new-avg_words_block
+
+        read_from_clustered_merged.read(path + "/temporary/values_clusteredfrom_precomputed_dbscan.csv")
+        # show results
+        #show_boxes(filepath, clean_arrays, eps)
+
+        print(dbs <= dbs_old)
+        print(chs >= chs_old)
+        print(silhoutte >= silhoutte_old)
+
+        old_eps = eps
+
+        #block to see which conditions apply first, mostly silhoutte and dbs
+        if not dbs<=dbs_old and avg_words_block_new>avg_words_block:
+            print("stopping threshold reached dbs")
+            clean_arrays = read_from_clustered_merged.read(
+            path + "/temporary/values_clusteredfrom_precomputed_dbscan.csv")
+            show_boxes(filepath, clean_arrays, "threshold dbs")
+        if not chs>=chs_old and avg_words_block_new>avg_words_block:
+            print("stopping threshold reached chs")
+            clean_arrays = read_from_clustered_merged.read(
+            path + "/temporary/values_clusteredfrom_precomputed_dbscan.csv")
+            show_boxes(filepath, clean_arrays, "threshold chs")
+        if not silhoutte>=silhoutte_old and avg_words_block_new > avg_words_block:
+            print("stopping threshold reached silhoutte")
+            clean_arrays = read_from_clustered_merged.read(
+            path + "/temporary/values_clusteredfrom_precomputed_dbscan.csv")
+            show_boxes(filepath, clean_arrays, "threshold silhoutte")
+
+        # and/or, or does not cluster too much, but can also be not enough
+        if (not dbs <= dbs_old or not chs >= chs_old or not silhoutte >= silhoutte_old) and avg_words_block_new > avg_words_block:
+            print("stopping threshold reached")
+            break
+        try:
+            eps = find_nearest_above(knn, eps)
+            eps = knn[eps]
+        except:
+            print("highest nn value reached")
+            break
+    res, number_clusters, dbs, chs, silhoutte = dbscan.clustering(dm, old_eps, path)
+    print("Last EPS: ", old_eps)
+    print("Last W/B: ", avg_words_block)
+    clean_arrays = read_from_clustered_merged.read_default(path + "/temporary/list_to_csv_with_corner_points.csv")
+    show_boxes(filepath, clean_arrays, "default")
+    clean_arrays = read_from_clustered_merged.read(path + "/temporary/values_clusteredfrom_precomputed_dbscan.csv")
+    #show results
+    show_boxes(filepath, clean_arrays, eps)
+
+if __name__ == "__main__":
+    main()

+ 254 - 0
clustering_precomputed_dbscan_noParallels.py

@@ -0,0 +1,254 @@
+# coding: utf8
+import numpy as np
+import pandas
+import csv
+from math import sqrt
+from sklearn.cluster import DBSCAN
+
+from sklearn import metrics
+from sklearn.metrics import davies_bouldin_score
+import time
+
+def get_average_xy(list_input, path):
+    csv_name = path+"/temporary/list_to_csv_with_corner_points.csv"
+    resultFile = open(csv_name, 'w')
+    wr = csv.writer(resultFile, delimiter=";")
+    wr.writerow(["element", "xmin","ymin","xmax","ymax", "ausrichtung","point_xmi_ymi","point_xma_ymi","point_xmi_yma","point_xma_yma"])
+
+    #result_df = pandas.DataFrame(columns=["point_xmi_ymi","point_xma_ymi","point_xmi_yma","point_xma_yma"])
+    result_df = pandas.DataFrame(columns=["point_xmi_ymi","point_xma_ymi","point_xmi_yma","point_xma_yma","ausrichtung"])
+
+    for element in list_input:
+        xavg_elem = 0
+        yavg_elem = 0
+        ymin = 100000000
+        ymax = 0
+        xmin = 100000000
+        xmax = 0
+        newList = []
+        check = False
+        if len(element) == 5 and not isinstance(element[0], list):
+            newList.append(element)
+            element = newList
+        """if len(element) != 5 and isinstance(element[0], list):
+            for el in element:
+                check = isinstance(el[0], list)
+                if len(el) != 5:
+                    print(el)
+                #if check:
+                #    print(el)"""
+
+        for blub in element: #get the smallest and largest x and y value for whole block
+
+            if isinstance(blub[0],list) and len(blub[0]) == 5:
+                blub = blub [0]
+            if float(blub[1]) < ymin:
+                ymin = float(blub[1])
+                #print("y_min:",y_min)
+            if float(blub[0]) < xmin:
+                xmin = float(blub[0])
+            if float(blub[3]) > ymax:
+                ymax = float(blub[3])
+            if float(blub[2]) > xmax:
+                xmax = float(blub[2])
+        if float(xmax)-float(xmin) > 1.3*(float(ymax)-float(ymin)):
+            ausrichtung = 0  # horizontal
+        #elif
+        elif 1.3*(float(xmax)-float(xmin)) < float(ymax)-float(ymin):
+            ausrichtung = 1   # vertikal
+        else:
+            ausrichtung = 3   # sonstiges
+
+
+        ##### GET CORNER POINTS
+        point_xmi_ymi = [xmin,ymin]
+        point_xma_ymi = [xmax,ymin]
+        point_xmi_yma = [xmin,ymax]
+        point_xma_yma = [xmax,ymax]
+        wr.writerow([element,xmin,ymin,xmax,ymax, ausrichtung,point_xmi_ymi,point_xma_ymi,point_xmi_yma,point_xma_yma])
+        result_df.loc[len(result_df)]=[point_xmi_ymi,point_xma_ymi, point_xmi_yma, point_xma_yma,ausrichtung]
+        #wr.writerow([element, xmin,ymin,xmax,ymax])
+        #result_df.loc[len(result_df)]=[xmin,xmax, xmin, ymax, ausrichtung]
+
+    resultFile.close()
+    return result_df
+
+def intersects(rectangle1, rectangle2): #using the separating axis theorem, returns true if they intersect, otherwise false
+
+    rect_1_min = eval(rectangle1[0])
+    rect_1_max = eval(rectangle1[3])
+    rect1_bottom_left_x = rect_1_min[0]
+    rect1_top_right_x = rect_1_max[0]
+    rect1_bottom_left_y = rect_1_max[1]
+    rect1_top_right_y = rect_1_min[1]
+
+    rect_2_min = eval(rectangle2[0])
+    rect_2_max = eval(rectangle2[3])
+    rect2_bottom_left_x = rect_2_min[0]
+    rect2_top_right_x = rect_2_max[0]
+    rect2_bottom_left_y = rect_2_max[1]
+    rect2_top_right_y = rect_2_min[1]
+
+    return not (rect1_top_right_x < rect2_bottom_left_x or rect1_bottom_left_x > rect2_top_right_x or rect1_top_right_y > rect2_bottom_left_y or rect1_bottom_left_y < rect2_top_right_y)
+
+
+def get_ausrichtung(rectangle1,rectangle2):
+    #check if rect 1 and rect 2 are above or beside, r,l, a,b
+
+    min_1 = eval(rectangle1[0])
+    #max_1 = eval(rectangle1[3])
+    min_2 = eval(rectangle2[0])
+    #max_2 = eval(rectangle2[3])
+
+    diff_y = min_1[1] - min_2[1] #
+    diff_x = min_1[0] - min_2[0]
+
+    if diff_x < diff_y:
+        ausrichtung = "above"
+        #print(rectangle1, rectangle2, "above")
+    else:
+        ausrichtung = "side"
+        #print(rectangle1,rectangle2, "side")
+
+    return ausrichtung
+
+
+def get_parallel(rectangle1, rectangle2):
+    #check if long sides are parallel, then we do not want to cluster these
+    #check if x or y axis is longer, then get_ausrichtung
+    parallel = False
+    #x_longer_1 = False
+    #x_longer_2 = False
+    #print(rectangle1, rectangle1[0])
+    min_1 = eval(rectangle1[0])
+    max_1 = eval(rectangle1[3])
+    min_2 = eval(rectangle2[0])
+    max_2 = eval(rectangle2[3])
+    ausrichtung_1 = eval(rectangle1[4])
+    ausrichtung_2 = eval(rectangle2[4])
+    x_axis_rect1 = float(max_1[0])-float(min_1[0])
+    x_axis_rect2 = float(max_2[0])-float(min_2[0])
+
+    y_axis_rect1 = float(max_1[1])-float(min_1[1])
+    y_axis_rect2 = float(max_2[1])-float(min_2[1])
+
+
+
+    if ausrichtung_1 == ausrichtung_2 and ausrichtung_1 == 0:
+        ausrichtung = get_ausrichtung(rectangle1, rectangle2)
+        if ausrichtung == "above":
+            parallel = True
+
+    if ausrichtung_1 == ausrichtung_2 and ausrichtung_1 == 1:
+        ausrichtung = get_ausrichtung(rectangle1, rectangle2)
+        if ausrichtung == "side":
+            parallel = True
+
+
+
+
+    return parallel
+
+
+def dist(rectangle1, rectangle2):
+ #get minimal distance between two rectangles
+    distance = 100000000
+    second_dist = 100000
+    dist_x = 100000
+    dist_y = 100000
+    #print(rectangle1, rectangle2)
+    #get_parallel(rectangle1, rectangle2)
+    for point1 in rectangle1[:4]:
+        point1 = eval(point1)
+        for point2 in rectangle2[:4]:
+            point2 = eval(point2)
+            dist = sqrt((float(point2[0]) - float(point1[0]))**2 + ((float(point2[1]) - float(point1[1])))**2)
+            if dist < distance:
+                second_dist = distance
+                distance = dist
+                dist_x = float(point2[0]) - float(point1[0])
+                #dist_y = (float(point2[1]) - float(point1[1]))
+        if get_parallel(rectangle1,rectangle2):
+            #print("parallel", rectangle2, rectangle1)
+            distance += 1000
+            second_dist += 1000
+            #continue
+        # if rectangle1[4] == rectangle2[4]:
+        #     if rectangle1[4] == "0" and dist_x < 10:
+        #           #print(rectangle1, rectangle2)
+        #         distance = dist + 100
+        #     elif rectangle1[4] == "1" and dist_y < 10:
+        #         distance = dist + 100
+        #          #print(rectangle1, rectangle2)
+
+        if intersects(rectangle1, rectangle2):
+          #print(rectangle1, rectangle2, " intersect")
+          distance = 0
+          second_dist = 0
+    #print("distanz_zwei: ", second_dist, "distanz: ", distance)
+    distance = (distance+second_dist)/2
+    return distance
+
+def clustering(dm,eps,path):
+    db = DBSCAN(eps=eps, min_samples=1, metric="precomputed").fit(dm)
+    labels = db.labels_
+    n_clusters_ = len(set(labels)) - (1 if -1 in labels else 0)
+
+    print('Estimated number of clusters: %d' % n_clusters_)
+    data_df = pandas.read_csv(path +"/temporary/list_to_csv_with_corner_points.csv", sep=";")
+    data_df["cluster"] = labels
+    try:
+        dbs = davies_bouldin_score(dm, labels)
+        #dbs = "1"
+        chs = metrics.calinski_harabasz_score(dm, labels)
+        #chs = 1
+        silhoutte = metrics.silhouette_score(dm, labels, metric='precomputed')
+        #silhoutte = 2
+        print("DBscore: ", dbs)
+        print("calsinski: ", chs)
+        print("silhoutte: ", silhoutte)
+
+    except:
+        dbs=1
+        chs=1
+        silhoutte=1
+
+    data_df["ausrichtung"] = 1
+    data_df = data_df.groupby(['cluster', 'ausrichtung'])['element'].apply(','.join).reset_index()
+    data_df.to_csv(path+"/temporary/values_clusteredfrom_precomputed_dbscan.csv",sep=";", header=False, index=False)
+
+    return data_df, n_clusters_, dbs, chs, silhoutte
+
+def cluster_and_preprocess(result,eps,path):
+    start_time = time.time()
+    result = get_average_xy(result, path) #input: array of arrays, output: either csv file or array of arrays
+    end_time = time.time()
+    time_taken_get_average = end_time - start_time
+    print("time get average: ", time_taken_get_average)
+
+    start_time = time.time()
+    result.to_csv(path+"/temporary/blub.csv", sep=";", index=False, header=None)
+    end_time = time.time()
+    time_taken_tocsv = end_time - start_time
+    print("time to csv:" , time_taken_tocsv)
+
+    with open(path+"/temporary/blub.csv") as csvfile:
+        readCSV = csv.reader(csvfile, delimiter=';')
+        result = list(readCSV)
+
+
+    start_time = time.time()
+    dm = np.asarray([[dist(p1, p2) for p2 in result] for p1 in result])
+    end_time = time.time()
+    time_taken_dm = end_time - start_time
+    print("time dm:" , time_taken_dm)
+
+
+    start_time = time.time()
+    clustering_result, n_clusters_, dbs, chs, silhoutte = clustering(dm,float(eps), path)
+    end_time = time.time()
+    time_taken_clustering = end_time - start_time
+    print("time clustering:" , time_taken_clustering)
+
+    return clustering_result, n_clusters_, dbs, chs, silhoutte, dm
+

+ 6 - 8
main.py

@@ -1,17 +1,19 @@
 import order_bounding_boxes_in_each_block
-import clustering_precomputed_dbscan
+import clustering_precomputed_dbscan_noParallels as clustering_precomputed_dbscan
 import read_from_clustered_merged
 import regex_clean_new
 import organize_drawing_according_to_details_new
 import json
 import redis
 import sys
+import algoritm_knn
 
 def write_redis(uuid, result, db_params):
-    db = redis.Redis(db_params)
+    #db = redis.Redis(db_params)
+    db = db = redis.Redis(unix_socket_path='/tmp/redis.sock',db=7)
+    print(db_params)
     db.set(uuid, result)
 
-
 def main(uuid, filepath, db, eps):
     path = "/home/centurio/Projects/engineering_drawings_extraction"
     #path = "/home/bscheibel/PycharmProjects/engineering_drawings_extraction"
@@ -40,16 +42,12 @@ def main(uuid, filepath, db, eps):
     write_redis(uuid+"eps", str(number_blocks)+","+str(number_words), db)
     write_redis(uuid+"details",json_details ,db)
 
-
-
-
-
 if __name__ == "__main__":
     uuid = sys.argv[1]
     filename = sys.argv[2]
     db = sys.argv[3]
     eps = sys.argv[4]
-    main(uuid,filename, db, eps)
+    algoritm_knn.main(uuid,filename, db, eps)
 
 
 

+ 53 - 0
main.py~

@@ -0,0 +1,53 @@
+import order_bounding_boxes_in_each_block
+import clustering_precomputed_dbscan
+import read_from_clustered_merged
+import regex_clean_new
+import organize_drawing_according_to_details_new
+import json
+import redis
+import sys
+
+def write_redis(uuid, result, db_params):
+    db = redis.Redis(db_params)
+    print(db_params)
+    db.set(uuid, result)
+
+def main(uuid, filepath, db, eps):
+    path = "/home/centurio/Projects/engineering_drawings_extraction"
+    #path = "/home/bscheibel/PycharmProjects/engineering_drawings_extraction"
+    filename = order_bounding_boxes_in_each_block.pdf_to_html(uuid, filepath, path)
+    result, number_blocks, number_words= order_bounding_boxes_in_each_block.get_bound_box(filename)  ##get coordinates+text out of html file into array of arrays
+    print("words:" + str(number_words),"blocks:" + str(number_blocks))
+    if eps == '0':
+        if number_words > 500:
+            eps = 7
+        else:
+            eps = 1
+    isos, general_tol = order_bounding_boxes_in_each_block.extract_isos(result)
+    print(general_tol)
+    res = clustering_precomputed_dbscan.cluster_and_preprocess(result,eps, path)
+    clean_arrays = read_from_clustered_merged.read(path+"/temporary/values_clusteredfrom_precomputed_dbscan.csv")
+    tables = order_bounding_boxes_in_each_block.get_tables(clean_arrays)
+    pretty = regex_clean_new.print_clean(clean_arrays)
+    res, details_dict = organize_drawing_according_to_details_new.main_function(pretty, tables)
+
+    json_isos = json.dumps(isos)
+    json_result = json.dumps(res)
+    json_details =json.dumps(details_dict)
+    write_redis(uuid+"tol", general_tol,db)
+    write_redis(uuid+"dims", json_result, db)
+    write_redis(uuid+"isos",json_isos, db)
+    write_redis(uuid+"eps", str(number_blocks)+","+str(number_words), db)
+    write_redis(uuid+"details",json_details ,db)
+
+if __name__ == "__main__":
+    uuid = sys.argv[1]
+    filename = sys.argv[2]
+    db = sys.argv[3]
+    eps = sys.argv[4]
+    main(uuid,filename, db, eps)
+
+
+
+
+#main("33333", "/home/centurio/Projects/engineering_drawings_extraction/drawings/5152166_Rev04.pdf", "'/tmp/redis.sock', db=7",3)

+ 5 - 3
read_from_clustered_merged.py

@@ -70,6 +70,8 @@ def read(file):
             coords.append(ymin)
             coords.append(xmax)
             coords.append(ymax)
-            dict[element] = coords
-
-    return dict
+            if dict[elementt]:
+                dict[element] = coords
+            else:
+                dict[element] = coords
+    return dict

+ 72 - 126
temporary/blub.csv

@@ -1,126 +1,72 @@
-[67.790402, 11.570546];[73.239534, 11.570546];[67.790402, 20.626588];[73.239534, 20.626588];1
-[268.068994, 11.450546];[273.518126, 11.450546];[268.068994, 20.506588];[273.518126, 20.506588];1
-[167.989461, 11.570546];[173.438592, 11.570546];[167.989461, 20.626588];[173.438592, 20.626588];1
-[368.268523, 11.450546];[373.717654, 11.450546];[368.268523, 20.506588];[373.717654, 20.506588];1
-[468.348387, 11.450546];[473.797518, 11.450546];[468.348387, 20.506588];[473.797518, 20.506588];1
-[568.547916, 11.450546];[573.997047, 11.450546];[568.547916, 20.506588];[573.997047, 20.506588];1
-[122.630951, 46.695792];[190.286116, 46.695792];[122.630951, 60.279874];[190.286116, 60.279874];3
-[120.761894, 78.819233];[130.537431, 78.819233];[120.761894, 91.199965];[130.537431, 91.199965];3
-[646.430741, 113.055766];[715.046105, 113.055766];[646.430741, 126.639848];[715.046105, 126.639848];3
-[475.533479, 179.470821];[487.897401, 179.470821];[475.533479, 198.119921];[487.897401, 198.119921];1
-[150.11094, 166.850483];[169.239999, 166.850483];[150.11094, 175.906526];[169.239999, 175.906526];3
-[108.590957, 216.735724];[177.206123, 216.735724];[108.590957, 230.319806];[177.206123, 230.319806];3
-[141.830943, 335.450416];[147.819107, 335.450416];[141.830943, 344.506458];[147.819107, 344.506458];1
-[356.870857, 355.005249];[378.1424, 355.005249];[356.870857, 368.279803];[378.1424, 368.279803];3
-[144.590942, 406.782692];[173.852474, 406.782692];[144.590942, 411.90645];[173.852474, 411.90645];3
-[165.590934, 413.627848];[184.771375, 413.627848];[165.590934, 429.293089];[184.771375, 429.293089];3
-[63.230575, 420.770382];[88.83962, 420.770382];[63.230575, 429.826424];[88.83962, 429.826424];3
-[42.470583, 443.753959];[92.560972, 443.753959];[42.470583, 451.706412];[92.560972, 451.706412];3
-[193.670836, 421.547845];[210.211285, 421.547845];[193.670836, 429.293089];[210.211285, 429.293089];3
-[375.23085, 376.24524];[404.662389, 376.24524];[375.23085, 389.639794];[404.662389, 389.639794];3
-[302.030879, 379.143886];[336.502426, 379.143886];[302.030879, 388.906441];[336.502426, 388.906441];3
-[823.066288, 343.730413];[830.142318, 343.730413];[823.066288, 352.786455];[830.142318, 352.786455];3
-[463.790814, 439.010375];[470.327812, 439.010375];[463.790814, 448.066417];[470.327812, 448.066417];3
-[159.710792, 447.833957];[212.081156, 447.833957];[159.710792, 451.706412];[212.081156, 451.706412];3
-[42.470335, 454.902672];[211.633124, 454.902672];[42.470335, 505.626412];[211.633124, 505.626412];3
-[466.670813, 461.872555];[469.467056, 461.872555];[466.670813, 466.51979];[469.467056, 466.51979];1
-[705.831325, 461.872555];[731.067818, 461.872555];[705.831325, 466.51979];[731.067818, 466.51979];3
-[548.030781, 470.504063];[580.469249, 470.504063];[548.030781, 474.853041];[580.469249, 474.853041];3
-[667.910733, 470.504063];[688.949102, 470.504063];[667.910733, 474.853041];[688.949102, 474.853041];3
-[314.630874, 505.335609];[324.436384, 505.335609];[314.630874, 518.919691];[324.436384, 518.919691];3
-[408.110604, 505.335609];[417.916114, 505.335609];[408.110604, 518.919691];[417.916114, 518.919691];3
-[463.070815, 516.462648];[482.012282, 516.462648];[463.070815, 521.586406];[482.012282, 521.586406];3
-[143.870942, 524.02246];[197.447921, 524.02246];[143.870942, 536.386382];[197.447921, 536.386382];3
-[503.150619, 516.582648];[518.732192, 516.582648];[503.150619, 521.706406];[518.732192, 521.706406];3
-[480.950808, 525.285181];[483.269564, 525.285181];[480.950808, 531.719737];[483.269564, 531.719737];1
-[515.390794, 526.005181];[528.982379, 526.005181];[515.390794, 532.439737];[528.982379, 532.439737];3
-[543.230783, 516.462648];[554.732298, 516.462648];[543.230783, 521.586406];[554.732298, 521.586406];3
-[583.310767, 516.462648];[609.692421, 516.462648];[583.310767, 535.9864];[609.692421, 535.9864];3
-[555.350778, 525.405181];[567.031154, 525.405181];[555.350778, 531.839737];[567.031154, 531.839737];3
-[653.390739, 516.525184];[702.366371, 516.525184];[653.390739, 522.959741];[702.366371, 522.959741];3
-[653.390739, 536.445176];[690.366444, 536.445176];[653.390739, 542.879733];[690.366444, 542.879733];3
-[481.910807, 545.930332];[504.234616, 545.930332];[481.910807, 554.986374];[504.234616, 554.986374];3
-[514.190794, 546.467795];[556.170929, 546.467795];[514.190794, 554.213039];[556.170929, 554.213039];3
-[777.711531, 461.392555];[779.386259, 461.392555];[777.711531, 466.03979];[779.386259, 466.03979];1
-[743.751643, 461.872555];[753.346152, 461.872555];[743.751643, 466.51979];[753.346152, 466.51979];3
-[806.751614, 461.392555];[808.426342, 461.392555];[806.751614, 466.03979];[808.426342, 466.03979];1
-[735.710706, 470.504063];[791.770297, 470.504063];[735.710706, 474.853041];[791.770297, 474.853041];3
-[797.510681, 470.504063];[817.690262, 470.504063];[797.510681, 474.853041];[817.690262, 474.853041];3
-[368.269029, 575.93032];[373.71816, 575.93032];[368.269029, 584.986362];[373.71816, 584.986362];1
-[468.348598, 575.93032];[473.797729, 575.93032];[468.348598, 584.986362];[473.797729, 584.986362];1
-[705.470718, 542.210333];[790.359576, 542.210333];[705.470718, 551.266376];[790.359576, 551.266376];3
-[568.548127, 575.93032];[573.997258, 575.93032];[568.548127, 584.986362];[573.997258, 584.986362];1
-[668.627696, 575.93032];[674.076827, 575.93032];[668.627696, 584.986362];[674.076827, 584.986362];1
-[823.666285, 544.010333];[829.654449, 544.010333];[823.666285, 553.066375];[829.654449, 553.066375];1
-[793.551216, 556.486651];[809.654008, 556.486651];[793.551216, 562.146317];[809.654008, 562.146317];3
-[710.390716, 562.970325];[748.599674, 562.970325];[710.390716, 572.026367];[748.599674, 572.026367];3
-[586.910765, 568.366647];[633.756366, 568.366647];[586.910765, 574.026312];[633.756366, 574.026312];3
-[491.630803, 568.507468];[538.636672, 568.507468];[491.630803, 572.439753];[538.636672, 572.439753];3
-[268.0695, 575.93032];[273.518632, 575.93032];[268.0695, 584.986362];[273.518632, 584.986362];1
-[705.470718, 521.570342];[794.679443, 521.570342];[705.470718, 530.626384];[794.679443, 530.626384];3
-[653.390739, 556.486651];[689.893473, 556.486651];[653.390739, 562.146317];[689.893473, 562.146317];3
-[466.430813, 557.446651];[563.915856, 557.446651];[466.430813, 563.226317];[563.915856, 563.226317];3
-[100.550559, 567.405164];[110.302109, 567.405164];[100.550559, 573.83972];[110.302109, 573.83972];3
-[167.989931, 575.93032];[173.439062, 575.93032];[167.989931, 584.986362];[173.439062, 584.986362];1
-[712.190715, 470.504063];[724.810175, 470.504063];[712.190715, 474.853041];[724.810175, 474.853041];3
-[463.070815, 486.526679];[799.693722, 486.526679];[463.070815, 512.946337];[799.693722, 512.946337];3
-[42.470803, 542.502637];[72.932298, 542.502637];[42.470803, 547.626395];[72.932298, 547.626395];3
-[67.790402, 575.93032];[73.239534, 575.93032];[67.790402, 584.986362];[73.239534, 584.986362];1
-[477.110851, 461.392555];[506.78728, 461.392555];[477.110851, 466.03979];[506.78728, 466.03979];3
-[618.710753, 478.78406];[663.970438, 478.78406];[618.710753, 483.133038];[663.970438, 483.133038];3
-[42.470583, 549.941496];[208.019915, 549.941496];[42.470583, 563.159698];[208.019915, 563.159698];3
-[42.470583, 566.502628];[91.052115, 566.502628];[42.470583, 571.626386];[91.052115, 571.626386];3
-[823.426286, 443.810373];[829.963283, 443.810373];[823.426286, 452.866415];[829.963283, 452.866415];3
-[462.470815, 470.504063];[473.619336, 470.504063];[462.470815, 474.853041];[473.619336, 474.853041];3
-[99.35056, 510.285187];[161.902038, 510.285187];[99.35056, 516.719743];[161.902038, 516.719743];3
-[42.470803, 522.582645];[135.452419, 522.582645];[42.470803, 527.706403];[135.452419, 527.706403];3
-[528.950788, 309.462546];[583.367767, 309.462546];[528.950788, 321.730116];[583.367767, 321.730116];3
-[447.401371, 378.550836];[456.457414, 378.550836];[447.401371, 407.399837];[456.457414, 407.399837];1
-[233.270907, 372.222521];[277.119929, 372.222521];[233.270907, 384.826442];[277.119929, 384.826442];3
-[112.551016, 387.885236];[195.982459, 387.885236];[112.551016, 402.959789];[195.982459, 402.959789];3
-[275.44144, 398.470841];[284.497482, 398.470841];[275.44144, 432.239827];[284.497482, 432.239827];1
-[42.470803, 396.822696];[75.092321, 396.822696];[42.470803, 401.946454];[75.092321, 401.946454];3
-[527.270789, 295.662551];[583.367767, 295.662551];[527.270789, 307.930122];[583.367767, 307.930122];3
-[450.516211, 316.048318];[456.950767, 316.048318];[450.516211, 329.519874];[456.950767, 329.519874];1
-[260.030896, 338.445256];[289.342435, 338.445256];[260.030896, 351.839809];[289.342435, 351.839809];3
-[42.470583, 362.14271];[206.062152, 362.14271];[42.470583, 383.279797];[206.062152, 383.279797];3
-[42.470583, 406.782692];[81.93211, 406.782692];[42.470583, 411.90645];[81.93211, 411.90645];3
-[735.470706, 220.252619];[754.843312, 220.252619];[735.470706, 234.705879];[754.843312, 234.705879];3
-[263.683349, 260.725762];[278.136932, 260.725762];[263.683349, 273.479891];[278.136932, 273.479891];3
-[363.710855, 295.095693];[373.516364, 295.095693];[363.710855, 308.679775];[373.516364, 308.679775];3
-[267.833014, 296.210432];[281.562101, 296.210432];[267.833014, 305.266474];[281.562101, 305.266474];3
-[255.230898, 322.010421];[261.767895, 322.010421];[255.230898, 331.066464];[261.767895, 331.066464];3
-[42.470803, 386.8627];[109.892388, 386.8627];[42.470803, 391.986458];[109.892388, 391.986458];3
-[730.790708, 159.650486];[753.159781, 159.650486];[730.790708, 168.706529];[753.159781, 168.706529];3
-[664.790734, 162.770485];[681.759836, 162.770485];[664.790734, 171.826528];[681.759836, 171.826528];3
-[823.066288, 243.770453];[830.142318, 243.770453];[823.066288, 252.826495];[830.142318, 252.826495];3
-[174.59093, 249.050451];[208.359931, 249.050451];[174.59093, 267.946489];[208.359931, 267.946489];3
-[154.790938, 281.142557];[203.687919, 281.142557];[154.790938, 321.466468];[203.687919, 321.466468];3
-[31.910589, 343.730413];[38.986619, 343.730413];[31.910589, 352.786455];[38.986619, 352.786455];3
-[823.426286, 143.690493];[829.963283, 143.690493];[823.426286, 152.746535];[829.963283, 152.746535];3
-[614.150754, 225.772685];[631.59029, 225.772685];[614.150754, 242.985857];[631.59029, 242.985857];3
-[450.453489, 286.28323];[464.150764, 286.28323];[450.453489, 376.07985];[464.150764, 376.07985];1
-[141.950943, 244.850452];[148.487941, 244.850452];[141.950943, 253.906495];[148.487941, 253.906495];3
-[666.230734, 143.210493];[683.199836, 143.210493];[666.230734, 152.266535];[683.199836, 152.266535];3
-[528.03618, 149.412075];[541.310733, 149.412075];[528.03618, 224.63991];[541.310733, 224.63991];1
-[408.230413, 143.535754];[417.212672, 143.535754];[408.230413, 157.119836];[417.212672, 157.119836];1
-[502.59619, 161.248393];[515.990744, 161.248393];[502.59619, 212.879915];[515.990744, 212.879915];1
-[379.841398, 133.990852];[388.897441, 133.990852];[379.841398, 156.479937];[388.897441, 156.479937];1
-[348.163641, 125.988458];[365.976808, 125.988458];[348.163641, 142.79992];[365.976808, 142.79992];3
-[205.963601, 116.896848];[216.216897, 116.896848];[205.963601, 125.99995];[216.216897, 125.99995];3
-[552.470779, 63.102644];[620.927752, 63.102644];[552.470779, 75.370215];[620.927752, 75.370215];3
-[401.270839, 73.18264];[439.239891, 73.18264];[401.270839, 85.450211];[439.239891, 85.450211];3
-[32.150587, 143.690493];[38.687585, 143.690493];[32.150587, 152.746535];[38.687585, 152.746535];3
-[31.910589, 243.770453];[38.986619, 243.770453];[31.910589, 252.826495];[38.986619, 252.826495];3
-[823.426286, 43.490533];[829.963283, 43.490533];[823.426286, 52.546575];[829.963283, 52.546575];3
-[552.470779, 50.93053];[562.771048, 50.93053];[552.470779, 59.986572];[562.771048, 59.986572];3
-[407.750837, 53.382648];[456.287818, 53.382648];[407.750837, 65.650219];[456.287818, 65.650219];3
-[343.430863, 65.055785];[353.236372, 65.055785];[343.430863, 78.639867];[353.236372, 78.639867];3
-[32.390586, 544.010333];[38.37875, 544.010333];[32.390586, 553.066375];[38.37875, 553.066375];1
-[768.827013, 11.450546];[774.276145, 11.450546];[768.827013, 20.506588];[774.276145, 20.506588];1
-[342.230863, 30.855799];[417.326089, 30.855799];[342.230863, 44.439881];[417.326089, 44.439881];3
-[32.150587, 43.490533];[38.687585, 43.490533];[32.150587, 52.546575];[38.687585, 52.546575];3
-[32.150587, 443.810373];[38.687585, 443.810373];[32.150587, 452.866415];[38.687585, 452.866415];3
-[668.627485, 11.450546];[674.076616, 11.450546];[668.627485, 20.506588];[674.076616, 20.506588];1
-[798.35074, 564.107788];[814.89116, 564.107788];[798.35074, 571.853032];[814.89116, 571.853032];3
-[765.587245, 575.93032];[777.516363, 575.93032];[765.587245, 584.986362];[777.516363, 584.986362];3
+[116.3392, 10.9671];[124.651701, 10.9671];[116.3392, 31.4721];[124.651701, 31.4721];1
+[250.9792, 10.9671];[259.291701, 10.9671];[250.9792, 31.4721];[259.291701, 31.4721];1
+[392.7142, 10.9671];[401.026701, 10.9671];[392.7142, 31.4721];[401.026701, 31.4721];1
+[534.4492, 10.9671];[542.761701, 10.9671];[534.4492, 31.4721];[542.761701, 31.4721];1
+[676.1842, 10.9671];[684.496701, 10.9671];[676.1842, 31.4721];[684.496701, 31.4721];1
+[817.9192, 10.9671];[826.231701, 10.9671];[817.9192, 31.4721];[826.231701, 31.4721];1
+[959.6542, 10.9671];[967.966701, 10.9671];[959.6542, 31.4721];[967.966701, 31.4721];1
+[1094.2942, 10.9671];[1102.606701, 10.9671];[1094.2942, 31.4721];[1102.606701, 31.4721];1
+[45.9892, 72.7221];[53.260039, 72.7221];[45.9892, 93.2271];[53.260039, 93.2271];1
+[1165.6792, 72.7221];[1172.950039, 72.7221];[1165.6792, 93.2271];[1172.950039, 93.2271];1
+[775.586771, 166.650564];[804.533483, 166.650564];[775.586771, 182.697812];[804.533483, 182.697812];0
+[791.634019, 158.8749];[812.309147, 158.8749];[791.634019, 166.650564];[812.309147, 166.650564];0
+[799.409683, 153.691124];[817.492923, 153.691124];[799.409683, 158.8749];[817.492923, 158.8749];0
+[557.106912, 149.733756];[566.895854, 149.733756];[557.106912, 167.816842];[566.895854, 167.816842];1
+[134.159579, 152.935004];[167.147658, 152.935004];[134.159579, 171.01809];[167.147658, 171.01809];0
+[401.662262, 189.140861];[441.981024, 189.140861];[401.662262, 207.223947];[441.981024, 207.223947];0
+[45.5992, 198.0621];[53.640872, 198.0621];[45.5992, 218.5671];[53.640872, 218.5671];1
+[1165.2892, 198.0621];[1173.330872, 198.0621];[1165.2892, 218.5671];[1173.330872, 218.5671];1
+[401.662262, 224.579477];[441.981024, 224.579477];[401.662262, 242.662563];[441.981024, 242.662563];0
+[401.662262, 245.691844];[441.981024, 245.691844];[401.662262, 263.77493];[441.981024, 263.77493];0
+[846.608258, 326.080223];[1042.938171, 326.080223];[846.608258, 344.163309];[1042.938171, 344.163309];0
+[44.0392, 339.8871];[55.205863, 339.8871];[44.0392, 360.3921];[55.205863, 360.3921];1
+[850.9695, 413.248902];[868.317715, 413.248902];[850.9695, 431.331988];[868.317715, 431.331988];3
+[408.99074, 416.05912];[441.978818, 416.05912];[408.99074, 434.142206];[441.978818, 434.142206];0
+[408.99074, 437.171486];[441.978818, 437.171486];[408.99074, 455.254572];[441.978818, 455.254572];0
+[890.611042, 413.248902];[926.47982, 413.248902];[890.611042, 447.233588];[926.47982, 447.233588];3
+[1163.7292, 339.8871];[1174.895863, 339.8871];[1163.7292, 360.3921];[1174.895863, 360.3921];1
+[945.104942, 413.248902];[980.97372, 413.248902];[945.104942, 447.233588];[980.97372, 447.233588];3
+[434.653642, 472.610102];[441.984326, 472.610102];[434.653642, 490.693188];[441.984326, 490.693188];1
+[43.5292, 481.6221];[55.716688, 481.6221];[43.5292, 502.1271];[55.716688, 502.1271];1
+[1163.2192, 481.6221];[1175.406688, 481.6221];[1163.2192, 502.1271];[1175.406688, 502.1271];1
+[176.687461, 510.879574];[254.734389, 510.879574];[176.687461, 528.96266];[254.734389, 528.96266];0
+[769.095043, 530.652376];[787.178129, 530.652376];[769.095043, 570.971138];[787.178129, 570.971138];1
+[733.656427, 530.652376];[751.739513, 530.652376];[733.656427, 570.971138];[751.739513, 570.971138];1
+[712.54406, 530.652376];[730.627146, 530.652376];[712.54406, 570.971138];[730.627146, 570.971138];1
+[542.176785, 530.654582];[560.259871, 530.654582];[542.176785, 563.64266];[560.259871, 563.64266];1
+[521.064418, 530.654582];[539.147504, 530.654582];[521.064418, 563.64266];[539.147504, 563.64266];1
+[485.625802, 530.649074];[503.708888, 530.649074];[485.625802, 537.979758];[503.708888, 537.979758];0
+[557.106912, 511.14414];[566.895854, 511.14414];[557.106912, 529.227226];[566.895854, 529.227226];1
+[45.3142, 623.2521];[53.918371, 623.2521];[45.3142, 643.7571];[53.918371, 643.7571];1
+[1165.0042, 623.2521];[1173.608371, 623.2521];[1165.0042, 643.7571];[1173.608371, 643.7571];1
+[882.448459, 658.701588];[919.949242, 658.701588];[882.448459, 687.711396];[919.949242, 687.711396];3
+[653.64685, 658.93403];[803.600202, 658.93403];[653.64685, 702.117088];[803.600202, 702.117088];0
+[692.566595, 708.313633];[708.880573, 708.313633];[692.566595, 716.063566];[708.880573, 716.063566];0
+[737.104615, 708.143554];[763.459446, 708.143554];[737.104615, 715.893487];[763.459446, 715.893487];0
+[785.809572, 708.103869];[805.198848, 708.103869];[785.809572, 715.853802];[805.198848, 715.853802];0
+[967.0281, 709.5146];[1130.587402, 709.5146];[967.0281, 765.3146];[1130.587402, 765.3146];0
+[653.125274, 731.977291];[676.175986, 731.977291];[653.125274, 739.727224];[676.175986, 739.727224];0
+[653.102597, 743.571009];[685.263286, 743.571009];[653.102597, 751.320943];[685.263286, 751.320943];0
+[653.255668, 755.845044];[688.149904, 755.845044];[653.255668, 763.594977];[688.149904, 763.594977];0
+[653.862283, 768.27215];[679.117974, 768.27215];[653.862283, 776.022083];[679.117974, 776.022083];0
+[1086.599952, 663.435454];[1117.762614, 663.435454];[1086.599952, 671.185387];[1117.762614, 671.185387];0
+[936.006337, 708.103869];[971.255616, 708.103869];[936.006337, 715.853802];[971.255616, 715.853802];0
+[652.564014, 719.856328];[684.880476, 719.856328];[652.564014, 727.606261];[684.880476, 727.606261];0
+[44.0542, 748.7871];[55.158362, 748.7871];[44.0542, 769.2921];[55.158362, 769.2921];1
+[971.195682, 662.874193];[1049.1463, 662.874193];[971.195682, 670.624126];[1049.1463, 670.624126];0
+[809.71134, 766.469312];[841.433557, 766.469312];[809.71134, 774.219245];[841.433557, 774.219245];0
+[935.643501, 766.469312];[978.950875, 766.469312];[935.643501, 774.219245];[978.950875, 774.219245];0
+[1137.7948, 769.5933];[1151.865636, 769.5933];[1137.7948, 784.6303];[1151.865636, 784.6303];3
+[860.0295, 778.1931];[880.377928, 778.1931];[860.0295, 790.4961];[880.377928, 790.4961];0
+[116.3392, 810.3321];[124.651701, 810.3321];[116.3392, 830.8371];[124.651701, 830.8371];1
+[250.9792, 810.3321];[259.291701, 810.3321];[250.9792, 830.8371];[259.291701, 830.8371];1
+[392.7142, 810.3321];[401.026701, 810.3321];[392.7142, 830.8371];[401.026701, 830.8371];1
+[534.4492, 810.3321];[542.761701, 810.3321];[534.4492, 830.8371];[542.761701, 830.8371];1
+[676.1842, 810.3321];[684.496701, 810.3321];[676.1842, 830.8371];[684.496701, 830.8371];1
+[809.6253, 803.42556];[836.140748, 803.42556];[809.6253, 811.168248];[836.140748, 811.168248];0
+[817.9192, 810.3321];[826.231701, 810.3321];[817.9192, 830.8371];[826.231701, 830.8371];1
+[935.643501, 803.563542];[971.83397, 803.563542];[935.643501, 811.313475];[971.83397, 811.313475];0
+[959.6542, 810.3321];[967.966701, 810.3321];[959.6542, 830.8371];[967.966701, 830.8371];1
+[1163.7442, 748.7871];[1174.848363, 748.7871];[1163.7442, 769.2921];[1174.848363, 769.2921];1
+[1061.5133, 803.563542];[1099.465074, 803.563542];[1061.5133, 811.313475];[1099.465074, 811.313475];0
+[1094.2942, 810.3321];[1102.606701, 810.3321];[1094.2942, 830.8371];[1102.606701, 830.8371];1

File diff suppressed because it is too large
+ 72 - 126
temporary/list_to_csv_with_corner_points.csv


File diff suppressed because it is too large
+ 66 - 125
temporary/values_clusteredfrom_precomputed_dbscan.csv