def _load_file_weight(self, path): # Training if Validator.is_type(path, str): if os.path.isfile(path): self.model.load_weights(path) return True raise InappropriateArgsError("Model not founded in directory") raise InappropriateArgsError("Input not valid")
def _load_model(self, path): if Validator.is_type(path, str): if os.path.isfile(path): with open(path, "r") as f: json_str = f.read() f.close() self.model = keras.models.model_from_json(json_str) return True raise InappropriateArgsError("Model not founded in directory") raise InappropriateArgsError("Input not valid")
def __init__(self, pure_sudoku_field): if Validator.is_type(pure_sudoku_field, np.ndarray): self.img = pure_sudoku_field self.sudoku_size = 9 self.height, self.width = self._get_height_width(self.img) self.error = self.width // 200 # some lines are thicker than others self.cut_border = 3 # try to avoid border lines of the square with the number self.model = Char74kClassify() if self.height != self.width: raise InappropriateArgsError( "processing sudoku field! The height and width are not matching" ) else: raise InappropriateArgsError("processing sudoku field input: " + str(pure_sudoku_field))
def __init__(self, parent, text, **kwargs): if (Validator.is_type(parent, tkinter.Tk) or Validator.is_type(parent, Frame)) and Validator.is_type(text, str): super().__init__(master=parent, text=text) self.config(font=(var.LABEL_FONT, var.LABEL_FONT_SIZE), fg=var.LABEL_TEXTCOLOR) self.grid(kwargs) else: raise InappropriateArgsError("creating a label!")
def __init__(self, parent, height=10, width=10, **kwargs): if Validator.is_positive_number([height, width]) and \ (Validator.is_type(parent, tkinter.Tk) or Validator.is_type(parent, Frame)): super().__init__(master=parent, height=height, width=width) self.grid(kwargs) else: raise InappropriateArgsError("creating a frame!")
def _img_to_array(self, img): if Validator.is_type(img, np.ndarray): img = np.array(img) img = img.astype('float32') img /= 255 return img raise InappropriateArgsError("Input not valid")
def __init__(self, bt1_text, bt1_funct, bt2_text, bt2_funct): if Validator.is_type([bt1_text, bt2_text], str) and Validator.is_function([bt1_funct, bt2_funct]): super().__init__() self.title(var.TITLE_TEXT) self.title_frame = widgets.Frame(self, row=1, padx=var.BORDER, pady=var.BORDER) self.title_label = widgets.Title(self.title_frame, var.TITLE_TEXT) self.info_frame = widgets.Frame(self, row=3, padx=var.BORDER, pady=var.BORDER) self.info_label = widgets.Label(self.info_frame, "") self.bot_frame = widgets.Frame(self, row=4, sticky="ew", padx=var.BORDER, pady=var.BORDER) self.bot_frame.grid_columnconfigure(0, weight=1) self.bot_frame.grid_columnconfigure(2, weight=1) self.left_button_frame = widgets.Frame(self.bot_frame, row=0, column=0, sticky="w") self.right_button_frame = widgets.Frame(self.bot_frame, row=0, column=2, sticky="e") self.left_button = widgets.Button(self.left_button_frame, bt1_text, bt1_funct) self.right_button = widgets.Button(self.right_button_frame, bt2_text, bt2_funct) self.protocol("WM_DELETE_WINDOW", self._on_destroy) self.resizable(False, False) else: raise InappropriateArgsError("a main template!")
def _get_number(self, img): if Validator.is_type(img, np.ndarray): img = self._prepare_image_for_recognizing_or_return_0(img) if Validator.is_type(img, int) and img == 0: return 0 return int(self.model.classify_image(img)) raise InappropriateArgsError("getting a number! arg: " + str(img))
def _get_cropped_tl_br_point(self, x1, y1, x2, y2): if Validator.is_positive_number([x1, y1, x2, y2]): return (x1 + self.cut_border, y1 + self.cut_border), (x2 - self.cut_border, y2 - self.cut_border) raise InappropriateArgsError( "getting cropped top-left bottom-right point")
def display_message(self, text, after_error_text, color, error_duration=1): if Validator.is_type([text, after_error_text, color], str) and Validator.is_positive_number(error_duration): self.info_label.config(fg=color) self.info_label["text"] = text return self.after(error_duration * 1000, self.set_info_label, after_error_text) else: raise InappropriateArgsError("setting info label text!")
def _get_distance_between_points(self, p1, p2): if Validator.is_type([p1, p2], tuple) and Validator.is_number( [p1[0], p1[1], p2[0], p2[1]]): return math.sqrt((p1[0] - p2[0])**2 + (p1[1] - p2[1])**2) raise InappropriateArgsError( "calculating distance between points p1: " + str(p1) + " and p2: " + str(p2))
def _get_image_from_coords(self, x_error, x, y_error, y, padding): if Validator.is_positive_number([x_error, x, y_error, y, y_error, padding]) and \ Validator.is_type([x, y, x_error, y_error, padding], int): x1, y1, x2, y2 = self._get_tr_bl_corners_of_little_square( x_error, x, y_error, y, padding) return self._extract_field_square_with_number_image(x1, y1, x2, y2) raise InappropriateArgsError("getting image from coors!")
def set_info_label(self, text): if Validator.is_type(text, str) and not isinstance(text, list): self.info_label.config(fg="black") self.info_label["text"] = text return text else: raise InappropriateArgsError("setting info label text!")
def _create_white_picture(self, width, height): if Validator.is_positive_number([width, height]) and Validator.is_type( [width, height], int): img = np.zeros((height, width), dtype=np.uint8) img.fill(255) # must be white return img raise InappropriateArgsError("creating white picture")
def __init__(self, parent, text, action, **kwargs): if (Validator.is_type(parent, tkinter.Tk) or Validator.is_type(parent, Frame)) \ and Validator.is_type(text, str) and Validator.is_function(action): super().__init__(master=parent, text=text, command=action, width=12) self.config(bg=var.BUTTON_BACKGROUND, fg=var.BUTTON_TEXTCOLOR) self.grid(kwargs) else: raise InappropriateArgsError("creating a button!")
def _extract_field_square_with_number_image(self, x1, y1, x2, y2): if Validator.is_positive_number( [x1, y1, x2, y2]) and Validator.is_type([x1, y1, x2, y2], int): p1, p4 = self._get_cropped_tl_br_point(x1, y1, x2, y2) r = cv2.boundingRect(np.array([[p1[0], p1[1]], [p4[0], p4[1]]])) return self.img[r[1]:r[1] + r[3], r[0]:r[0] + r[2]] raise InappropriateArgsError( "extracting field square with number image")
def _get_higher_lower_diff(self, width, height): if Validator.is_positive_number([width, height]): higher, lower = max(width, height), min(width, height) diff = lower * 100 if higher > 0: diff = (lower / higher) * 100 return higher, lower, diff raise InappropriateArgsError("getting higher lower difference")
def _get_points_on_line(self, rho, theta): if Validator.is_number([rho, theta]): a, b = np.cos(theta), np.sin(theta) x0, y0 = a * rho, b * rho return int(x0 + 1000 * (-b)), int(y0 + 1000 * a), int(x0 - 1000 * (-b)), int(y0 - 1000 * a) raise InappropriateArgsError("getting points with rho: " + str(rho) + " and theta: " + str(theta))
def _get_tr_bl_corners_of_little_square(self, x_error, x, y_error, y, padding): if Validator.is_positive_number([x, y, x_error, y_error, padding]): x_error = self._update_error(x, x_error) x1, y1 = self._calculate_x_y(x, y, x_error, y_error, padding) next_point_error = self._update_error(x + 1, x_error) return x1, y1, x1 + padding + next_point_error, y1 + padding + y_error raise InappropriateArgsError( "getting top-right and bottom-left corners of little square")
def _prepare_original_for_recognition(self, img, height, width, x, y, kernel): # thicker the number and extract it (hopefully) if Validator.is_type([img, kernel], np.ndarray) and Validator.is_positive_number( [height, width, x, y]): original = cv2.erode(img, kernel) return original[y:y + height, x:x + width] raise InappropriateArgsError("preparing image for recognition!")
def _get_coords_of_angle(self, lines): if Validator.is_type(lines, np.ndarray): angles = np.array([line[0][1] for line in lines ]) # returns angles in [0, pi] in radians # multiply the angles by two and find coordinates of that angle return np.array( [[np.cos(2 * angle), np.sin(2 * angle)] for angle in angles], dtype=np.float32) raise InappropriateArgsError("getting the coordinates of the angles" + str(lines))
def _draw_lines_if_true(self, y, padding, y_error, draw): if not (Validator.is_positive_number([y, padding, y_error]) and Validator.is_type(draw, bool)): raise InappropriateArgsError("drawing lines") if draw: self._draw_line(0, padding * y + y_error, self.width, padding * y + y_error) self._draw_line(padding * y + y_error, 0, padding * y + y_error, self.height) return True return False
def get_solution(unsolved_matrix, print_solution=False): if Validator.is_9x9_integers_field(unsolved_matrix): solution = SudokuSolver._solve_sudoku(unsolved_matrix) if solution: if print_solution: SudokuSolver.print_sudoku(unsolved_matrix) return unsolved_matrix if print_solution: print("No solution!") return False # can not solve sudoku raise InappropriateArgsError("getting solution for sudoku field")
def _hide_smaller_blobs(self, max_point): if Validator.is_type(max_point, tuple) and Validator.is_positive_number( [max_point[0], max_point[1]]): for y in range(self.height): row = self.changing_img[y] for x in range(self.width): if row[x] == 64 and max_point[0] != x and max_point[ 1] != y: # fills gray parts with black cv2.floodFill(self.changing_img, None, (x, y), 0) return True raise InappropriateArgsError("hiding smaller blobs with point: " + str(max_point))
def _run_kmeans_on_coords(self, lines, k, **kwargs): if Validator.is_type(lines, np.ndarray) and Validator.is_positive_number( k) and Validator.is_type(k, int): # Define criteria = (type, max_iter, epsilon) criteria, flags, attempts = self._get_criteria_flags_attempts( **kwargs) pts = self._get_coords_of_angle(lines) # run k-means on the coordinates labels, centers = cv2.kmeans(pts, k, None, criteria, attempts, flags)[1:] return labels.reshape(-1) # transpose to row vector raise InappropriateArgsError("running k-means on coordinates: " + str(lines))
def _change_image_like_training_images(self, image, width, height): # this function adds white corners around the digit. The image is then more similar to the training set images! if Validator.is_positive_number([width, height]) and Validator.is_type([width, height], int) and \ Validator.is_type(image, np.ndarray) and width >= image.shape[1] and height >= image.shape[0]: new_img = self._create_white_picture(width, height) # completely white smaller_height, smaller_width = self._get_height_width(image) x_offset, y_offset = self._get_offset(width, height, smaller_height, smaller_width) new_img[y_offset:y_offset + smaller_height, x_offset:x_offset + smaller_width] = image return new_img raise InappropriateArgsError("changing image like training images!")
def _number_unassigned(matrix): if Validator.is_9x9_integers_field(matrix): num_unassign = 0 for i in range(0, SIZE): for j in range(0, SIZE): if matrix[i][j] == 0: # cell is unassigned row = i col = j num_unassign = 1 a = [row, col, num_unassign] return a a = [-1, -1, num_unassign] return a raise InappropriateArgsError("number unassigned")
def __init__(self, parent, number, readonly=False, **kwargs): if Validator.is_positive_number(number) and Validator.is_type(number, int) and number <= 9 and\ (Validator.is_type(parent, tkinter.Tk) or Validator.is_type(parent, Frame)) and \ Validator.is_type(readonly, bool): self.value = tkinter.StringVar() self.value.trace('w', self._limit_size) super().__init__(master=parent, textvariable=self.value) self.grid(kwargs) self.config(justify='center', width=var.SUDOKU_SQUARE_SIZE, font=(var.NUMBERS_FONT, var.NUMBERS_SIZE)) if number > 0: # 0 is empty self.value.set(str(number)) if readonly: self.config(state='readonly') else: raise InappropriateArgsError("creating an entry!")
def _get_longest_line(self, tl, tr, bl, br): if Validator.is_type([tl, tr, bl, br], tuple) and \ Validator.is_number([tl[0], tl[1], tr[0], tr[1], bl[0], bl[1], br[0], br[1]]): tltr = self._get_distance_between_points(tl, tr) tlbl = self._get_distance_between_points(tl, bl) trbr = self._get_distance_between_points(tr, br) blbr = self._get_distance_between_points(bl, br) max_value = max([tltr, tlbl, trbr, blbr]) # returns the max value of the list min_value = min([tltr, tlbl, trbr, blbr]) # returns the min value of the list if max_value - min_value > max_value * 0.1: # if the difference is grater than 10 % of max value raise SudokuFieldSizeError( ) # one corner wasn't detected so we should try it again return max_value raise InappropriateArgsError("calculating the longest line")
def _prepare_image_for_recognizing_or_return_0(self, img): if not Validator.is_type(img, np.ndarray): raise InappropriateArgsError( "preparing image for recognition! arg: " + str(img)) working_img, original = self._get_transformed_img_and_original(img) contours = self._get_contours(working_img) if contours: x, y, width, height = self._get_x_y_width_height_from_contours( contours) higher, lower, diff = self._get_higher_lower_diff(width, height) if 20 < diff < 90 and height > 7 and width > 7: # some parameters that tries to separate edges from numbers original = self._prepare_original_for_recognition( original, height, width, x, y, self._get_kernel(3, 3)) return self._change_image_like_training_images( original, working_img.shape[1], working_img.shape[0]) return 0 # square is not containing any number