fixed layer.add()

This commit is contained in:
Askill 2020-11-08 16:28:47 +01:00
parent 01b5d7f9a9
commit 3c3c8da9cd
14 changed files with 78 additions and 81 deletions

View File

@ -3,25 +3,27 @@ class Config:
c = { c = {
"min_area" : 100, "min_area" : 100,
"max_area" : 40000, "max_area" : 40000,
"threashold" : 5, "threashold" : 8,
"resizeWidth" : 512, "resizeWidth" : 512,
"inputPath" : None, "inputPath" : None,
"outputPath": None, "outputPath": None,
"maxLayerLength": 900, "maxLayerLength": 900,
"minLayerLength": 20, "minLayerLength": 20,
"tolerance": 20, "tolerance": 10,
"maxLength": None, "maxLength": None,
"ttolerance": 60, "ttolerance": 60,
"videoBufferLength": 500, "videoBufferLength": 500,
"noiseThreashold": 0.3, "noiseThreashold": 0.25,
"noiseSensitivity": 3/4, "noiseSensitivity": 3/4,
"LayersPerContour": 5, "LayersPerContour": 2,
"averageFrames": 10 "avgNum":10
} }
def __init__(self): def __init__(self):
'''This is basically just a wrapper for a json / python dict''' '''This is basically just a wrapper for a json / python dict'''
print("Current Config:", self.c) print("Current Config:")
for key, value in self.c.items():
print(f"{key}:\t\t{value}")
def __getitem__(self, key): def __getitem__(self, key):
if key not in self.c: if key not in self.c:

View File

@ -109,7 +109,9 @@ class ContourExtractor:
def computeMovingAverage(self, frames): def computeMovingAverage(self, frames):
avg = [] avg = []
averageFrames = self.config["averageFrames"] averageFrames = self.config["avgNum"]
nth = int(averageFrames/3) # only take /x x frames to average
if frames[0][0] < averageFrames: if frames[0][0] < averageFrames:
frame = frames[0][1] frame = frames[0][1]
frame = self.prepareFrame(frame) frame = self.prepareFrame(frame)
@ -123,7 +125,7 @@ class ContourExtractor:
if self.lastFrames is not None: if self.lastFrames is not None:
frames = self.lastFrames + frames frames = self.lastFrames + frames
tmp = [[j, frames, averageFrames]for j in range(averageFrames, len(frames))] tmp = [[j, frames, averageFrames] for j in range(averageFrames, len(frames))]
with ThreadPool(16) as pool: with ThreadPool(16) as pool:
pool.map(self.averageDaFrames, tmp) pool.map(self.averageDaFrames, tmp)
@ -136,6 +138,6 @@ class ContourExtractor:
frame = self.prepareFrame(frame) frame = self.prepareFrame(frame)
avg = frame/averageFrames avg = frame/averageFrames
for jj in reversed(range(averageFrames-1)): for jj in range(0,averageFrames-1):
avg += self.prepareFrame(frames[j-jj][1])/averageFrames avg += self.prepareFrame(frames[j-jj][1])/averageFrames
self.averages[frameNumber] = np.array(np.round(avg), dtype=np.uint8) self.averages[frameNumber] = np.array(np.round(avg), dtype=np.uint8)

View File

