Commit 49ade68f authored by Tilmann Sager's avatar Tilmann Sager
Browse files

Added line type detection

parent 46e4215c
......@@ -25,12 +25,13 @@ sigma = 0.35
method = straight
min_px_size = 150
connectivity = 2
split_by = 3
threshold = 90
postprocess = 1
split_by = 6
threshold = 70
postprocess = 0
ratio_threshold = 5
[straight]
threshold = 0.9
threshold = 0.5
[probabilistic]
line_length = 150
......
......@@ -32,7 +32,7 @@ def init():
return {
# General
'multiprocessing': bool(cp.get(_general_key, 'multiprocessing')),
'multiprocessing': bool(int(cp.get(_general_key, 'multiprocessing'))),
# Path
'hdf_dir': fileio.check_path([cp.get(_path_key, 'hdf'), cp.get(_product_key, 'name')], create=False),
......@@ -60,7 +60,8 @@ def init():
'connectivity': int(cp.get(_detect_key, 'connectivity')),
'split_by': int(cp.get(_detect_key, 'split_by')),
'threshold': int(cp.get(_detect_key, 'threshold')),
'postprocess': bool(cp.get(_detect_key, 'postprocess')),
'postprocess': bool(int(cp.get(_detect_key, 'postprocess'))),
'ratio_threshold': int(cp.get(_detect_key, 'ratio_threshold')),
# Detection - Probabilistic
'prob_line_length': int(cp.get(_probabilistic_key, 'line_length')),
......
......@@ -2,11 +2,40 @@ import numpy as np
from skimage.draw import line_aa, line
from skimage.feature import canny
from skimage.filters import scharr
from skimage.morphology import binary_closing, remove_small_objects, binary_dilation, label, closing, square
from skimage.measure import label, regionprops_table
from skimage.morphology import binary_closing, remove_small_objects, binary_dilation, closing, square
from skimage.transform import probabilistic_hough_line, hough_line, hough_line_peaks
from constants import Columns as col
"""
PROPERTIES
"""
def _dimension_label_ratio(segment: np.array):
props = regionprops_table(segment, properties=('major_axis_length', 'minor_axis_length'))
if props['major_axis_length'].size > 0 and props['minor_axis_length'].size > 0:
ratio = props['major_axis_length'][0] / props['minor_axis_length'][0]
else:
ratio = 0
return ratio
def _filter_segments_by_ratio(labeled, intersections, ratio_threshold):
line_type_segments = []
for i_label in intersections:
mask = labeled == i_label
mask = mask.astype(np.uint8) # np.array(mask, dtype=np.uint8)
ratio = _dimension_label_ratio(mask)
if ratio and ratio >= ratio_threshold:
line_type_segments.append(i_label)
return list(set(line_type_segments))
"""
BLOCKS
"""
......@@ -44,7 +73,9 @@ def _binary_closing(arr):
return binary_closing(arr)
def _remove_small_objects(arr, max_size):
def _remove_small_objects(arr, max_size, is_bool=False):
if is_bool:
arr = arr.astype(bool)
return remove_small_objects(arr, max_size)
......@@ -77,10 +108,13 @@ def _filter_labels(img, label_list):
def _correct_value(val, shape):
if val in [float("-inf"), float("inf"), float("nan")]:
return float("nan")
if type(val) in [float("-inf"), float("inf"), float("nan"), float("NaN")] or not val:
return None
val = round(val)
try:
val = round(val)
except (ValueError, OverflowError):
return None
if val >= shape:
val = shape - 1
......@@ -95,11 +129,9 @@ def _label(img):
# TODO: refactor
def _line_segment_intersect(labeled, h, theta, d, threshold, shape):
intersection_labels = []
hough_threshold = threshold * h.max()
intersections = []
for _, angle, dist in zip(*hough_line_peaks(h, theta, d, threshold=hough_threshold)):
for _, angle, dist in zip(*hough_line_peaks(h, theta, d, threshold=threshold * h.max())):
if angle == 0.0:
continue
......@@ -109,7 +141,7 @@ def _line_segment_intersect(labeled, h, theta, d, threshold, shape):
x0 = 0
x1 = _correct_value(shape[1], shape[1])
if y0 == float("nan") or y1 == float("nan"):
if y0 is None or y1 is None or x0 is None or x1 is None:
continue
line_arr = np.zeros(labeled.shape, dtype=int)
......@@ -123,9 +155,9 @@ def _line_segment_intersect(labeled, h, theta, d, threshold, shape):
masked = line_arr * mask
if masked.any():
intersection_labels.append(label_num)
intersections.append(label_num)
return intersection_labels
return list(set(intersections))
"""
......@@ -179,13 +211,13 @@ def _line_segment_intersect_prob(labeled: np.array, lines: []) -> [int]:
# TODO: add thresholding again
def _probabilistic(img, sigma: int, line_length: int, line_gap: int, edge_filter: str):
if edge_filter == 'scharr':
def _probabilistic(img, params):
if params.get('prob_filter') == 'scharr':
edges = _scharr(img)
else:
edges = _canny(img, sigma)
edges = _canny(img, params.get('prob_sigma'))
lines = probabilistic_hough_line(edges, line_length, line_gap)
lines = probabilistic_hough_line(edges, params.get('prob_line_length'), params.get('prob_line_gap'))
labeled = _label(img)
intersections = _line_segment_intersect_prob(labeled, lines)
......@@ -206,11 +238,16 @@ def _hough_line(img: np.array):
return hough_line(img, theta=tested_angles)
def _straight(img: np.array, threshold: float) -> np.array:
def _straight(img: np.array, params: {}) -> np.array:
h, theta, d = _hough_line(img)
labeled = _label(img)
intersections = _line_segment_intersect(labeled, h, theta, d, threshold, img.shape)
mask = _filter_labels(labeled, intersections)
intersections = _line_segment_intersect(labeled, h, theta, d, params.get('straight_threshold'), img.shape)
line_type_labels = _filter_segments_by_ratio(labeled, intersections, params.get('ratio_threshold'))
mask = _filter_labels(labeled, line_type_labels)
mask = _binary_closing(mask)
mask = _remove_small_objects(mask, params.get('max_px_size'), True)
return mask
......@@ -237,17 +274,15 @@ def run(granule: {}, params: {}):
# Detection
if params.get('method') == 'probabilistic':
masks = [_probabilistic(block, sigma=params.get('prob_sigma'), line_length=params.get('prob_line_length'),
line_gap=params.get('prob_line_gap'), edge_filter=params.get('prob_filter')) for block
masks = [_probabilistic(block, params) for block
in blocks]
else:
masks = [_straight(block, threshold=params.get('straight_threshold')) for block in blocks]
masks = [_straight(block, params) for block in blocks]
mask = _combine_blocks(masks, split_by)
if params.get('postprocess'):
mask = _probabilistic(mask, sigma=params.get('prob_sigma'), line_length=params.get('prob_line_length'),
line_gap=params.get('prob_line_gap'), edge_filter=params.get('prob_filter'))
mask = _probabilistic(mask, params)
granule[col.contrail_mask] = mask
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment