def iter_blob_extremes(image, n=5): original_shape = image.shape[::-1] if max(original_shape) < 2000: size = (500, 500) y_scale = original_shape[0] / 500 x_scale = original_shape[1] / 500 else: size = (1000, 1000) y_scale = original_shape[0] / 1000 x_scale = original_shape[1] / 1000 img = resize(image, size) bimg = gaussian_filter(img, sigma=1.0) bimg = threshold_adaptive(bimg, 20, offset=2 / 255) bimg = -bimg bimg = ndi.binary_fill_holes(bimg) label_image = label(bimg, background=False) label_image += 1 regions = regionprops(label_image) regions.sort(key=attrgetter('area'), reverse=True) iter_n = 0 for region in regions: try: iter_n += 1 if iter_n > n: break # Skip small images if region.area < int(np.prod(size) * 0.05): continue coords = get_contours( add_border(label_image == region.label, size=label_image.shape, border_size=1, background_value=False))[0] coords = np.fliplr(coords) top_left = sorted(coords, key=lambda x: np.linalg.norm(np.array(x)))[0] top_right = sorted(coords, key=lambda x: np.linalg.norm( np.array(x) - [img.shape[1], 0]))[0] bottom_left = sorted(coords, key=lambda x: np.linalg.norm( np.array(x) - [0, img.shape[0]]))[0] bottom_right = sorted( coords, key=lambda x: np.linalg.norm( np.array(x) - [img.shape[1], img.shape[0]]))[0] scaled_extremes = [(int(x[0] * y_scale), int(x[1] * x_scale)) for x in (top_left, top_right, bottom_left, bottom_right)] yield scaled_extremes except Exception: pass raise SudokuExtractError("No suitable blob could be found.")
def get_centered_blob(img, border_size=1): img = to_binary_otsu(img) blob = _get_most_centered_blob(img) if blob is None: blob = _get_most_centered_blob(to_binary_otsu(binary_dilation(img))) if blob is None: return None blob_img = add_border(blob, (28, 28), border_size=border_size) blob_img = to_binary_otsu(blob_img) return blob_img
def iter_blob_extremes(image, n=5): original_shape = image.shape[::-1] if max(original_shape) < 2000: size = (500, 500) y_scale = original_shape[0] / 500 x_scale = original_shape[1] / 500 else: size = (1000, 1000) y_scale = original_shape[0] / 1000 x_scale = original_shape[1] / 1000 img = resize(image, size) bimg = gaussian_filter(img, sigma=1.0) bimg = threshold_adaptive(bimg, 20, offset=2/255) bimg = -bimg bimg = ndi.binary_fill_holes(bimg) label_image = label(bimg, background=False) label_image += 1 regions = regionprops(label_image) regions.sort(key=attrgetter('area'), reverse=True) iter_n = 0 for region in regions: try: iter_n += 1 if iter_n > n: break # Skip small images if region.area < int(np.prod(size) * 0.05): continue coords = get_contours(add_border(label_image == region.label, size=label_image.shape, border_size=1, background_value=False))[0] coords = np.fliplr(coords) top_left = sorted(coords, key=lambda x: np.linalg.norm(np.array(x)))[0] top_right = sorted(coords, key=lambda x: np.linalg.norm(np.array(x) - [img.shape[1], 0]))[0] bottom_left = sorted(coords, key=lambda x: np.linalg.norm(np.array(x) - [0, img.shape[0]]))[0] bottom_right = sorted(coords, key=lambda x: np.linalg.norm(np.array(x) - [img.shape[1], img.shape[0]]))[0] scaled_extremes = [(int(x[0] * y_scale), int(x[1]*x_scale)) for x in (top_left, top_right, bottom_left, bottom_right)] yield scaled_extremes except Exception: pass raise SudokuExtractError("No suitable blob could be found.")
def iter_blob_contours(image, n=5): original_shape = image.shape[::-1] if max(original_shape) < 2000: size = (500, 500) y_scale = original_shape[0] / 500 x_scale = original_shape[1] / 500 else: size = (1000, 1000) y_scale = original_shape[0] / 1000 x_scale = original_shape[1] / 1000 img = resize(image, size) bimg = gaussian_filter(img, sigma=1.0) bimg = threshold_adaptive(bimg, 20, offset=2 / 255) bimg = (~binary_erosion(bimg)) label_image = label(bimg, background=False) label_image += 1 regions = regionprops(label_image) regions.sort(key=attrgetter('area'), reverse=True) iter_n = 0 for region in regions: iter_n += 1 if iter_n > n: break try: coords = get_contours( add_border(label_image == region.label, size=label_image.shape, border_size=1, background_value=False))[0] if np.linalg.norm(coords[0, :] - coords[-1, :]) > 1e-10: raise SudokuExtractError("Not a closed contour.") else: coords = np.fliplr(coords[:-1, :]) top_left = sorted(coords, key=lambda x: np.linalg.norm(np.array(x)))[0] top_right = sorted(coords, key=lambda x: np.linalg.norm( np.array(x) - [img.shape[1], 0]))[0] bottom_left = sorted(coords, key=lambda x: np.linalg.norm( np.array(x) - [0, img.shape[0]]))[0] bottom_right = sorted( coords, key=lambda x: np.linalg.norm( np.array(x) - [img.shape[1], img.shape[0]]))[0] tl_i = np.argmax((coords == top_left).sum(axis=1)) tr_i = np.argmax((coords == top_right).sum(axis=1)) bl_i = np.argmax((coords == bottom_left).sum(axis=1)) br_i = np.argmax((coords == bottom_right).sum(axis=1)) coords[:, 0] *= y_scale coords[:, 1] *= x_scale if tl_i > bl_i: left_edge = coords[bl_i:tl_i + 1, :] else: coords_end_of_array = coords[bl_i:, :] coords_start_of_array = coords[:tl_i + 1] left_edge = np.concatenate( [coords_end_of_array, coords_start_of_array], axis=0) if tr_i > tl_i: top_edge = coords[tl_i:tr_i + 1, :] else: coords_end_of_array = coords[tl_i:, :] coords_start_of_array = coords[:tr_i + 1] top_edge = np.concatenate( [coords_end_of_array, coords_start_of_array], axis=0) if br_i > tr_i: right_edge = coords[tr_i:br_i + 1, :] else: coords_end_of_array = coords[tr_i:, :] coords_start_of_array = coords[:br_i + 1] right_edge = np.concatenate( [coords_end_of_array, coords_start_of_array], axis=0) if bl_i > br_i: bottom_edge = coords[br_i:bl_i + 1, :] else: coords_end_of_array = coords[br_i:, :] coords_start_of_array = coords[:bl_i + 1] bottom_edge = np.concatenate( [coords_end_of_array, coords_start_of_array], axis=0) yield left_edge, top_edge, right_edge, bottom_edge except Exception: pass raise SudokuExtractError("No suitable blob could be found.")
def iter_blob_contours(image, n=5): original_shape = image.shape[::-1] if max(original_shape) < 2000: size = (500, 500) y_scale = original_shape[0] / 500 x_scale = original_shape[1] / 500 else: size = (1000, 1000) y_scale = original_shape[0] / 1000 x_scale = original_shape[1] / 1000 img = resize(image, size) bimg = gaussian_filter(img, sigma=1.0) bimg = threshold_adaptive(bimg, 20, offset=2/255) bimg = (-binary_erosion(bimg)) label_image = label(bimg, background=False) label_image += 1 regions = regionprops(label_image) regions.sort(key=attrgetter('area'), reverse=True) iter_n = 0 for region in regions: iter_n += 1 if iter_n > n: break try: coords = get_contours(add_border(label_image == region.label, size=label_image.shape, border_size=1, background_value=False))[0] if np.linalg.norm(coords[0, :] - coords[-1, :]) > 1e-10: raise SudokuExtractError("Not a closed contour.") else: coords = np.fliplr(coords[:-1, :]) top_left = sorted(coords, key=lambda x: np.linalg.norm(np.array(x)))[0] top_right = sorted(coords, key=lambda x: np.linalg.norm(np.array(x) - [img.shape[1], 0]))[0] bottom_left = sorted(coords, key=lambda x: np.linalg.norm(np.array(x) - [0, img.shape[0]]))[0] bottom_right = sorted(coords, key=lambda x: np.linalg.norm(np.array(x) - [img.shape[1], img.shape[0]]))[0] tl_i = np.argmax((coords == top_left).sum(axis=1)) tr_i = np.argmax((coords == top_right).sum(axis=1)) bl_i = np.argmax((coords == bottom_left).sum(axis=1)) br_i = np.argmax((coords == bottom_right).sum(axis=1)) coords[:, 0] *= y_scale coords[:, 1] *= x_scale if tl_i > bl_i: left_edge = coords[bl_i:tl_i + 1, :] else: coords_end_of_array = coords[bl_i:, :] coords_start_of_array = coords[:tl_i + 1] left_edge = np.concatenate([coords_end_of_array, coords_start_of_array], axis=0) if tr_i > tl_i: top_edge = coords[tl_i:tr_i + 1, :] else: coords_end_of_array = coords[tl_i:, :] coords_start_of_array = coords[:tr_i + 1] top_edge = np.concatenate([coords_end_of_array, coords_start_of_array], axis=0) if br_i > tr_i: right_edge = coords[tr_i:br_i + 1, :] else: coords_end_of_array = coords[tr_i:, :] coords_start_of_array = coords[:br_i + 1] right_edge = np.concatenate([coords_end_of_array, coords_start_of_array], axis=0) if bl_i > br_i: bottom_edge = coords[br_i:bl_i + 1, :] else: coords_end_of_array = coords[br_i:, :] coords_start_of_array = coords[:bl_i + 1] bottom_edge = np.concatenate([coords_end_of_array, coords_start_of_array], axis=0) yield left_edge, top_edge, right_edge, bottom_edge except Exception: pass raise SudokuExtractError("No suitable blob could be found.")