@ -16,17 +16,13 @@ class Exporter:
self.config = config self.config = config
print("Exporter initiated") print("Exporter initiated")
def export(self, layers, raw = True, layered = False, overlayed = True): def export(self, layers, contours, raw = True, overlayed = True):
if raw: if raw:
self.exportRawData(layers) self.exportRawData(layers, contours)
if layered and overlayed: if overlayed:
print("Layered and Individual are mutually exclusive, individual was choosen automatically")
overlayed = False
if layered and not overlayed:
self.exportLayers(layers)
if overlayed and not layered:
self.exportOverlayed(layers) self.exportOverlayed(layers)
else:
self.exportLayers(layers)
def exportLayers(self, layers): def exportLayers(self, layers):
@ -37,7 +33,6 @@ class Exporter:
maxLength = self.getMaxLengthOfLayers(layers) maxLength = self.getMaxLengthOfLayers(layers)
underlay = cv2.VideoCapture(self.footagePath).read()[1] underlay = cv2.VideoCapture(self.footagePath).read()[1]
underlay = cv2.cvtColor(underlay, cv2.COLOR_BGR2RGB) underlay = cv2.cvtColor(underlay, cv2.COLOR_BGR2RGB)
frames = [underlay]*maxLength
exportFrame = 0 exportFrame = 0
self.fps = videoReader.getFPS() self.fps = videoReader.getFPS()
@ -52,7 +47,7 @@ class Exporter:
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
frame2 = np.copy(underlay) frame2 = np.copy(underlay)
for layer in layers: for xi, layer in enumerate(layers):
if layer.startFrame <= frameCount and layer.startFrame + len(layer.bounds) > frameCount: if layer.startFrame <= frameCount and layer.startFrame + len(layer.bounds) > frameCount:
for (x, y, w, h) in layer.bounds[frameCount - layer.startFrame]: for (x, y, w, h) in layer.bounds[frameCount - layer.startFrame]:
if x is None: if x is None:
@ -64,7 +59,7 @@ class Exporter:
h = int(h * factor) h = int(h * factor)
frame2[y:y+h, x:x+w] = np.copy(frame[y:y+h, x:x+w]) frame2[y:y+h, x:x+w] = np.copy(frame[y:y+h, x:x+w])
cv2.putText(frame2, str(int(frameCount/self.fps)), (int(x+w/2), int(y+h/2)), cv2.FONT_HERSHEY_SIMPLEX, 1,(255,255,255), 2) cv2.putText(frame2, str(xi) + " " + str(int(frameCount/self.fps)), (int(x+w/2), int(y+h/2)), cv2.FONT_HERSHEY_SIMPLEX, 1,(255,255,255), 2)
writer.append_data(frame2) writer.append_data(frame2)
@ -119,9 +114,10 @@ class Exporter:
writer.close() writer.close()
def exportRawData(self, layers): def exportRawData(self, layers, contours):
with open(self.outputPath.split(".")[-2] + ".txt", "wb+") as file: with open(self.config["importPath"], "wb+") as file:
pickle.dump(layers, file) pickle.dump((layers, contours), file)
def getMaxLengthOfLayers(self, layers): def getMaxLengthOfLayers(self, layers):

View File

@ -5,6 +5,7 @@ class Importer:
self.path = config["importPath"] self.path = config["importPath"]
def importRawData(self): def importRawData(self):
print("Loading previous results")
with open(self.path, "rb") as file: with open(self.path, "rb") as file:
layers = pickle.load(file) layers, contours = pickle.load(file)
return layers return (layers, contours)

View File

