#!/usr/bin/env python # coding: utf-8 # In[1]: from skimage.color import rgb2gray import matplotlib.pyplot as plt from skimage.io import imread from skimage.filters import threshold_sauvola import numpy as np from skimage.exposure import is_low_contrast from skimage.exposure import adjust_gamma from skimage import exposure from skimage.color import rgb2hsv cimage = imread('/home/wolf/Documents/datasets/text/Images/Train/img406.jpg') img = rgb2gray(cimage) plt.figure(figsize=(20,20)) plt.imshow(img, cmap="gray") # In[2]: plt.figure(figsize=(20,20)) plt.imshow(img<0.9, cmap="gray") # In[3]: # binarize from skimage.morphology import binary_closing from skimage.filters import threshold_otsu, threshold_sauvola window_size = 5 thresh_sauvola = threshold_sauvola(img, window_size) binary_sauvola = img < thresh_sauvola plt.figure(figsize=(20,20)) plt.imshow(binary_sauvola, cmap="gray") # In[4]: from skimage.measure import label, regionprops import matplotlib.patches as mpatches label_image = label(binary_sauvola) fig, ax = plt.subplots(figsize=(20,20)) ax.imshow(binary_sauvola) for region in regionprops(label_image): # draw rectangle around segmented coins minr, minc, maxr, maxc = region.bbox rect = mpatches.Rectangle((minc, minr), maxc - minc, maxr - minr, fill=False, edgecolor='red', linewidth=2) ax.add_patch(rect) ax.set_axis_off() plt.tight_layout() plt.show() # In[5]: def is_a_child(root_region, child_region): rminr, rminc, rmaxr, rmaxc = root_region.bbox minr, minc, maxr, maxc = child_region.bbox if minr > rminr and minc > rminc and maxr < rmaxr and maxc < rmaxc: return True return False # In[6]: from scipy.ndimage.morphology import distance_transform_edt region_props = regionprops(label_image) fig, ax = plt.subplots(figsize=(20, 16)) bounding_boxes = [] img_height, img_weight = binary_sauvola.shape for index, region in enumerate(region_props): minr, minc, maxr, maxc = region.bbox height = maxr - minr width = maxc - minc aspect_ratio = width/height should_clean = region.area < 15 * (img_height * img_weight / (600**2)) should_clean = should_clean or (region.area > (img_height*img_weight/5)) should_clean = should_clean or aspect_ratio < 0.06 or aspect_ratio > 3 should_clean = should_clean or region.eccentricity > 0.995 should_clean = should_clean or region.solidity < 0.3 should_clean = should_clean or region.extent < 0.2 or region.extent > 0.9 # should_clean = should_clean or region.euler_number < -4 strokeWidthValues = distance_transform_edt(region.image) strokeWidthMetric = np.std(strokeWidthValues)/np.mean(strokeWidthValues) should_clean = should_clean or strokeWidthMetric < 0.4 # if should_clean: # for coord in region.coords: # cleaned_img[coord[0],coord[1]] = False if not should_clean: expansionAmountY = 0.02 expansionAmountX = 0.03 minr, minc, maxr, maxc = region.bbox minr = np.floor((1-expansionAmountY) * minr) minc = np.floor((1-expansionAmountX) * minc) maxr = np.ceil((1+expansionAmountY) * maxr) maxc = np.ceil((1+expansionAmountX) * maxc) bounding_boxes.append([minr, minc, maxr, maxc]) rect = mpatches.Rectangle((minc, minr), maxc - minc, maxr - minr, fill=False, edgecolor='red', linewidth=2) ax.add_patch(rect) #remove ccs which have more than 3 components within them # label_heirarchy = {} # for iindex, iregion in enumerate(region_props[0:-1]): # count = 0 # for jindex, jregion in enumerate(region_props[1:]): # if is_a_child(iregion, jregion): # count += 1 # if count < 3: # minr, minc, maxr, maxc = iregion.bbox # bounding_boxes.append([minr, minc, maxr, maxc]) ax.set_axis_off() print(len(bounding_boxes)) ax.imshow(binary_sauvola) plt.show() # In[7]: # https://stackoverflow.com/questions/306316/determine-if-two-rectangles-overlap-each-other import pandas as pd import time # minr, minc, maxr, maxc def is_overlapping(box1, box2): # if (RectA.minc < RectB.maxc && RectA.maxc > RectB.minc && # RectA.minr > RectB.maxr && RectA.maxr < RectB.minr ) if box1[1] < box2[3] and box1[3] > box2[1] and box1[0] < box2[2] and box1[2] > box2[0]: return True return False def is_almost_in_line(box1, box2): centroid_b1 = [int((box1[0]+box1[2])/2), int((box1[1]+box1[3])/2)] centroid_b2 = [int((box2[0]+box2[2])/2), int((box2[1]+box2[3])/2)] if (centroid_b2[0]-centroid_b1[0]) == 0: return True angle = (np.arctan(np.abs((centroid_b2[1]-centroid_b1[1])/(centroid_b2[0]-centroid_b1[0])) )*180)/np.pi if angle > 80: return True return False #print(is_overlapping([1,1,3,3],[2,2,4,4])) def combine_boxes(box1, box2): minr = np.min([box1[0],box2[0]]) minc = np.min([box1[1],box2[1]]) maxr = np.max([box1[2],box2[2]]) maxc = np.max([box1[3],box2[3]]) return [minr, minc, maxr, maxc] def group_the_bounding_boxes(bounding_boxes): stime = time.time() number_of_checks = 0 box_groups = [] dont_check_anymore = [] for iindex, box1 in enumerate(bounding_boxes): if iindex in dont_check_anymore: continue group_size = 0 bigger_box = box1 for jindex, box2 in enumerate(bounding_boxes): if jindex in dont_check_anymore: continue if jindex == iindex: continue number_of_checks+=1 if is_overlapping(bigger_box, box2) and is_almost_in_line(bigger_box, box2): bigger_box = combine_boxes(bigger_box, box2) dont_check_anymore.append(jindex) group_size += 1 if group_size > 0: # check if this group overlaps any other # and combine it there otherwise make a new box. combined_with_existing_box = False for kindex, box3 in enumerate(box_groups): if is_overlapping(bigger_box, box3): bigger_box = combine_boxes(bigger_box, box3) box_groups[kindex] = bigger_box combined_with_existing_box = True break if not combined_with_existing_box: box_groups.append(bigger_box) else: dont_check_anymore.append(iindex) print("number_of_checks:", number_of_checks) print("time_taken:", str(time.time() - stime)) return box_groups box_groups = group_the_bounding_boxes(bounding_boxes) fig, ax = plt.subplots(figsize=(20, 16)) # minr, minc, maxr, maxc for box in box_groups: minr = box[0] minc = box[1] maxr = box[2] maxc = box[3] rect = mpatches.Rectangle((minc, minr), maxc - minc, maxr - minr, fill=False, edgecolor='red', linewidth=2) ax.add_patch(rect) ax.axis("off") ax.imshow(cimage) plt.show() #4914 # In[ ]: