File size: 2,340 Bytes
64ea7b2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import numpy as np
import cv2
import skimage.morphology
import skimage.filters.rank


# Aux functions (originally from suzie.images)

def local_entropy(im, kernel_size=5, normalize=True):
    kernel = skimage.morphology.disk(kernel_size)
    if len(im.shape)>2:
        kkernel = np.zeros((kernel.shape[0], kernel.shape[1],im.shape[2]))
        for i in range(im.shape[2]):
            kkernel[:,:,i]=kernel
        kernel = kkernel
    entr_img = skimage.filters.rank.entropy(im, kernel)
    if normalize:
        max_img = np.max(entr_img)
        entr_img = (entr_img * 255 / max_img).astype(np.uint8)
    return entr_img


def calc_dim(contour):
    c_0 = [point[0][0] for point in contour]
    c_1 = [point[0][1] for point in contour]
    return (min(c_0), max(c_0), min(c_1), max(c_1))


def calc_size(dim):
    return (dim[1] - dim[0]) * (dim[3] - dim[2])


def calc_dist(dim1, dim2):
    return None


# -- Main function

def extract_mask(img, filled=True, threshold=135, kernel_size=5):
    entr_img = local_entropy(img, kernel_size=kernel_size)
    _, mask = cv2.threshold(entr_img, threshold, 255, cv2.THRESH_BINARY)
    while(len(np.unique(mask))==1):
        threshold -= 5
        print("Reducing threshold to ",threshold)
        _, mask = cv2.threshold(entr_img, threshold, 255, cv2.THRESH_BINARY)
    contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

    contours_d = [calc_dim(c) for c in contours]
    contours_sizes = [calc_size(c) for c in contours_d]
    contour_indices = np.argsort(contours_sizes)[::-1]

    # remove artifacts
    fratio = 0
    sratio = 5
    idx = -1
    while fratio < 0.3 or sratio > 5:
        idx += 1
        biggest = contour_indices[idx]
        filled_mask = np.zeros(img.shape, dtype=np.uint8)
        filled_mask = cv2.fillPoly(filled_mask, [contours[biggest]], 255)
        fratio = filled_mask.sum() / 255 / contours_sizes[biggest]
        cdim = contours_d[biggest]
        sratio = (cdim[3] - cdim[2]) / (cdim[1] - cdim[0])
        if sratio < 1: sratio = 1 / sratio
  
    # generating the mask
    filled_mask = np.zeros(img.shape, dtype=np.uint8)
    if filled:
        filled_mask = cv2.fillPoly(filled_mask, [contours[biggest]], 255)
    else:
        filled_mask = cv2.polylines(filled_mask, [contours[biggest]], 30, 255)

    return filled_mask