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()
|