2022-08-16 20:50:00 +00:00
|
|
|
import os
|
2020-10-17 22:02:05 +00:00
|
|
|
from multiprocessing.pool import ThreadPool
|
2022-08-16 20:50:00 +00:00
|
|
|
|
2020-10-19 19:35:15 +00:00
|
|
|
import numpy as np
|
2022-08-16 20:50:00 +00:00
|
|
|
|
|
|
|
|
from Application.Config import Config
|
|
|
|
|
from Application.Exporter import Exporter
|
|
|
|
|
from Application.Layer import Layer
|
|
|
|
|
from Application.VideoReader import VideoReader
|
2020-12-18 20:27:19 +00:00
|
|
|
|
2022-01-09 19:25:44 +00:00
|
|
|
|
2020-09-20 20:01:54 +00:00
|
|
|
class LayerFactory:
|
2020-10-11 15:09:49 +00:00
|
|
|
def __init__(self, config, data=None):
|
|
|
|
|
self.data = {}
|
|
|
|
|
self.layers = []
|
|
|
|
|
self.tolerance = config["tolerance"]
|
|
|
|
|
self.ttolerance = config["ttolerance"]
|
2022-09-11 09:25:36 +00:00
|
|
|
self.min_layer_length = config["minLayerLength"]
|
|
|
|
|
self.max_layer_length = config["maxLayerLength"]
|
|
|
|
|
self.resize_width = config["resizeWidth"]
|
|
|
|
|
self.footage_path = config["inputPath"]
|
2020-10-18 15:36:34 +00:00
|
|
|
self.config = config
|
2020-09-24 20:48:04 +00:00
|
|
|
print("LayerFactory constructed")
|
|
|
|
|
self.data = data
|
|
|
|
|
if data is not None:
|
2022-09-11 09:25:36 +00:00
|
|
|
self.extract_layers(data)
|
2020-09-24 20:48:04 +00:00
|
|
|
|
2022-09-11 09:25:36 +00:00
|
|
|
def extract_layers(self, data, mask_arr):
|
2022-01-09 19:25:44 +00:00
|
|
|
"""Bundle given contours together into Layer Objects"""
|
2020-09-24 20:48:04 +00:00
|
|
|
|
2022-09-11 09:25:36 +00:00
|
|
|
frame_number = min(data)
|
|
|
|
|
contours = data[frame_number]
|
|
|
|
|
masks = mask_arr[frame_number]
|
2020-11-27 00:06:25 +00:00
|
|
|
|
|
|
|
|
for contour, mask in zip(contours, masks):
|
|
|
|
|
mask = np.unpackbits(mask, axis=0)
|
2022-09-11 09:25:36 +00:00
|
|
|
self.layers.append(Layer(frame_number, contour, mask, self.config))
|
2020-12-18 20:27:19 +00:00
|
|
|
|
2022-09-11 09:25:36 +00:00
|
|
|
self.old_layer_i_ds = []
|
2020-12-18 20:27:19 +00:00
|
|
|
|
2021-02-05 19:04:10 +00:00
|
|
|
with ThreadPool(os.cpu_count()) as pool:
|
2022-09-11 09:25:36 +00:00
|
|
|
for frame_number in sorted(data.keys()):
|
|
|
|
|
contours = data[frame_number]
|
|
|
|
|
masks = mask_arr[frame_number]
|
2022-01-09 19:25:44 +00:00
|
|
|
masks = [np.unpackbits(mask, axis=0) for mask, contours in zip(masks, contours)]
|
2022-09-11 09:25:36 +00:00
|
|
|
if frame_number % 100 == 0:
|
2020-12-18 20:27:19 +00:00
|
|
|
print(
|
2022-09-11 09:25:36 +00:00
|
|
|
f" {int(round(frame_number/max(data.keys()), 2)*100)}% done with Layer extraction {len(self.layers)} Layers",
|
2022-01-09 19:25:44 +00:00
|
|
|
end="\r",
|
|
|
|
|
)
|
2020-12-18 20:27:19 +00:00
|
|
|
|
2022-09-11 09:25:36 +00:00
|
|
|
tmp = [[frame_number, contour, mask] for contour, mask in zip(contours, masks)]
|
2022-01-09 19:25:44 +00:00
|
|
|
# pool.map(self.getLayers, tmp)
|
2020-11-08 15:28:47 +00:00
|
|
|
for x in tmp:
|
2022-09-11 09:25:36 +00:00
|
|
|
self.get_layers(x)
|
2020-10-18 17:24:55 +00:00
|
|
|
|
2020-12-26 13:58:58 +00:00
|
|
|
# self.joinLayers()
|
2020-10-13 22:16:39 +00:00
|
|
|
return self.layers
|
2020-09-24 20:48:04 +00:00
|
|
|
|
2022-09-11 09:25:36 +00:00
|
|
|
def get_layers(self, data):
|
|
|
|
|
frame_number = data[0]
|
2020-10-17 22:02:05 +00:00
|
|
|
bounds = data[1]
|
2020-11-27 00:06:25 +00:00
|
|
|
mask = data[2]
|
2020-12-18 20:27:19 +00:00
|
|
|
(x, y, w, h) = bounds
|
2020-10-17 22:02:05 +00:00
|
|
|
tol = self.tolerance
|
2020-12-18 20:27:19 +00:00
|
|
|
|
2022-09-11 09:25:36 +00:00
|
|
|
found_layer_i_ds = set()
|
2020-12-18 20:27:19 +00:00
|
|
|
for i, layer in enumerate(self.layers):
|
2022-09-11 09:25:36 +00:00
|
|
|
if frame_number - layer.last_frame > self.ttolerance:
|
2020-10-17 22:02:05 +00:00
|
|
|
continue
|
|
|
|
|
|
2022-09-11 09:25:36 +00:00
|
|
|
last_xframes = min(40, len(layer))
|
|
|
|
|
last_bounds = [bound for bounds in layer.bounds[-last_xframes:] for bound in bounds]
|
2020-12-18 20:27:19 +00:00
|
|
|
|
2022-09-11 09:25:36 +00:00
|
|
|
for j, bounds in enumerate(sorted(last_bounds, reverse=True)):
|
2020-11-08 15:28:47 +00:00
|
|
|
if bounds is None:
|
2020-10-17 22:02:05 +00:00
|
|
|
break
|
2020-12-18 20:27:19 +00:00
|
|
|
(x2, y2, w2, h2) = bounds
|
2022-09-11 09:25:36 +00:00
|
|
|
if self.contours_overlay((x - tol, y + h + tol), (x + w + tol, y - tol), (x2, y2 + h2), (x2 + w2, y2)):
|
|
|
|
|
layer.add(frame_number, (x, y, w, h), mask)
|
|
|
|
|
found_layer_i_ds.add(i)
|
2020-11-08 15:28:47 +00:00
|
|
|
break
|
2020-10-17 22:02:05 +00:00
|
|
|
|
2022-09-11 09:25:36 +00:00
|
|
|
found_layer_i_ds = sorted(list(found_layer_i_ds))
|
|
|
|
|
if len(found_layer_i_ds) == 0:
|
|
|
|
|
self.layers.append(Layer(frame_number, (x, y, w, h), mask, self.config))
|
|
|
|
|
if len(found_layer_i_ds) > 1:
|
|
|
|
|
self.merge_layers(found_layer_i_ds)
|
2020-11-12 17:59:57 +00:00
|
|
|
|
2022-09-11 09:25:36 +00:00
|
|
|
def merge_layers(self, found_layer_i_ds):
|
|
|
|
|
layers = self.get_layers_by_id(found_layer_i_ds)
|
|
|
|
|
merged_layers = layers[0]
|
2020-12-18 20:27:19 +00:00
|
|
|
for layer in layers[1:]:
|
|
|
|
|
for i, (contours, masks) in enumerate(zip(layer.bounds, layer.masks)):
|
|
|
|
|
for contour, mask in zip(contours, masks):
|
2022-09-11 09:25:36 +00:00
|
|
|
merged_layers.add(layer.startFrame + i, contour, mask)
|
2020-11-12 17:59:57 +00:00
|
|
|
|
2022-09-11 09:25:36 +00:00
|
|
|
for i, id in enumerate(found_layer_i_ds):
|
2020-12-18 20:27:19 +00:00
|
|
|
del self.layers[id - i]
|
|
|
|
|
|
2022-09-11 09:25:36 +00:00
|
|
|
self.layers.append(merged_layers)
|
2020-12-18 20:27:19 +00:00
|
|
|
|
2022-09-11 09:25:36 +00:00
|
|
|
def join_layers(self):
|
2020-12-18 20:27:19 +00:00
|
|
|
self.layers.sort(key=lambda c: c.startFrame)
|
2022-09-11 09:25:36 +00:00
|
|
|
min_frame = self.get_min_start(self.layers)
|
|
|
|
|
max_frame = self.get_max_end(self.layers)
|
2020-12-18 20:27:19 +00:00
|
|
|
|
2022-09-11 09:25:36 +00:00
|
|
|
for i in range(min_frame, max_frame):
|
|
|
|
|
p_l, indexes = self.get_possible_layers(i)
|
|
|
|
|
if len(p_l) <= 1:
|
2020-12-18 20:27:19 +00:00
|
|
|
continue
|
|
|
|
|
merge = set()
|
2022-09-11 09:25:36 +00:00
|
|
|
inner_max = self.get_max_end(p_l)
|
|
|
|
|
for x in range(self.get_min_start(p_l), inner_max):
|
|
|
|
|
for lc, l in enumerate(p_l):
|
2020-12-18 20:27:19 +00:00
|
|
|
if l.startFrame < x or l.lastFrame > x:
|
|
|
|
|
continue
|
2022-09-11 09:25:36 +00:00
|
|
|
for lc2, l2 in enumerate(p_l):
|
2020-12-18 20:27:19 +00:00
|
|
|
if lc2 == lc:
|
|
|
|
|
continue
|
2022-01-09 19:25:44 +00:00
|
|
|
for cnt in l.bounds[x - l.startFrame]:
|
|
|
|
|
for cnt2 in l2.bounds[x - l2.startFrame]:
|
2022-09-11 09:25:36 +00:00
|
|
|
if self.contours_overlay(cnt, cnt2):
|
2020-12-18 20:27:19 +00:00
|
|
|
merge.add(indexes[lc])
|
|
|
|
|
merge.add(indexes[lc2])
|
|
|
|
|
merge = list(merge)
|
|
|
|
|
if len(merge) > 1:
|
2022-09-11 09:25:36 +00:00
|
|
|
self.merge_layers(merge)
|
|
|
|
|
i = inner_max
|
2020-12-18 20:27:19 +00:00
|
|
|
|
2022-09-11 09:25:36 +00:00
|
|
|
def get_possible_layers(self, t):
|
2020-12-18 20:27:19 +00:00
|
|
|
ret = []
|
|
|
|
|
ii = []
|
2020-11-12 17:59:57 +00:00
|
|
|
for i, layer in enumerate(self.layers):
|
2022-09-11 09:25:36 +00:00
|
|
|
if layer.start_frame <= t and layer.last_frame <= t:
|
2020-12-18 20:27:19 +00:00
|
|
|
ret.append(layer)
|
|
|
|
|
ii.append(i)
|
|
|
|
|
return (ret, ii)
|
|
|
|
|
|
2022-09-11 09:25:36 +00:00
|
|
|
def get_min_start(self, layers):
|
|
|
|
|
min_frame = layers[0].startFrame
|
2020-12-18 20:27:19 +00:00
|
|
|
for l in layers:
|
2022-09-11 09:25:36 +00:00
|
|
|
if l.startFrame < min_frame:
|
|
|
|
|
min_frame = l.startFrame
|
|
|
|
|
return min_frame
|
2020-12-18 20:27:19 +00:00
|
|
|
|
2022-09-11 09:25:36 +00:00
|
|
|
def get_max_end(self, layers):
|
|
|
|
|
max_frame = layers[0].lastFrame
|
2020-12-18 20:27:19 +00:00
|
|
|
for l in layers:
|
2022-09-11 09:25:36 +00:00
|
|
|
if l.lastFrame < max_frame:
|
|
|
|
|
max_frame = l.lastFrame
|
|
|
|
|
return max_frame
|
2020-12-18 20:27:19 +00:00
|
|
|
|
2022-09-11 09:25:36 +00:00
|
|
|
def contours_overlay(self, l1, r1, l2, r2):
|
2022-01-09 19:25:44 +00:00
|
|
|
if l1[0] >= r2[0] or l2[0] >= r1[0]:
|
2020-09-24 20:48:04 +00:00
|
|
|
return False
|
2022-01-09 19:25:44 +00:00
|
|
|
if l1[1] <= r2[1] or l2[1] <= r1[1]:
|
2020-09-24 20:48:04 +00:00
|
|
|
return False
|
|
|
|
|
return True
|
2020-11-12 17:59:57 +00:00
|
|
|
|
2022-09-11 09:25:36 +00:00
|
|
|
def get_layers_by_id(self, found_layer_i_ds):
|
2020-11-12 17:59:57 +00:00
|
|
|
layers = []
|
2022-09-11 09:25:36 +00:00
|
|
|
for layer_id in found_layer_i_ds:
|
|
|
|
|
layers.append(self.layers[layer_id])
|
2020-12-18 20:27:19 +00:00
|
|
|
|
|
|
|
|
layers.sort(key=lambda c: c.startFrame)
|
|
|
|
|
return layers
|