import time import cv2 import threading import tensorflow as tf import json from keras.layers import Conv1D, MaxPooling1D, Flatten, Dense, Dropout, BatchNormalization, Activation, Add, GlobalAveragePooling1D from keras.preprocessing.image import ImageDataGenerator from keras.optimizers import Adam import math class ConnectingRectangle(): MAX_HORIZONTAL_ANGLE = math.tan(math.radians(25) ) MAX_VERTICAL_ANGLE = math.tan(math.radians(50) ) MIN_DISTANCE_BETWEEN_HORIZONTAL_EDGES = 100 def __init__(self, list_ending_puncts = None): self.list_ending_puncts = list_ending_puncts self.measure_light_obj = MeasureLightAround() # def detecting_biggest_rectangle(list_ending_puncts): # # list_ending_puncts -> x1, y1, x2, y2 # pass @staticmethod def _find_tan( list_pucts ): return (list_pucts[1] - list_pucts[3] ) / (list_pucts[0] - list_pucts[2]) def categorize_edges(self): self.likely_edges_horizontal = [[],[]] # right -> 0; left -> 1 self.likely_edges_vertical = [[], []] # right -> 0; left -> 1 for id_contour in range(len(self.list_ending_puncts)): tan_ = ConnectingRectangle._find_tan(self.list_ending_puncts[id_contour]) if abs(tan_) <= ConnectingRectangle.MAX_HORIZONTAL_ANGLE: if tan_ > 0: self.likely_edges_horizontal[0].append(self.list_ending_puncts[id_contour]) else: self.likely_edges_horizontal[1].append(self.list_ending_puncts[id_contour]) elif abs(tan_ ) >= ConnectingRectangle.MAX_VERTICAL_ANGLE: if tan_ > 0 : self.likely_edges_vertical[0].append(self.list_ending_puncts[id_contour]) else: self.likely_edges_vertical[1].append(self.list_ending_puncts[id_contour]) return self.likely_edges_horizontal, self.likely_edges_vertical @staticmethod def verify_distance(self, list_sided_edges): distances = [] max_distance_ids = 0 max_distance_val = None if len(list_sided_edges) == 0 : return distances, max_distance_ids, max_distance_val for id_contour_base in range(len(list_sided_edges)-1): for id_contour_adjusted in range(id_contour_base+1,len(list_sided_edges) ): distance_between_up_down_edges = abs(list_sided_edges[id_contour_base][3] - list_sided_edges[id_contour_adjusted][3]) if distance_between_up_down_edges > ConnectingRectangle.MIN_DISTANCE_BETWEEN_HORIZONTAL_EDGES : if distance_between_up_down_edges > max_distance_val: max_distance_ids = [id_contour_base,id_contour_adjusted] max_distance_val = distance_between_up_down_edges distances.append([id_contour_base,id_contour_adjusted, abs(distance_between_up_down_edges )] ) return distances, max_distance_id, max_distance_val def horizontal_edges_containers(self, ): if len(self.likely_edges_horizontal[0]) + len(self.likely_edges_horizontal[1]) <= 2: # będzie zero kontur if len(self.likely_edges_horizontal[0] ) == 0 and len(self.likely_edges_horizontal[1] ) == 0: return [] if len(self.likely_edges_horizontal[0] ) == 1 and len(self.likely_edges_horizontal[1] ) == 0: return self.likely_edges_horizontal[0] if len(self.likely_edges_horizontal[0] ) == 0 and len(self.likely_edges_horizontal[1] ) == 1: return self.likely_edges_horizontal[1] # będzie po jednej konturze if len(self.likely_edges_horizontal[0] ) == 1 and len(self.likely_edges_horizontal[1] ) == 1: id_lenghter = np.argmax( [ ConnectingRectangle.lenght_contour(self.likely_edges_horizontal[0]), ConnectingRectangle.lenght_contour(self.likely_edges_horizontal[1]) ] ) return self.likely_edges_horizontal[id_lenghter ] else: distances_right, max_distance_id_right, max_distance_val_right = ConnectingRectangle.verify_distance(self.likely_edges_horizontal[0]) distances_left, max_distance_id_left, max_distance_val_left = ConnectingRectangle.verify_distance(self.likely_edges_horizontal[1]) if max_distance_val_right != 0 and max_distance_val_left == 0: return [ self.likely_edges_horizontal[0][distances_right[0]] , self.likely_edges_horizontal[0][distances_right[1]] ] elif max_distance_val_right == 0 and max_distance_val_left != 0: return [ self.likely_edges_horizontal[1][distances_left[0]] , self.likely_edges_horizontal[1][distances_left[1]] ] elif max_distance_val_right != 0 and max_distance_val_left != 0 : id_max_distance = np.argmax([max_distance_val_right,max_distance_val_left]) if id_max_distance == 0 : return [ self.likely_edges_horizontal[0][distances_right[0]] , self.likely_edges_horizontal[0][distances_right[1]] ] elif id_max_distance == 1 : return [ self.likely_edges_horizontal[1][distances_left[0]] , self.likely_edges_horizontal[1][distances_left[1]]] def vertical_edges(self,): self.edges_with_equati self.pairs_hor_edges = [] self.puncts_of_interseti all_c all_conts.extend(self.likely_edges_vertical[1]) # .extend(self.likely_edges_vertical[1]) for id_, contour in enumerate(all_conts) : directi self.edges_with_equation[contour] = direction_factors for contour_right in range( len( self.likely_edges_vertical[0] ) ) : for contour_left in range( len( self.likely_edges_vertical[1] )) : x, y = ConnectingRectangle.puncts_of_intersection(self.edges_with_equation[contour_right],self.edges_with_equation[contour_left]) if x is None and y is None: return 0,0 if y > img_height: # daj tutaj adn. że to wynika z geometrii perspektywicznej self.pairs_hor_edges.append([ contour_right, contour_left ] ) self.puncts_of_intersetion_horizontal_edges.append(y) return self.pairs_hor_edges def vertical_edges_containers(self, ): if len(self.likely_edges_vertical[0] ) >= 1 and len(self.likely_edges_vertical[1] ) >= 1: self.vertical_edges() if len( self.pairs_hor_edges ) ==1 : return self.pairs_hor_edges[0] elif len( self.pairs_hor_edges) > 1: #tutaj tworzymy te kolory return self.measure_light_obj.pick_max_var_surronded_area(self.pairs_hor_edges) elif len( self.pairs_hor_edges ) == 0 : pass # problem tutaj sprawdz czy może te które są njablizęj a jeśli nie to odrzuć wsztskie elif len(self.likely_edges_vertical[0] ) == 0 and len(self.likely_edges_vertical[1] ) == 0: return [] elif len(self.likely_edges_vertical[0] ) == 0 and len(self.likely_edges_vertical[1] ) == 1: return self.likely_edges_vertical[1] elif len(self.likely_edges_vertical[0] ) == 1 and len(self.likely_edges_vertical[1] ) == 0: return self.likely_edges_vertical[0] @staticmethod def lenght_contour(contour): return np.sqrt( ( contour[0] - contour[2] ) ** 2 + ( contour[1] - contour[3] ) ** 2 ) @staticmethod def equation_line(bordered_puncts): a = (bordered_puncts[1] - bordered_puncts[3]) / (bordered_puncts[0] - bordered_puncts[2]) b = bordered_puncts[1] - a*bordered_puncts[0] return [ a,b ] @staticmethod def puncts_of_intersection(a1,b1,a2,b2): try: x = (b2-b1) / (a1 - a2) y = x * a1 + b1 return x, y except ZeroDivisionError: return None, None @staticmethod def sum_from_1_to_n(n): return n(n+1)/2 @staticmethod def mid_punct(contour ): x = int( ( contour[0] + contour[2]) / 2 ) y = int( ( contour[0] + contour[2]) / 2 ) return x, y def extreme_val_hor_edges(self,a,b): x = ( ConnectingRectangle.img_height - b ) / a if a > 0 : if b> 0 : return (0,b) , (x,ConnectingRectangle.img_height) else: x1 = -b/a return (0,x1) , (x,ConnectingRectangle.img_height) else: x_hor = -b/a if x_hor > ConnectingRectangle.img_width: y1 = ConnectingRectangle.img_width * a + b return (x,ConnectingRectangle.img_height), (ConnectingRectangle.img_width, y1) else: return (x,ConnectingRectangle.img_height), (x_hor, 0) def extreme_val_ver_edges(self,a,b): if a> 0 : if b> 0 : y = ConnectingRectangle.img_width * a + b if y > ConnectingRectangle.img_height : x = ( ConnectingRectangle.img_height - b ) /a return (0, b), (x, ConnectingRectangle.img_height ) else: return (0, b), (ConnectingRectangle.img_width, y) elif b< 0 : x = -b/a y = ConnectingRectangle.img_width * a + b return (x, 0), (ConnectingRectangle.img_width, y) elif a< 0 : y = a * ConnectingRectangle.img_width + b if b > ConnectingRectangle.img_height : x = (ConnectingRectangle.img_height - b)/a return (x,ConnectingRectangle.img_height) , (ConnectingRectangle.img_width, y) else: return (0, b), ( ConnectingRectangle.img_width, y) def _crop_image_without_hor(self, vertical_edges): ver1, ver2 = ConnectingRectangle.equation_line(vertical_edges[0]), ConnectingRectangle.equation_line(vertical_edges[1]) pt1, pt2 = self.extreme_val_ver_edges(*ver1) pt3, pt4 = self.extreme_val_ver_edges(*ver2) return [pt1, pt2, pt3, pt4] def _crop_image_two_ver_one_hor(self, vertical_edges,horizontal_edges): ver1, ver2 = ConnectingRectangle.equation_line(vertical_edges[0]), ConnectingRectangle.equation_line(vertical_edges[1]) a_hor ,b_hor = ConnectingRectangle.equation_line(horizontal_edges[0]) pt3 = ConnectingRectangle.puncts_of_intersection(a_hor, b_hor, *ver1) pt4 = ConnectingRectangle.puncts_of_intersection(a_hor, b_hor, *ver2) pt1 = self.extreme_val_ver_edges(*ver1) pt2 = self.extreme_val_ver_edges(*ver2) if a_hor > 0 : min_x_intersection = min([pt3,pt4], key = lambda x: x[0] ) if pt1[0][0] < min_x_intersection: pt1_choice = pt1[0] else: pt1_choice = pt1[1] if pt2[0][0] < min_x_intersection: pt2_choice = pt2[0] else: pt2_choice = pt2[1] else: max_x_intersecti key = lambda x: x[0] ) if pt1[0][0] > max_x_intersection: pt1_choice = pt1[0] else: pt1_choice = pt1[1] if pt2[0][0] > max_x_intersection: pt2_choice = pt2[0] else: pt2_choice = pt2[1] return [pt1_choice, pt2_choice, pt3, pt4] def _crop_image_one_ver_two_hor(self, vertical_edges,horizontal_edges): hor1, hor2 = ConnectingRectangle.equation_line(horizontal_edges[0]), ConnectingRectangle.equation_line(horizontal_edges[1]) a_ver ,b_ver = ConnectingRectangle.equation_line(vertical_edges[0]) pts1 = self.extreme_val_hor_edges(*hor1) pts2 = self.extreme_val_hor_edges(*hor2) pt3 = ConnectingRectangle.puncts_of_intersection(a_ver, b_ver, *hor1) pt4 = ConnectingRectangle.puncts_of_intersection(a_ver, b_ver, *hor2) if vertical_edges > 0.55 * ConnectingRectangle.img_height: pt1 = min(pts1, key = lambda x: x[1]) pt2 = min(pts1, key = lambda x: x[1]) elif vertical_edges < 0.45 * ConnectingRectangle.img_height: pt1 = max(pts1, key = lambda x: x[1]) pt2 = max(pts1, key = lambda x: x[1]) return [pt1, pt2, pt3, pt4 ] #Mozna tu dodać jakby ifa # else: # pass # coś zjebanego def _crop_image_two_hor_two_ver(self, vertical_edges,horizontal_edges): corner_puncts = [] vertical_lines_equati ConnectingRectangle.equation_line(vertical_edges[1])] horiz equation_line(horizontal_edges[0]) for ver_equa in vertical_lines_equations: for hor_equa in horizontal_lines_equations: corner_puncts.append(ConnectingRectangle.puncts_of_intersection(*ver_equa, *hor_equa) ) return corner_puncts def _crop_image_without_edges(self,): return [(0,ConnectingRectangle.img_height) , (ConnectingRectangle.img_width, 0),(ConnectingRectangle.img_width,ConnectingRectangle.img_height) , (0,0)] def _calculate_corner_puncts(self, vertical_edges, horizontal_edges): if vertical_edges is None and horizontal_edges is None: print(f'vertical_edges {vertical_edges} horizontal_edges {horizontal_edges}') return self._crop_image_without_edges() # najgorszy przypadek elif len( vertical_edges) == 2 and len( horizontal_edges ) == 2 : return self._crop_image_two_hor_two_ver(vertical_edges, horizontal_edges) elif len( vertical_edges) == 2 and len( horizontal_edges ) == 1 : return self._crop_image_two_ver_one_hor(vertical_edges , horizontal_edges) elif len(vertical_edges) == 2 and len( horizontal_edges ) == 0 : return self._crop_image_without_hor(vertical_edges) elif len(verical_edges ) == 1 and len(horizontal_edges ) == 2: return self._crop_image_one_ver_two_hor(verical_edges , horizontal_edges) else: print(f'vertical_edges {vertical_edges} horizontal_edges {horizontal_edges}') return self._crop_image_without_edges() # cały obraz def find_corner_puncts_img(self,lines_edges): self.list_ending_puncts = lines_edges self.categorize_edges() self.ver_ = self.vertical_edges_containers() self.hor_ = self.horizontal_edges_containers() # tutaj napisz dodaj argumenty return self._calculate_corner_puncts(self.ver_, self.hor_) class MeasureLightAround(): def __init__(self,c : self.c def kernel_light_measure(self, x,y,side, ): half_kernel = self.kernel_size//2 sum_pixel = 0 for id_ in range(self.kernel_size): if side == "left": current_y = y - half_kernel + id_ elif side == "right": current_x = x - half_kernel + id_ for amount_row in range(self.kernel_size - id_ ): if side == "left": current_x = x - half_kernel + amount_row + id_ elif side == "right" : current_y = y - half_kernel + amount_row + id_ if current_y > ConnectingRectangle.img_height and current_y >= 0 and current_x <= ConnectingRectangle.img_width and current_x >= 0 : sum_pixel += img[current_x, current_y] else: sum_pixel += 255 return sum_pixel / ConnectingRectangle.sum_from_1_to_n(self.kernel_size) def check_approximation_pixel(self, contour, ): x , y = ConnectingRectangle.mid_punct(contour) mean_right = self.kernel_light_measure(x, y, side = "right") mean_left = self.kernel_light_measure(x, y, side = "left") return [mean_right, mean_left] def pick_max_var_surronded_area(self, pairs_contours, ): self.var_values = [] for right_cont, left_cont in pairs_contours: right_area = self.check_approximation_pixel(right_cont) left_area = self.check_approximation_pixel(left_cont) self.var_values.append( np.var(right_area.extend(left_area)) ) return pairs_contours[ np.argmax(self.var_values) ], self.var_values data = [[467, 366, 506, 49], [439, 371, 659, 374], [24, 148, 97, 385], [515, 373, 567, 43], [516, 373, 568, 43], [94, 380, 356, 393], [436, 375, 675, 379], [96, 385, 418, 385]] connecting_obj = ConnectingRectangle() connecting_obj.find_corner_puncts_img(data) # def horizontal_down(a,b ): # x = -b/ a # if x> ConnectingRectangle.img_width or x < 0 : # ConnectingRectangle.img_height / a # def horizontal_up(a,b): # pass # def extreme_values_ver_edges_up(a, b): # y_max = ConnectingRectangle.img_width * a + b # if y_max > ConnectingRectangle.img_height: # x_max = (ConnectingRectangle.img_height - b) /a # return x_max, ConnectingRectangle.img_height # else: # return ConnectingRectangle.img_width ,y_max # def extreme_values_ver_edges_down(a,b): # if b> 0 : # return 0, b # else: # x_min = -b / a # return x_min, 0