@ -37,40 +37,19 @@ class Layer:
def add(self, frameNumber, bound): def add(self, frameNumber, bound):
'''Adds a bound''' '''Adds a bound'''
if not self.startFrame + len(self.bounds) < frameNumber: if self.startFrame + len(self.bounds) - 1 > frameNumber:
if len(self.bounds[self.startFrame - frameNumber]) >= 1: if len(self.bounds[frameNumber - self.startFrame]) >= 1:
self.bounds[self.startFrame - frameNumber].append(bound) self.bounds[frameNumber - self.startFrame].append(bound)
else: else:
self.lastFrame = frameNumber self.lastFrame = frameNumber
self.bounds.append([bound]) self.bounds.append([bound])
self.getLength()
def getLength(self): def getLength(self):
return len(self) return len(self)
def __len__(self): def __len__(self):
self.length = len(self.bounds) self.length = len(self.bounds)
return self.length return self.length
def fill(self, inputPath, resizeWidth):
'''deprecated
Fills the data[] array by iterateing over the bounds'''
cap = cv2.VideoCapture(inputPath)
self.data = [None]*len(self.bounds)
i = 0
cap.set(1, self.startFrame)
while i < len(self.bounds):
ret, frame = cap.read()
if ret:
frame = imutils.resize(frame, width=resizeWidth)
(x, y, w, h) = self.bounds[i]
self.data[i] = frame[y:y+h, x:x+w]
i+=1
cap.release()
def clusterDelete(self): def clusterDelete(self):
'''Uses a cluster analysis to remove contours which are not the result of movement''' '''Uses a cluster analysis to remove contours which are not the result of movement'''
@ -146,13 +125,14 @@ class Layer:
newContours = [[]] newContours = [[]]
for i, dis in enumerate(dists): for i, dis in enumerate(dists):
# copy contours which are spread out, delete rest by not copying them # copy contours which are spread out, delete rest by not copying them
if dis > noiseThreashold:
for j in classed[i]: for j in classed[i]:
x, y = mapping[j] x, y = mapping[j]
while x >= len(newContours): while x >= len(newContours):
newContours.append([]) newContours.append([])
while y > len(newContours[x]): while y > len(newContours[x]):
newContours[x].append((None, None, None, None)) newContours[x].append((None, None, None, None))
if dis > noiseThreashold:
newContours[x].append(org[x][y]) newContours[x].append(org[x][y])
self.bounds = newContours self.bounds = newContours

View File

@ -45,9 +45,9 @@ class LayerFactory:
print(f"{int(round(frameNumber/max(data.keys()), 2)*100)}% done with Layer extraction") print(f"{int(round(frameNumber/max(data.keys()), 2)*100)}% done with Layer extraction")
tmp = [[frameNumber, contour] for contour in contours] tmp = [[frameNumber, contour] for contour in contours]
pool.map(self.getLayers, tmp) #pool.map(self.getLayers, tmp)
#for x in tmp: for x in tmp:
#self.getLayers(x) self.getLayers(x)
return self.layers return self.layers
@ -59,20 +59,28 @@ class LayerFactory:
foundLayer = 0 foundLayer = 0
for i in range(0, len(self.layers)): for i in range(0, len(self.layers)):
if foundLayer >= self.config["LayersPerContour"]:
break
if i in self.oldLayerIDs: if i in self.oldLayerIDs:
continue continue
if frameNumber - self.layers[i].lastFrame > self.ttolerance: if frameNumber - self.layers[i].lastFrame > self.ttolerance:
self.oldLayerIDs.append(i) self.oldLayerIDs.append(i)
continue continue
lastXframes = 3
if len(self.layers[i].bounds) < lastXframes:
lastXframes = len(self.layers[i].bounds)
lastBounds = [bound for bounds in self.layers[i].bounds[-lastXframes:] for bound in bounds]
for bounds in self.layers[i].bounds[-1]: for bounds in lastBounds:
if bounds is None or foundLayer >= self.config["LayersPerContour"]: if bounds is None:
break break
(x2,y2,w2,h2) = bounds (x2,y2,w2,h2) = bounds
if self.contoursOverlay((x-tol,y+h+tol), (x+w+tol,y-tol), (x2,y2+h2), (x2+w2,y2)): if self.contoursOverlay((x-tol,y+h+tol), (x+w+tol,y-tol), (x2,y2+h2), (x2+w2,y2)):
self.layers[i].add(frameNumber, (x,y,w,h)) self.layers[i].add(frameNumber, (x,y,w,h))
foundLayer += 1 foundLayer += 1
#break break
if foundLayer == 0: if foundLayer == 0:
self.layers.append(Layer(frameNumber, (x,y,w,h), self.config)) self.layers.append(Layer(frameNumber, (x,y,w,h), self.config))

View File

