File size: 3,051 Bytes
abd2a81
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import matplotlib.pyplot as plt

import numpy as np
import shapely.geometry
import shapely.affinity
import skimage.io
import skimage.measure
from matplotlib.ticker import StrMethodFormatter


def compute_polygon_angles(polygon):
    # --- Rotate polygon so that main axis is aligned with the x-axis
    min_rot_rect = polygon.minimum_rotated_rectangle
    min_rot_rect_contour = np.array(min_rot_rect.exterior.coords[:])
    min_rot_rect_edges = min_rot_rect_contour[1:] - min_rot_rect_contour[:-1]
    min_rot_rect_norms = np.linalg.norm(min_rot_rect_edges, axis=1)
    max_norms_index = np.argmax(min_rot_rect_norms)
    longest_edge = min_rot_rect_edges[max_norms_index]
    main_angle = np.angle(longest_edge[0] + 1j*longest_edge[1])
    polygon = shapely.affinity.rotate(polygon, -main_angle, use_radians=True)
    
    contour = np.array(polygon.exterior)
    edges = contour[1:] - contour[:-1]
    edges = edges[:, 1] + 1j * edges[:, 0]
    angles = np.angle(edges)
    angles[angles < 0] += np.pi  # Don't care about direction of edge

    return angles


def get_angles(mask_filepath, level=0.5, tol=0.1):
    # Read images
    mask = skimage.io.imread(mask_filepath) / 255

    # Compute contours
    contours = skimage.measure.find_contours(mask, level, fully_connected='low', positive_orientation='high')
    polygons = [shapely.geometry.Polygon(contour[:, ::-1]) for contour in contours]
    # Filter out really small polylines
    polygons = [polygon for polygon in polygons if 2 < polygon.area]
    # Simplify
    polygons = [polygon.simplify(tol, preserve_topology=True) for polygon in polygons]

    # Compute angles
    contours_angles = [compute_polygon_angles(polygon) for polygon in polygons]

    angles = np.concatenate(contours_angles)
    relative_degrees = angles * 180 / np.pi
    return relative_degrees


def plot_contour_angle_hist(list_info, level=0.5, tol=0.1):
    start = 0
    stop = 180
    bin_count = 100
    bin_edges = np.linspace(start, stop, bin_count + 1)
    bin_width = (stop - start) / bin_count
    for i, info in enumerate(list_info):
        degrees = get_angles(info["mask_filepath"], level, tol)
        hist, bin_edges = np.histogram(degrees, bins=bin_edges)
        freq = hist / np.sum(hist)
        plt.bar(bin_edges[1:] - bin_width/2, freq, width=bin_width, alpha=0.5, label=info["name"])

    plt.title("Histogram of relative contour angles")
    plt.xlabel("Relative angle")
    plt.ylabel("Freq")
    plt.gca().xaxis.set_major_formatter(StrMethodFormatter(u"{x:.0f}°"))
    plt.legend(loc="upper left")
    plt.xlim(0, 180)
    plt.savefig("histogram_of_relative_contour_angles.pdf", transparent=True)
    plt.show()


def main():

    list_info = [
        {
            "name": "ICTNet",
            "mask_filepath": "inria_dataset_test_sample_result.ictlab.jpg"
        },
        {
            "name": "Ours",
            "mask_filepath": "inria_dataset_test_sample_result.ours.tif"
        },
    ]

    plot_contour_angle_hist(list_info, tol=1)


if __name__ == '__main__':
    main()