@ -28,7 +28,7 @@ class LayerManager:
print("'Cleaning' Layers") print("'Cleaning' Layers")
self.freeMin() self.freeMin()
self.sortLayers() self.sortLayers()
self.cleanLayers2() #self.cleanLayers2()
self.freeMax() self.freeMax()
def removeStaticLayers(self): def removeStaticLayers(self):
@ -107,5 +107,8 @@ class LayerManager:
self.layers.sort(key = lambda c:c.startFrame) self.layers.sort(key = lambda c:c.startFrame)
def cleanLayers2(self): def cleanLayers2(self):
#with ThreadPool(16) as pool:
# pool.map(self.getContours, tmpData)
for layer in self.layers: for layer in self.layers:
layer.clusterDelete() layer.clusterDelete()

View File

@ -2,7 +2,7 @@
import cv2 import cv2
import imageio import imageio
import time import time
writer = imageio.get_writer("./x23.mp4", fps=20) writer = imageio.get_writer("./x23.mp4", fps=15)
url = "http://50.227.41.1/mjpg/video.mjpg" url = "http://50.227.41.1/mjpg/video.mjpg"
i = 0 i = 0
@ -20,15 +20,15 @@ while True :
print("Error in cap.read()") # this is for preventing a breaking error print("Error in cap.read()") # this is for preventing a breaking error
# break; # break;
time.sleep(1) time.sleep(1)
continue break
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
writer.append_data(frame) writer.append_data(frame)
i+=1 i+=1
if i > 20*60*60: if i > 20*60*60*2:
break break
except Exception as e: except Exception as e:
print("meh")
cap.release() cap.release()
cv2.destroyAllWindows() cv2.destroyAllWindows()
writer.close() writer.close()

25
main.py
View File

@ -14,22 +14,26 @@ def main():
start = time.time() start = time.time()
config = Config() config = Config()
config["inputPath"] = os.path.join(os.path.dirname(__file__), "generate test footage/Merica-1.m4v") fileName = "3.mp4"
#config["importPath"] = os.path.join(os.path.dirname(__file__), "output/short.txt") outputPath = os.path.join(os.path.dirname(__file__), "output")
config["outputPath"] = os.path.join(os.path.dirname(__file__), "output/shor.mp4") dirName = os.path.join(os.path.dirname(__file__), "generate test footage")
vr = VideoReader(config) config["inputPath"] = os.path.join(dirName, fileName)
config["w"], config["h"] = vr.getWH() config["outputPath"] = os.path.join(outputPath, fileName)
if config["importPath"] is None: config["importPath"] = os.path.join(outputPath, fileName.split(".")[0] + ".txt")
config["w"], config["h"] = VideoReader(config).getWH()
if not os.path.exists(config["importPath"]):
contours = ContourExtractor(config).extractContours() contours = ContourExtractor(config).extractContours()
print("Time consumed extracting: ", time.time() - start) print("Time consumed extracting: ", time.time() - start)
layerFactory = LayerFactory(config) layerFactory = LayerFactory(config)
layers = layerFactory.extractLayers(contours) layers = layerFactory.extractLayers(contours)
else: else:
layers = Importer(config).importRawData() layers, contours = Importer(config).importRawData()
#layerFactory = LayerFactory(config)
#layers = layerFactory.extractLayers(contours)
layerManager = LayerManager(config, layers) layerManager = LayerManager(config, layers)
layerManager.cleanLayers() layerManager.cleanLayers()
@ -37,7 +41,8 @@ def main():
#layerManager.tagLayers() #layerManager.tagLayers()
layers = layerManager.layers layers = layerManager.layers
exporter = Exporter(config) exporter = Exporter(config)
exporter.export(layers, raw=False) print(f"Exporting {len(contours)} Contours and {len(layers)} Layers")
exporter.export(layers, contours, raw=True, overlayed=False)
print("Total time: ", time.time() - start) print("Total time: ", time.time() - start)

Binary file not shown.

BIN
output/out.txt Normal file

Binary file not shown.

Binary file not shown.

BIN
output/x23.txt Normal file

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 311 KiB

After

Width:  |  Height:  |  Size: 313 KiB